and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+//TODO(ms): move to org.eclipse.jgit.ssh.jsch in 6.0
+package org.eclipse.jgit.transport;
+
+import static java.util.stream.Collectors.joining;
+import static java.util.stream.Collectors.toList;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.ConnectException;
+import java.net.UnknownHostException;
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Stream;
+
+import org.eclipse.jgit.errors.TransportException;
+import org.eclipse.jgit.internal.transport.jsch.JSchText;
+import org.eclipse.jgit.util.FS;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.jcraft.jsch.ConfigRepository;
+import com.jcraft.jsch.ConfigRepository.Config;
+import com.jcraft.jsch.HostKey;
+import com.jcraft.jsch.HostKeyRepository;
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.JSchException;
+import com.jcraft.jsch.Session;
+
+/**
+ * The base session factory that loads known hosts and private keys from
+ * $HOME/.ssh
.
+ *
+ * This is the default implementation used by JGit and provides most of the
+ * compatibility necessary to match OpenSSH, a popular implementation of SSH
+ * used by C Git.
+ *
+ * The factory does not provide UI behavior. Override the method
+ * {@link #configure(org.eclipse.jgit.transport.OpenSshConfig.Host, Session)} to
+ * supply appropriate {@link com.jcraft.jsch.UserInfo} to the session.
+ */
+public class JschConfigSessionFactory extends SshSessionFactory {
+
+ private static final String JSCH = "jsch"; //$NON-NLS-1$
+
+ private static final Logger LOG = LoggerFactory
+ .getLogger(JschConfigSessionFactory.class);
+
+ /**
+ * We use different Jsch instances for hosts that have an IdentityFile
+ * configured in ~/.ssh/config. Jsch by default would cache decrypted keys
+ * only per session, which results in repeated password prompts. Using
+ * different Jsch instances, we can cache the keys on these instances so
+ * that they will be re-used for successive sessions, and thus the user is
+ * prompted for a key password only once while Eclipse runs.
+ */
+ private final Map byIdentityFile = new HashMap<>();
+
+ private JSch defaultJSch;
+
+ private OpenSshConfig config;
+
+ /** {@inheritDoc} */
+ @Override
+ public synchronized RemoteSession getSession(URIish uri,
+ CredentialsProvider credentialsProvider, FS fs, int tms)
+ throws TransportException {
+
+ String user = uri.getUser();
+ final String pass = uri.getPass();
+ String host = uri.getHost();
+ int port = uri.getPort();
+
+ try {
+ if (config == null)
+ config = OpenSshConfig.get(fs);
+
+ final OpenSshConfig.Host hc = config.lookup(host);
+ if (port <= 0)
+ port = hc.getPort();
+ if (user == null)
+ user = hc.getUser();
+
+ Session session = createSession(credentialsProvider, fs, user,
+ pass, host, port, hc);
+
+ int retries = 0;
+ while (!session.isConnected()) {
+ try {
+ retries++;
+ session.connect(tms);
+ } catch (JSchException e) {
+ session.disconnect();
+ session = null;
+ // Make sure our known_hosts is not outdated
+ knownHosts(getJSch(hc, fs), fs);
+
+ if (isAuthenticationCanceled(e)) {
+ throw e;
+ } else if (isAuthenticationFailed(e)
+ && credentialsProvider != null) {
+ // if authentication failed maybe credentials changed at
+ // the remote end therefore reset credentials and retry
+ if (retries < 3) {
+ credentialsProvider.reset(uri);
+ session = createSession(credentialsProvider, fs,
+ user, pass, host, port, hc);
+ } else
+ throw e;
+ } else if (retries >= hc.getConnectionAttempts()) {
+ throw e;
+ } else {
+ try {
+ Thread.sleep(1000);
+ session = createSession(credentialsProvider, fs,
+ user, pass, host, port, hc);
+ } catch (InterruptedException e1) {
+ throw new TransportException(
+ JSchText.get().transportSSHRetryInterrupt,
+ e1);
+ }
+ }
+ }
+ }
+
+ return new JschSession(session, uri);
+
+ } catch (JSchException je) {
+ final Throwable c = je.getCause();
+ if (c instanceof UnknownHostException) {
+ throw new TransportException(uri,
+ JSchText.get().unknownHost,
+ je);
+ }
+ if (c instanceof ConnectException) {
+ throw new TransportException(uri, c.getMessage(), je);
+ }
+ throw new TransportException(uri, je.getMessage(), je);
+ }
+
+ }
+
+ @Override
+ public String getType() {
+ return JSCH;
+ }
+
+ private static boolean isAuthenticationFailed(JSchException e) {
+ return e.getCause() == null && e.getMessage().equals("Auth fail"); //$NON-NLS-1$
+ }
+
+ private static boolean isAuthenticationCanceled(JSchException e) {
+ return e.getCause() == null && e.getMessage().equals("Auth cancel"); //$NON-NLS-1$
+ }
+
+ // Package visibility for tests
+ Session createSession(CredentialsProvider credentialsProvider,
+ FS fs, String user, final String pass, String host, int port,
+ final OpenSshConfig.Host hc) throws JSchException {
+ final Session session = createSession(hc, user, host, port, fs);
+ // Jsch will have overridden the explicit user by the one from the SSH
+ // config file...
+ setUserName(session, user);
+ // Jsch will also have overridden the port.
+ if (port > 0 && port != session.getPort()) {
+ session.setPort(port);
+ }
+ // We retry already in getSession() method. JSch must not retry
+ // on its own.
+ session.setConfig("MaxAuthTries", "1"); //$NON-NLS-1$ //$NON-NLS-2$
+ if (pass != null)
+ session.setPassword(pass);
+ final String strictHostKeyCheckingPolicy = hc
+ .getStrictHostKeyChecking();
+ if (strictHostKeyCheckingPolicy != null)
+ session.setConfig("StrictHostKeyChecking", //$NON-NLS-1$
+ strictHostKeyCheckingPolicy);
+ final String pauth = hc.getPreferredAuthentications();
+ if (pauth != null)
+ session.setConfig("PreferredAuthentications", pauth); //$NON-NLS-1$
+ if (credentialsProvider != null
+ && (!hc.isBatchMode() || !credentialsProvider.isInteractive())) {
+ session.setUserInfo(new CredentialsProviderUserInfo(session,
+ credentialsProvider));
+ }
+ safeConfig(session, hc.getConfig());
+ if (hc.getConfig().getValue("HostKeyAlgorithms") == null) { //$NON-NLS-1$
+ setPreferredKeyTypesOrder(session);
+ }
+ configure(hc, session);
+ return session;
+ }
+
+ private void safeConfig(Session session, Config cfg) {
+ // Ensure that Jsch checks all configured algorithms, not just its
+ // built-in ones. Otherwise it may propose an algorithm for which it
+ // doesn't have an implementation, and then run into an NPE if that
+ // algorithm ends up being chosen.
+ copyConfigValueToSession(session, cfg, "Ciphers", "CheckCiphers"); //$NON-NLS-1$ //$NON-NLS-2$
+ copyConfigValueToSession(session, cfg, "KexAlgorithms", "CheckKexes"); //$NON-NLS-1$ //$NON-NLS-2$
+ copyConfigValueToSession(session, cfg, "HostKeyAlgorithms", //$NON-NLS-1$
+ "CheckSignatures"); //$NON-NLS-1$
+ }
+
+ private static void setPreferredKeyTypesOrder(Session session) {
+ HostKeyRepository hkr = session.getHostKeyRepository();
+ HostKey[] hostKeys = hkr.getHostKey(hostName(session), null);
+
+ if (hostKeys == null) {
+ return;
+ }
+
+ List known = Stream.of(hostKeys)
+ .map(HostKey::getType)
+ .collect(toList());
+
+ if (!known.isEmpty()) {
+ String serverHostKey = "server_host_key"; //$NON-NLS-1$
+ String current = session.getConfig(serverHostKey);
+ if (current == null) {
+ session.setConfig(serverHostKey, String.join(",", known)); //$NON-NLS-1$
+ return;
+ }
+
+ String knownFirst = Stream.concat(
+ known.stream(),
+ Stream.of(current.split(",")) //$NON-NLS-1$
+ .filter(s -> !known.contains(s)))
+ .collect(joining(",")); //$NON-NLS-1$
+ session.setConfig(serverHostKey, knownFirst);
+ }
+ }
+
+ private static String hostName(Session s) {
+ if (s.getPort() == SshConstants.SSH_DEFAULT_PORT) {
+ return s.getHost();
+ }
+ return String.format("[%s]:%d", s.getHost(), //$NON-NLS-1$
+ Integer.valueOf(s.getPort()));
+ }
+
+ private void copyConfigValueToSession(Session session, Config cfg,
+ String from, String to) {
+ String value = cfg.getValue(from);
+ if (value != null) {
+ session.setConfig(to, value);
+ }
+ }
+
+ private void setUserName(Session session, String userName) {
+ // Jsch 0.1.54 picks up the user name from the ssh config, even if an
+ // explicit user name was given! We must correct that if ~/.ssh/config
+ // has a different user name.
+ if (userName == null || userName.isEmpty()
+ || userName.equals(session.getUserName())) {
+ return;
+ }
+ try {
+ Class>[] parameterTypes = { String.class };
+ Method method = Session.class.getDeclaredMethod("setUserName", //$NON-NLS-1$
+ parameterTypes);
+ method.setAccessible(true);
+ method.invoke(session, userName);
+ } catch (NullPointerException | IllegalAccessException
+ | IllegalArgumentException | InvocationTargetException
+ | NoSuchMethodException | SecurityException e) {
+ LOG.error(MessageFormat.format(JSchText.get().sshUserNameError,
+ userName, session.getUserName()), e);
+ }
+ }
+
+ /**
+ * Create a new remote session for the requested address.
+ *
+ * @param hc
+ * host configuration
+ * @param user
+ * login to authenticate as.
+ * @param host
+ * server name to connect to.
+ * @param port
+ * port number of the SSH daemon (typically 22).
+ * @param fs
+ * the file system abstraction which will be necessary to
+ * perform certain file system operations.
+ * @return new session instance, but otherwise unconfigured.
+ * @throws com.jcraft.jsch.JSchException
+ * the session could not be created.
+ */
+ protected Session createSession(final OpenSshConfig.Host hc,
+ final String user, final String host, final int port, FS fs)
+ throws JSchException {
+ return getJSch(hc, fs).getSession(user, host, port);
+ }
+
+ /**
+ * Provide additional configuration for the JSch instance. This method could
+ * be overridden to supply a preferred
+ * {@link com.jcraft.jsch.IdentityRepository}.
+ *
+ * @param jsch
+ * jsch instance
+ * @since 4.5
+ */
+ protected void configureJSch(JSch jsch) {
+ // No additional configuration required.
+ }
+
+ /**
+ * Provide additional configuration for the session based on the host
+ * information. This method could be used to supply
+ * {@link com.jcraft.jsch.UserInfo}.
+ *
+ * @param hc
+ * host configuration
+ * @param session
+ * session to configure
+ */
+ protected void configure(OpenSshConfig.Host hc, Session session) {
+ // No additional configuration required.
+ }
+
+ /**
+ * Obtain the JSch used to create new sessions.
+ *
+ * @param hc
+ * host configuration
+ * @param fs
+ * the file system abstraction which will be necessary to
+ * perform certain file system operations.
+ * @return the JSch instance to use.
+ * @throws com.jcraft.jsch.JSchException
+ * the user configuration could not be created.
+ */
+ protected JSch getJSch(OpenSshConfig.Host hc, FS fs) throws JSchException {
+ if (defaultJSch == null) {
+ defaultJSch = createDefaultJSch(fs);
+ if (defaultJSch.getConfigRepository() == null) {
+ defaultJSch.setConfigRepository(
+ new JschBugFixingConfigRepository(config));
+ }
+ for (Object name : defaultJSch.getIdentityNames())
+ byIdentityFile.put((String) name, defaultJSch);
+ }
+
+ final File identityFile = hc.getIdentityFile();
+ if (identityFile == null)
+ return defaultJSch;
+
+ final String identityKey = identityFile.getAbsolutePath();
+ JSch jsch = byIdentityFile.get(identityKey);
+ if (jsch == null) {
+ jsch = new JSch();
+ configureJSch(jsch);
+ if (jsch.getConfigRepository() == null) {
+ jsch.setConfigRepository(defaultJSch.getConfigRepository());
+ }
+ jsch.setHostKeyRepository(defaultJSch.getHostKeyRepository());
+ jsch.addIdentity(identityKey);
+ byIdentityFile.put(identityKey, jsch);
+ }
+ return jsch;
+ }
+
+ /**
+ * Create default instance of jsch
+ *
+ * @param fs
+ * the file system abstraction which will be necessary to perform
+ * certain file system operations.
+ * @return the new default JSch implementation.
+ * @throws com.jcraft.jsch.JSchException
+ * known host keys cannot be loaded.
+ */
+ protected JSch createDefaultJSch(FS fs) throws JSchException {
+ final JSch jsch = new JSch();
+ JSch.setConfig("ssh-rsa", JSch.getConfig("signature.rsa")); //$NON-NLS-1$ //$NON-NLS-2$
+ JSch.setConfig("ssh-dss", JSch.getConfig("signature.dss")); //$NON-NLS-1$ //$NON-NLS-2$
+ configureJSch(jsch);
+ knownHosts(jsch, fs);
+ identities(jsch, fs);
+ return jsch;
+ }
+
+ private static void knownHosts(JSch sch, FS fs) throws JSchException {
+ final File home = fs.userHome();
+ if (home == null)
+ return;
+ final File known_hosts = new File(new File(home, ".ssh"), "known_hosts"); //$NON-NLS-1$ //$NON-NLS-2$
+ try (FileInputStream in = new FileInputStream(known_hosts)) {
+ sch.setKnownHosts(in);
+ } catch (FileNotFoundException none) {
+ // Oh well. They don't have a known hosts in home.
+ } catch (IOException err) {
+ // Oh well. They don't have a known hosts in home.
+ }
+ }
+
+ private static void identities(JSch sch, FS fs) {
+ final File home = fs.userHome();
+ if (home == null)
+ return;
+ final File sshdir = new File(home, ".ssh"); //$NON-NLS-1$
+ if (sshdir.isDirectory()) {
+ loadIdentity(sch, new File(sshdir, "identity")); //$NON-NLS-1$
+ loadIdentity(sch, new File(sshdir, "id_rsa")); //$NON-NLS-1$
+ loadIdentity(sch, new File(sshdir, "id_dsa")); //$NON-NLS-1$
+ }
+ }
+
+ private static void loadIdentity(JSch sch, File priv) {
+ if (priv.isFile()) {
+ try {
+ sch.addIdentity(priv.getAbsolutePath());
+ } catch (JSchException e) {
+ // Instead, pretend the key doesn't exist.
+ }
+ }
+ }
+
+ private static class JschBugFixingConfigRepository
+ implements ConfigRepository {
+
+ private final ConfigRepository base;
+
+ public JschBugFixingConfigRepository(ConfigRepository base) {
+ this.base = base;
+ }
+
+ @Override
+ public Config getConfig(String host) {
+ return new JschBugFixingConfig(base.getConfig(host));
+ }
+
+ /**
+ * A {@link com.jcraft.jsch.ConfigRepository.Config} that transforms
+ * some values from the config file into the format Jsch 0.1.54 expects.
+ * This is a work-around for bugs in Jsch.
+ *
+ * Additionally, this config hides the IdentityFile config entries from
+ * Jsch; we manage those ourselves. Otherwise Jsch would cache passwords
+ * (or rather, decrypted keys) only for a single session, resulting in
+ * multiple password prompts for user operations that use several Jsch
+ * sessions.
+ */
+ private static class JschBugFixingConfig implements Config {
+
+ private static final String[] NO_IDENTITIES = {};
+
+ private final Config real;
+
+ public JschBugFixingConfig(Config delegate) {
+ real = delegate;
+ }
+
+ @Override
+ public String getHostname() {
+ return real.getHostname();
+ }
+
+ @Override
+ public String getUser() {
+ return real.getUser();
+ }
+
+ @Override
+ public int getPort() {
+ return real.getPort();
+ }
+
+ @Override
+ public String getValue(String key) {
+ String k = key.toUpperCase(Locale.ROOT);
+ if ("IDENTITYFILE".equals(k)) { //$NON-NLS-1$
+ return null;
+ }
+ String result = real.getValue(key);
+ if (result != null) {
+ if ("SERVERALIVEINTERVAL".equals(k) //$NON-NLS-1$
+ || "CONNECTTIMEOUT".equals(k)) { //$NON-NLS-1$
+ // These values are in seconds. Jsch 0.1.54 passes them
+ // on as is to java.net.Socket.setSoTimeout(), which
+ // expects milliseconds. So convert here to
+ // milliseconds.
+ try {
+ int timeout = Integer.parseInt(result);
+ result = Long.toString(
+ TimeUnit.SECONDS.toMillis(timeout));
+ } catch (NumberFormatException e) {
+ // Ignore
+ }
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public String[] getValues(String key) {
+ String k = key.toUpperCase(Locale.ROOT);
+ if ("IDENTITYFILE".equals(k)) { //$NON-NLS-1$
+ return NO_IDENTITIES;
+ }
+ return real.getValues(key);
+ }
+ }
+ }
+
+ /**
+ * Set the {@link OpenSshConfig} to use. Intended for use in tests.
+ *
+ * @param config
+ * to use
+ */
+ synchronized void setConfig(OpenSshConfig config) {
+ this.config = config;
+ }
+}
diff --git a/org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/JschSession.java b/org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/JschSession.java
new file mode 100644
index 0000000000..300e03d798
--- /dev/null
+++ b/org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/JschSession.java
@@ -0,0 +1,373 @@
+/*
+ * Copyright (C) 2009, Constantine Plotnikov
+ * Copyright (C) 2008-2009, Google Inc.
+ * Copyright (C) 2009, Google, Inc.
+ * Copyright (C) 2009, JetBrains s.r.o.
+ * Copyright (C) 2008, Robin Rosenberg
+ * Copyright (C) 2008, Shawn O. Pearce and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+//TODO(ms): move to org.eclipse.jgit.ssh.jsch in 6.0
+package org.eclipse.jgit.transport;
+
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jgit.errors.TransportException;
+import org.eclipse.jgit.internal.transport.jsch.JSchText;
+import org.eclipse.jgit.util.io.IsolatedOutputStream;
+
+import com.jcraft.jsch.Channel;
+import com.jcraft.jsch.ChannelExec;
+import com.jcraft.jsch.ChannelSftp;
+import com.jcraft.jsch.JSchException;
+import com.jcraft.jsch.Session;
+import com.jcraft.jsch.SftpException;
+
+/**
+ * Run remote commands using Jsch.
+ *
+ * This class is the default session implementation using Jsch. Note that
+ * {@link org.eclipse.jgit.transport.JschConfigSessionFactory} is used to create
+ * the actual session passed to the constructor.
+ */
+public class JschSession implements RemoteSession {
+ final Session sock;
+ final URIish uri;
+
+ /**
+ * Create a new session object by passing the real Jsch session and the URI
+ * information.
+ *
+ * @param session
+ * the real Jsch session created elsewhere.
+ * @param uri
+ * the URI information for the remote connection
+ */
+ public JschSession(Session session, URIish uri) {
+ sock = session;
+ this.uri = uri;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Process exec(String command, int timeout) throws IOException {
+ return new JschProcess(command, timeout);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void disconnect() {
+ if (sock.isConnected())
+ sock.disconnect();
+ }
+
+ /**
+ * A kludge to allow {@link org.eclipse.jgit.transport.TransportSftp} to get
+ * an Sftp channel from Jsch. Ideally, this method would be generic, which
+ * would require implementing generic Sftp channel operations in the
+ * RemoteSession class.
+ *
+ * @return a channel suitable for Sftp operations.
+ * @throws com.jcraft.jsch.JSchException
+ * on problems getting the channel.
+ * @deprecated since 5.2; use {@link #getFtpChannel()} instead
+ */
+ @Deprecated
+ public Channel getSftpChannel() throws JSchException {
+ return sock.openChannel("sftp"); //$NON-NLS-1$
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 5.2
+ */
+ @Override
+ public FtpChannel getFtpChannel() {
+ return new JschFtpChannel();
+ }
+
+ /**
+ * Implementation of Process for running a single command using Jsch.
+ *
+ * Uses the Jsch session to do actual command execution and manage the
+ * execution.
+ */
+ private class JschProcess extends Process {
+ private ChannelExec channel;
+
+ final int timeout;
+
+ private InputStream inputStream;
+
+ private OutputStream outputStream;
+
+ private InputStream errStream;
+
+ /**
+ * Opens a channel on the session ("sock") for executing the given
+ * command, opens streams, and starts command execution.
+ *
+ * @param commandName
+ * the command to execute
+ * @param tms
+ * the timeout value, in seconds, for the command.
+ * @throws TransportException
+ * on problems opening a channel or connecting to the remote
+ * host
+ * @throws IOException
+ * on problems opening streams
+ */
+ JschProcess(String commandName, int tms)
+ throws TransportException, IOException {
+ timeout = tms;
+ try {
+ channel = (ChannelExec) sock.openChannel("exec"); //$NON-NLS-1$
+ channel.setCommand(commandName);
+ setupStreams();
+ channel.connect(timeout > 0 ? timeout * 1000 : 0);
+ if (!channel.isConnected()) {
+ closeOutputStream();
+ throw new TransportException(uri,
+ JSchText.get().connectionFailed);
+ }
+ } catch (JSchException e) {
+ closeOutputStream();
+ throw new TransportException(uri, e.getMessage(), e);
+ }
+ }
+
+ private void closeOutputStream() {
+ if (outputStream != null) {
+ try {
+ outputStream.close();
+ } catch (IOException ioe) {
+ // ignore
+ }
+ }
+ }
+
+ private void setupStreams() throws IOException {
+ inputStream = channel.getInputStream();
+
+ // JSch won't let us interrupt writes when we use our InterruptTimer
+ // to break out of a long-running write operation. To work around
+ // that we spawn a background thread to shuttle data through a pipe,
+ // as we can issue an interrupted write out of that. Its slower, so
+ // we only use this route if there is a timeout.
+ OutputStream out = channel.getOutputStream();
+ if (timeout <= 0) {
+ outputStream = out;
+ } else {
+ IsolatedOutputStream i = new IsolatedOutputStream(out);
+ outputStream = new BufferedOutputStream(i, 16 * 1024);
+ }
+
+ errStream = channel.getErrStream();
+ }
+
+ @Override
+ public InputStream getInputStream() {
+ return inputStream;
+ }
+
+ @Override
+ public OutputStream getOutputStream() {
+ return outputStream;
+ }
+
+ @Override
+ public InputStream getErrorStream() {
+ return errStream;
+ }
+
+ @Override
+ public int exitValue() {
+ if (isRunning())
+ throw new IllegalStateException();
+ return channel.getExitStatus();
+ }
+
+ private boolean isRunning() {
+ return channel.getExitStatus() < 0 && channel.isConnected();
+ }
+
+ @Override
+ public void destroy() {
+ if (channel.isConnected())
+ channel.disconnect();
+ closeOutputStream();
+ }
+
+ @Override
+ public int waitFor() throws InterruptedException {
+ while (isRunning())
+ Thread.sleep(100);
+ return exitValue();
+ }
+ }
+
+ private class JschFtpChannel implements FtpChannel {
+
+ private ChannelSftp ftp;
+
+ @Override
+ public void connect(int timeout, TimeUnit unit) throws IOException {
+ try {
+ ftp = (ChannelSftp) sock.openChannel("sftp"); //$NON-NLS-1$
+ ftp.connect((int) unit.toMillis(timeout));
+ } catch (JSchException e) {
+ ftp = null;
+ throw new IOException(e.getLocalizedMessage(), e);
+ }
+ }
+
+ @Override
+ public void disconnect() {
+ ftp.disconnect();
+ ftp = null;
+ }
+
+ private T map(Callable op) throws IOException {
+ try {
+ return op.call();
+ } catch (Exception e) {
+ if (e instanceof SftpException) {
+ throw new FtpChannel.FtpException(e.getLocalizedMessage(),
+ ((SftpException) e).id, e);
+ }
+ throw new IOException(e.getLocalizedMessage(), e);
+ }
+ }
+
+ @Override
+ public boolean isConnected() {
+ return ftp != null && sock.isConnected();
+ }
+
+ @Override
+ public void cd(String path) throws IOException {
+ map(() -> {
+ ftp.cd(path);
+ return null;
+ });
+ }
+
+ @Override
+ public String pwd() throws IOException {
+ return map(() -> ftp.pwd());
+ }
+
+ @Override
+ public Collection ls(String path) throws IOException {
+ return map(() -> {
+ List result = new ArrayList<>();
+ for (Object e : ftp.ls(path)) {
+ ChannelSftp.LsEntry entry = (ChannelSftp.LsEntry) e;
+ result.add(new DirEntry() {
+
+ @Override
+ public String getFilename() {
+ return entry.getFilename();
+ }
+
+ @Override
+ public long getModifiedTime() {
+ return entry.getAttrs().getMTime();
+ }
+
+ @Override
+ public boolean isDirectory() {
+ return entry.getAttrs().isDir();
+ }
+ });
+ }
+ return result;
+ });
+ }
+
+ @Override
+ public void rmdir(String path) throws IOException {
+ map(() -> {
+ ftp.rm(path);
+ return null;
+ });
+ }
+
+ @Override
+ public void mkdir(String path) throws IOException {
+ map(() -> {
+ ftp.mkdir(path);
+ return null;
+ });
+ }
+
+ @Override
+ public InputStream get(String path) throws IOException {
+ return map(() -> ftp.get(path));
+ }
+
+ @Override
+ public OutputStream put(String path) throws IOException {
+ return map(() -> ftp.put(path));
+ }
+
+ @Override
+ public void rm(String path) throws IOException {
+ map(() -> {
+ ftp.rm(path);
+ return null;
+ });
+ }
+
+ @Override
+ public void rename(String from, String to) throws IOException {
+ map(() -> {
+ // Plain FTP rename will fail if "to" exists. Jsch knows about
+ // the FTP extension "posix-rename@openssh.com", which will
+ // remove "to" first if it exists.
+ if (hasPosixRename()) {
+ ftp.rename(from, to);
+ } else if (!to.equals(from)) {
+ // Try to remove "to" first. With git, we typically get this
+ // when a lock file is moved over the file locked. Note that
+ // the check for to being equal to from may still fail in
+ // the general case, but for use with JGit's TransportSftp
+ // it should be good enough.
+ delete(to);
+ ftp.rename(from, to);
+ }
+ return null;
+ });
+ }
+
+ /**
+ * Determine whether the server has the posix-rename extension.
+ *
+ * @return {@code true} if it is supported, {@code false} otherwise
+ * @see OpenSSH
+ * deviations and extensions to the published SSH protocol
+ * @see stdio.h:
+ * rename()
+ */
+ private boolean hasPosixRename() {
+ return "1".equals(ftp.getExtension("posix-rename@openssh.com")); //$NON-NLS-1$//$NON-NLS-2$
+ }
+ }
+}
diff --git a/org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/OpenSshConfig.java b/org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/OpenSshConfig.java
new file mode 100644
index 0000000000..5c6c80c768
--- /dev/null
+++ b/org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/OpenSshConfig.java
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2008, 2018, Google Inc. and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+//TODO(ms): move to org.eclipse.jgit.ssh.jsch in 6.0
+package org.eclipse.jgit.transport;
+
+import static org.eclipse.jgit.internal.transport.ssh.OpenSshConfigFile.positive;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.eclipse.jgit.internal.transport.ssh.OpenSshConfigFile;
+import org.eclipse.jgit.internal.transport.ssh.OpenSshConfigFile.HostEntry;
+import org.eclipse.jgit.util.FS;
+
+import com.jcraft.jsch.ConfigRepository;
+
+/**
+ * Fairly complete configuration parser for the OpenSSH ~/.ssh/config file.
+ *
+ * JSch does have its own config file parser
+ * {@link com.jcraft.jsch.OpenSSHConfig} since version 0.1.50, but it has a
+ * number of problems:
+ *
+ * - it splits lines of the format "keyword = value" wrongly: you'd end up
+ * with the value "= value".
+ *
- its "Host" keyword is not case insensitive.
+ *
- it doesn't handle quoted values.
+ *
- JSch's OpenSSHConfig doesn't monitor for config file changes.
+ *
+ *
+ * This parser makes the critical options available to
+ * {@link org.eclipse.jgit.transport.SshSessionFactory} via
+ * {@link org.eclipse.jgit.transport.OpenSshConfig.Host} objects returned
+ * by {@link #lookup(String)}, and implements a fully conforming
+ * {@link com.jcraft.jsch.ConfigRepository} providing
+ * {@link com.jcraft.jsch.ConfigRepository.Config}s via
+ * {@link #getConfig(String)}.
+ *
+ *
+ * @see OpenSshConfigFile
+ */
+public class OpenSshConfig implements ConfigRepository {
+
+ /**
+ * Obtain the user's configuration data.
+ *
+ * The configuration file is always returned to the caller, even if no file
+ * exists in the user's home directory at the time the call was made. Lookup
+ * requests are cached and are automatically updated if the user modifies
+ * the configuration file since the last time it was cached.
+ *
+ * @param fs
+ * the file system abstraction which will be necessary to
+ * perform certain file system operations.
+ * @return a caching reader of the user's configuration file.
+ */
+ public static OpenSshConfig get(FS fs) {
+ File home = fs.userHome();
+ if (home == null)
+ home = new File(".").getAbsoluteFile(); //$NON-NLS-1$
+
+ final File config = new File(new File(home, SshConstants.SSH_DIR),
+ SshConstants.CONFIG);
+ return new OpenSshConfig(home, config);
+ }
+
+ /** The base file. */
+ private OpenSshConfigFile configFile;
+
+ OpenSshConfig(File h, File cfg) {
+ configFile = new OpenSshConfigFile(h, cfg,
+ SshSessionFactory.getLocalUserName());
+ }
+
+ /**
+ * Locate the configuration for a specific host request.
+ *
+ * @param hostName
+ * the name the user has supplied to the SSH tool. This may be a
+ * real host name, or it may just be a "Host" block in the
+ * configuration file.
+ * @return r configuration for the requested name. Never null.
+ */
+ public Host lookup(String hostName) {
+ HostEntry entry = configFile.lookup(hostName, -1, null);
+ return new Host(entry, hostName, configFile.getLocalUserName());
+ }
+
+ /**
+ * Configuration of one "Host" block in the configuration file.
+ *
+ * If returned from {@link OpenSshConfig#lookup(String)} some or all of the
+ * properties may not be populated. The properties which are not populated
+ * should be defaulted by the caller.
+ *
+ * When returned from {@link OpenSshConfig#lookup(String)} any wildcard
+ * entries which appear later in the configuration file will have been
+ * already merged into this block.
+ */
+ public static class Host {
+ String hostName;
+
+ int port;
+
+ File identityFile;
+
+ String user;
+
+ String preferredAuthentications;
+
+ Boolean batchMode;
+
+ String strictHostKeyChecking;
+
+ int connectionAttempts;
+
+ private HostEntry entry;
+
+ private Config config;
+
+ // See com.jcraft.jsch.OpenSSHConfig. Translates some command-line keys
+ // to ssh-config keys.
+ private static final Map KEY_MAP = new TreeMap<>(
+ String.CASE_INSENSITIVE_ORDER);
+
+ static {
+ KEY_MAP.put("kex", SshConstants.KEX_ALGORITHMS); //$NON-NLS-1$
+ KEY_MAP.put("server_host_key", SshConstants.HOST_KEY_ALGORITHMS); //$NON-NLS-1$
+ KEY_MAP.put("cipher.c2s", SshConstants.CIPHERS); //$NON-NLS-1$
+ KEY_MAP.put("cipher.s2c", SshConstants.CIPHERS); //$NON-NLS-1$
+ KEY_MAP.put("mac.c2s", SshConstants.MACS); //$NON-NLS-1$
+ KEY_MAP.put("mac.s2c", SshConstants.MACS); //$NON-NLS-1$
+ KEY_MAP.put("compression.s2c", SshConstants.COMPRESSION); //$NON-NLS-1$
+ KEY_MAP.put("compression.c2s", SshConstants.COMPRESSION); //$NON-NLS-1$
+ KEY_MAP.put("compression_level", "CompressionLevel"); //$NON-NLS-1$ //$NON-NLS-2$
+ KEY_MAP.put("MaxAuthTries", //$NON-NLS-1$
+ SshConstants.NUMBER_OF_PASSWORD_PROMPTS);
+ }
+
+ private static String mapKey(String key) {
+ String k = KEY_MAP.get(key);
+ return k != null ? k : key;
+ }
+
+ /**
+ * Creates a new uninitialized {@link Host}.
+ */
+ public Host() {
+ // For API backwards compatibility with pre-4.9 JGit
+ }
+
+ Host(HostEntry entry, String hostName, String localUserName) {
+ this.entry = entry;
+ complete(hostName, localUserName);
+ }
+
+ /**
+ * @return the value StrictHostKeyChecking property, the valid values
+ * are "yes" (unknown hosts are not accepted), "no" (unknown
+ * hosts are always accepted), and "ask" (user should be asked
+ * before accepting the host)
+ */
+ public String getStrictHostKeyChecking() {
+ return strictHostKeyChecking;
+ }
+
+ /**
+ * @return the real IP address or host name to connect to; never null.
+ */
+ public String getHostName() {
+ return hostName;
+ }
+
+ /**
+ * @return the real port number to connect to; never 0.
+ */
+ public int getPort() {
+ return port;
+ }
+
+ /**
+ * @return path of the private key file to use for authentication; null
+ * if the caller should use default authentication strategies.
+ */
+ public File getIdentityFile() {
+ return identityFile;
+ }
+
+ /**
+ * @return the real user name to connect as; never null.
+ */
+ public String getUser() {
+ return user;
+ }
+
+ /**
+ * @return the preferred authentication methods, separated by commas if
+ * more than one authentication method is preferred.
+ */
+ public String getPreferredAuthentications() {
+ return preferredAuthentications;
+ }
+
+ /**
+ * @return true if batch (non-interactive) mode is preferred for this
+ * host connection.
+ */
+ public boolean isBatchMode() {
+ return batchMode != null && batchMode.booleanValue();
+ }
+
+ /**
+ * @return the number of tries (one per second) to connect before
+ * exiting. The argument must be an integer. This may be useful
+ * in scripts if the connection sometimes fails. The default is
+ * 1.
+ * @since 3.4
+ */
+ public int getConnectionAttempts() {
+ return connectionAttempts;
+ }
+
+
+ private void complete(String initialHostName, String localUserName) {
+ // Try to set values from the options.
+ hostName = entry.getValue(SshConstants.HOST_NAME);
+ user = entry.getValue(SshConstants.USER);
+ port = positive(entry.getValue(SshConstants.PORT));
+ connectionAttempts = positive(
+ entry.getValue(SshConstants.CONNECTION_ATTEMPTS));
+ strictHostKeyChecking = entry
+ .getValue(SshConstants.STRICT_HOST_KEY_CHECKING);
+ batchMode = Boolean.valueOf(OpenSshConfigFile
+ .flag(entry.getValue(SshConstants.BATCH_MODE)));
+ preferredAuthentications = entry
+ .getValue(SshConstants.PREFERRED_AUTHENTICATIONS);
+ // Fill in defaults if still not set
+ if (hostName == null || hostName.isEmpty()) {
+ hostName = initialHostName;
+ }
+ if (user == null || user.isEmpty()) {
+ user = localUserName;
+ }
+ if (port <= 0) {
+ port = SshConstants.SSH_DEFAULT_PORT;
+ }
+ if (connectionAttempts <= 0) {
+ connectionAttempts = 1;
+ }
+ List identityFiles = entry
+ .getValues(SshConstants.IDENTITY_FILE);
+ if (identityFiles != null && !identityFiles.isEmpty()) {
+ identityFile = new File(identityFiles.get(0));
+ }
+ }
+
+ Config getConfig() {
+ if (config == null) {
+ config = new Config() {
+
+ @Override
+ public String getHostname() {
+ return Host.this.getHostName();
+ }
+
+ @Override
+ public String getUser() {
+ return Host.this.getUser();
+ }
+
+ @Override
+ public int getPort() {
+ return Host.this.getPort();
+ }
+
+ @Override
+ public String getValue(String key) {
+ // See com.jcraft.jsch.OpenSSHConfig.MyConfig.getValue()
+ // for this special case.
+ if (key.equals("compression.s2c") //$NON-NLS-1$
+ || key.equals("compression.c2s")) { //$NON-NLS-1$
+ if (!OpenSshConfigFile.flag(
+ Host.this.entry.getValue(mapKey(key)))) {
+ return "none,zlib@openssh.com,zlib"; //$NON-NLS-1$
+ }
+ return "zlib@openssh.com,zlib,none"; //$NON-NLS-1$
+ }
+ return Host.this.entry.getValue(mapKey(key));
+ }
+
+ @Override
+ public String[] getValues(String key) {
+ List values = Host.this.entry
+ .getValues(mapKey(key));
+ if (values == null) {
+ return new String[0];
+ }
+ return values.toArray(new String[0]);
+ }
+ };
+ }
+ return config;
+ }
+
+ @Override
+ @SuppressWarnings("nls")
+ public String toString() {
+ return "Host [hostName=" + hostName + ", port=" + port
+ + ", identityFile=" + identityFile + ", user=" + user
+ + ", preferredAuthentications=" + preferredAuthentications
+ + ", batchMode=" + batchMode + ", strictHostKeyChecking="
+ + strictHostKeyChecking + ", connectionAttempts="
+ + connectionAttempts + ", entry=" + entry + "]";
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * Retrieves the full {@link com.jcraft.jsch.ConfigRepository.Config Config}
+ * for the given host name. Should be called only by Jsch and tests.
+ *
+ * @since 4.9
+ */
+ @Override
+ public Config getConfig(String hostName) {
+ Host host = lookup(hostName);
+ return host.getConfig();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String toString() {
+ return "OpenSshConfig [configFile=" + configFile + ']'; //$NON-NLS-1$
+ }
+}
diff --git a/org.eclipse.jgit.test/.classpath b/org.eclipse.jgit.test/.classpath
index 7cc18cca34..c99a7b0d34 100644
--- a/org.eclipse.jgit.test/.classpath
+++ b/org.eclipse.jgit.test/.classpath
@@ -1,22 +1,21 @@
-
+
-
+
-
+
-
diff --git a/org.eclipse.jgit.test/BUILD b/org.eclipse.jgit.test/BUILD
index cd6195e287..f12646e859 100644
--- a/org.eclipse.jgit.test/BUILD
+++ b/org.eclipse.jgit.test/BUILD
@@ -58,7 +58,6 @@ java_library(
resources = DATA,
deps = [
"//lib:assertj-core",
- "//lib:jsch",
"//lib:junit",
"//lib:mockito",
"//lib:slf4j-simple",
@@ -67,27 +66,6 @@ java_library(
],
)
-java_library(
- name = "sshd-helpers",
- testonly = 1,
- srcs = glob(["src/org/eclipse/jgit/transport/ssh/*.java"]),
- resource_strip_prefix = "org.eclipse.jgit.test/resources",
- resources = RESOURCES,
- visibility = [
- "//org.eclipse.jgit.gpg.bc.test:__pkg__",
- "//org.eclipse.jgit.ssh.apache.test:__pkg__",
- ],
- deps = [
- "//lib:jsch",
- "//lib:junit",
- "//lib:sshd-osgi",
- "//lib:sshd-sftp",
- "//org.eclipse.jgit:jgit",
- "//org.eclipse.jgit.junit:junit",
- "//org.eclipse.jgit.junit.ssh:junit-ssh",
- ],
-)
-
java_import(
name = "tst_rsrc",
jars = [":tst_rsrc_jar"],
diff --git a/org.eclipse.jgit.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.test/META-INF/MANIFEST.MF
index eda4505264..be3897ff68 100644
--- a/org.eclipse.jgit.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.test/META-INF/MANIFEST.MF
@@ -6,10 +6,8 @@ Bundle-SymbolicName: org.eclipse.jgit.test
Bundle-Version: 5.8.0.qualifier
Bundle-Localization: plugin
Bundle-Vendor: %Bundle-Vendor
-Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)",
- com.jcraft.jsch;version="[0.1.54,0.2.0)",
net.bytebuddy.dynamic.loading;version="[1.9.0,2.0.0)",
org.apache.commons.compress.archivers;version="[1.15.0,2.0)",
org.apache.commons.compress.archivers.tar;version="[1.15.0,2.0)",
@@ -46,7 +44,6 @@ Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)",
org.eclipse.jgit.internal.transport.http;version="[5.8.0,5.9.0)",
org.eclipse.jgit.internal.transport.parser;version="[5.8.0,5.9.0)",
org.eclipse.jgit.junit;version="[5.8.0,5.9.0)",
- org.eclipse.jgit.junit.ssh;version="[5.8.0,5.9.0)",
org.eclipse.jgit.junit.time;version="[5.8.0,5.9.0)",
org.eclipse.jgit.lfs;version="[5.8.0,5.9.0)",
org.eclipse.jgit.lib;version="[5.8.0,5.9.0)",
@@ -86,4 +83,3 @@ Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)",
org.tukaani.xz;version="[1.6.0,2.0)"
Require-Bundle: org.hamcrest.core;bundle-version="[1.1.0,2.0.0)",
org.hamcrest.library;bundle-version="[1.1.0,2.0.0)"
-Export-Package: org.eclipse.jgit.transport.ssh;version="5.8.0";x-friends:="org.eclipse.jgit.ssh.apache.test"
diff --git a/org.eclipse.jgit.test/build.properties b/org.eclipse.jgit.test/build.properties
index 78c8f55f3a..7dc26c0b0d 100644
--- a/org.eclipse.jgit.test/build.properties
+++ b/org.eclipse.jgit.test/build.properties
@@ -1,8 +1,7 @@
source.. = tst/,\
tst-rsrc/,\
exttst/,\
- src/,\
- resources/
+ src/
bin.includes = META-INF/,\
.,\
plugin.properties,\
diff --git a/org.eclipse.jgit.test/pom.xml b/org.eclipse.jgit.test/pom.xml
index 377938b463..fa9bac8507 100644
--- a/org.eclipse.jgit.test/pom.xml
+++ b/org.eclipse.jgit.test/pom.xml
@@ -149,9 +149,6 @@
plugin.properties
-
- resources/
-
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_dsa b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_dsa
deleted file mode 100644
index f097516df2..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_dsa
+++ /dev/null
@@ -1,12 +0,0 @@
------BEGIN DSA PRIVATE KEY-----
-MIIBuwIBAAKBgQC+mJEX/XBloWhNM+BEuoh5z+EAuZfVyJ8cHNKlQmC1sWrENKGh
-P8ZhzWeHW0A7JnvTQgMqW6yD4mDzCpbR1wEz5KeXAphEjCGPnRik7Q4RjpZTd6Nq
-nNF/CYYGYuwR7ZGUPITTpKJWgX6NkEk+a4tvTWP7xfxOq5iKIspFEhEOlQIVAIBi
-TdAR8M2twrXZdspBjdJprjDXAoGAOrRYdXRHhpsOewIi9GQah0lde7AVrmZawK9Z
-BwhDUagL58gS8PvcsNNVhS2dKEX45pqZmgayt2UEE/5bke3+CdZtStDsezBYMu8P
-I/0qjOULhl7xLJT5ayCIN2ZuvcH8vtqH89fXgZkIz0c68AzY1ZFjJPc+TdE0puI9
-3mMVRaoCgYEAslyMZiOwYA3oiFMQTJEphKdgejWsjqQ9LoKppfZ3d4Jj1V3tgI1s
-/wHfoneUUrUwM+sMHZKXbBDLWWQUOSIxDYcXKDkbZ1FlmhvJR+45D2LyLKjEnjVD
-lQCwYly4P26zXqciZS7k3H/DjiHtAPUeoHm9IYb1A03K8Bd/xW0guMcCFFeUfQeX
-3mFPCfKJ5uXMjkPUqIo/
------END DSA PRIVATE KEY-----
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_dsa.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_dsa.pub
deleted file mode 100644
index 676685332e..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_dsa.pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-dss AAAAB3NzaC1kc3MAAACBAL6YkRf9cGWhaE0z4ES6iHnP4QC5l9XInxwc0qVCYLWxasQ0oaE/xmHNZ4dbQDsme9NCAypbrIPiYPMKltHXATPkp5cCmESMIY+dGKTtDhGOllN3o2qc0X8JhgZi7BHtkZQ8hNOkolaBfo2QST5ri29NY/vF/E6rmIoiykUSEQ6VAAAAFQCAYk3QEfDNrcK12XbKQY3Saa4w1wAAAIA6tFh1dEeGmw57AiL0ZBqHSV17sBWuZlrAr1kHCENRqAvnyBLw+9yw01WFLZ0oRfjmmpmaBrK3ZQQT/luR7f4J1m1K0Ox7MFgy7w8j/SqM5QuGXvEslPlrIIg3Zm69wfy+2ofz19eBmQjPRzrwDNjVkWMk9z5N0TSm4j3eYxVFqgAAAIEAslyMZiOwYA3oiFMQTJEphKdgejWsjqQ9LoKppfZ3d4Jj1V3tgI1s/wHfoneUUrUwM+sMHZKXbBDLWWQUOSIxDYcXKDkbZ1FlmhvJR+45D2LyLKjEnjVDlQCwYly4P26zXqciZS7k3H/DjiHtAPUeoHm9IYb1A03K8Bd/xW0guMc= testuser
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_dsa_testpass b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_dsa_testpass
deleted file mode 100644
index 375d38fe43..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_dsa_testpass
+++ /dev/null
@@ -1,15 +0,0 @@
------BEGIN DSA PRIVATE KEY-----
-Proc-Type: 4,ENCRYPTED
-DEK-Info: AES-128-CBC,EBB6ACAA4F1FC558865344E3C2B91A5F
-
-CWMAq20YBO8ueHnmQ7IaKa7ISEvNbwbzqoBIxor6TZYSU3JvlIf5AL2UvGpMJDk1
-fyROdCjdVAeWKQC0peU54D3YnD3am4gZlrclPMjMRnjBmqO+vnU7bTudIt/8y6vg
-gmHZki0/aceQ6QvGwGrxBezBPaK4Bc926lePujHHE/PbtuQgkBw7rhIBGKVuy0qN
-sFbC4AGnYl5tudy5RLvCcpQvpDCjnYAfGQVimRYSOsaOwTEBvsnQFUH1pqQAYLC4
-Capo1yj6Q0smzwsGoyFSvmPkyzLbMTT42m+M48gc5nuaOkbU5absqOb8cQgRVmWB
-W1HnpufqGtyF6vBK+qlzg157bhQDYMwZuubX+IrTRL67djBiSIpiRDZduJavT3zq
-iSrRGSnjnkhp4NxtJJjprDQe4VAZEccN5GWPjClbogjpsG+fmTJiNDMI88L11DrV
-Vjeaxsql31iur/xGwvmBYd+/V+Nu4v7kA4XViO/3ZIpqi8qvQ3si5hbALSX0OPnm
-9q0eMp9qfmzPvbmysq2BEenBaZDwEWYTYpcF23pjwc1EvmfP8EAYT+xH95ZhxVmc
-Sujq0VyGeIhy7+gRHZo2Fg==
------END DSA PRIVATE KEY-----
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_dsa_testpass.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_dsa_testpass.pub
deleted file mode 100644
index 676685332e..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_dsa_testpass.pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-dss AAAAB3NzaC1kc3MAAACBAL6YkRf9cGWhaE0z4ES6iHnP4QC5l9XInxwc0qVCYLWxasQ0oaE/xmHNZ4dbQDsme9NCAypbrIPiYPMKltHXATPkp5cCmESMIY+dGKTtDhGOllN3o2qc0X8JhgZi7BHtkZQ8hNOkolaBfo2QST5ri29NY/vF/E6rmIoiykUSEQ6VAAAAFQCAYk3QEfDNrcK12XbKQY3Saa4w1wAAAIA6tFh1dEeGmw57AiL0ZBqHSV17sBWuZlrAr1kHCENRqAvnyBLw+9yw01WFLZ0oRfjmmpmaBrK3ZQQT/luR7f4J1m1K0Ox7MFgy7w8j/SqM5QuGXvEslPlrIIg3Zm69wfy+2ofz19eBmQjPRzrwDNjVkWMk9z5N0TSm4j3eYxVFqgAAAIEAslyMZiOwYA3oiFMQTJEphKdgejWsjqQ9LoKppfZ3d4Jj1V3tgI1s/wHfoneUUrUwM+sMHZKXbBDLWWQUOSIxDYcXKDkbZ1FlmhvJR+45D2LyLKjEnjVDlQCwYly4P26zXqciZS7k3H/DjiHtAPUeoHm9IYb1A03K8Bd/xW0guMc= testuser
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_256 b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_256
deleted file mode 100644
index 8a4c864afa..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_256
+++ /dev/null
@@ -1,5 +0,0 @@
------BEGIN EC PRIVATE KEY-----
-MHcCAQEEIAqXVKoLNr7/wNluxmGZnZmJCD/5h06ptAICRk+8FIjfoAoGCCqGSM49
-AwEHoUQDQgAEoQHTUWwu3nJnCHeSv3YE59UxfuGNjAXLzK0MjDwoXt6/qePjjKAQ
-ehHdAIYQHr9zYJu5SA5b86HL5glqjcy+Pg==
------END EC PRIVATE KEY-----
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_256.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_256.pub
deleted file mode 100644
index 43540ec0ec..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_256.pub
+++ /dev/null
@@ -1 +0,0 @@
-ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKEB01FsLt5yZwh3kr92BOfVMX7hjYwFy8ytDIw8KF7ev6nj44ygEHoR3QCGEB6/c2CbuUgOW/Ohy+YJao3Mvj4= testuser
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_256_testpass b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_256_testpass
deleted file mode 100644
index b767c8e99a..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_256_testpass
+++ /dev/null
@@ -1,8 +0,0 @@
------BEGIN EC PRIVATE KEY-----
-Proc-Type: 4,ENCRYPTED
-DEK-Info: AES-128-CBC,86940587F5C93441B585F469FF31AC06
-
-LaIyzOCeBPJA6OkFOFnFfVorYO+Rm1g5QpvqEcFZ+FCuEvhMZN00NMZ5hHKvwQLt
-XSK5Se8MUD+e6qFH/ZcoYTixUqYjYJlOkxJzKaXg5nM82wQHa1LqQqcL4IDrJmzv
-qJbCLtl6XOfkQQUA6gezqhtiNYWLDZIPfZ0dsaIB/fU=
------END EC PRIVATE KEY-----
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_256_testpass.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_256_testpass.pub
deleted file mode 100644
index 43540ec0ec..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_256_testpass.pub
+++ /dev/null
@@ -1 +0,0 @@
-ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKEB01FsLt5yZwh3kr92BOfVMX7hjYwFy8ytDIw8KF7ev6nj44ygEHoR3QCGEB6/c2CbuUgOW/Ohy+YJao3Mvj4= testuser
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_384 b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_384
deleted file mode 100644
index dc2ac86508..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_384
+++ /dev/null
@@ -1,6 +0,0 @@
------BEGIN EC PRIVATE KEY-----
-MIGkAgEBBDAgAgPcgkPaitxOrphrrLe+am0eUhYi346UUTnb5WZL3164MEjFByd9
-Egv6KwB4hCqgBwYFK4EEACKhZANiAAQhJrJ+vJLbkbd9C1he+4XuxaOyZ1IqYJqz
-PZCXcKkIlgy+0I07RAxRUd75GHKc4ViyUnLq5odV25H6FNzHJHO7ifE4H6jrEpA/
-UL6LkfZReYZ4sNmeQI7MBXm2IXQsIZ4=
------END EC PRIVATE KEY-----
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_384.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_384.pub
deleted file mode 100644
index 3e813a5e48..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_384.pub
+++ /dev/null
@@ -1 +0,0 @@
-ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBCEmsn68ktuRt30LWF77he7Fo7JnUipgmrM9kJdwqQiWDL7QjTtEDFFR3vkYcpzhWLJScurmh1XbkfoU3Mckc7uJ8TgfqOsSkD9QvouR9lF5hniw2Z5AjswFebYhdCwhng== testuser
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_384_testpass b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_384_testpass
deleted file mode 100644
index 06032d049f..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_384_testpass
+++ /dev/null
@@ -1,9 +0,0 @@
------BEGIN EC PRIVATE KEY-----
-Proc-Type: 4,ENCRYPTED
-DEK-Info: AES-128-CBC,80B1C4D6D9B45690A07B9886050C63A7
-
-WxS7EGs77p1aPZuxXW0G/yTFKAh4M30AaeGQBPjDR/HTAmPJe3irDH56fdmGhY4+
-zBT+6X1VppB+UqB0nJ/qHq7FeA37eJPXJnuskPh2BzLlBaVhmEnzZylEW33gzAuH
-XzC/Z2OjdWRjn+rBXM5fwo9IIC0WzTNpBokdeMo8tpnPzGTlsTFeyVgMZJ3wOlCO
-4ItX9ddY5P+MrLzWP672IyZZqAQGfLec4YoJ286wpHY=
------END EC PRIVATE KEY-----
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_384_testpass.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_384_testpass.pub
deleted file mode 100644
index 3e813a5e48..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_384_testpass.pub
+++ /dev/null
@@ -1 +0,0 @@
-ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBCEmsn68ktuRt30LWF77he7Fo7JnUipgmrM9kJdwqQiWDL7QjTtEDFFR3vkYcpzhWLJScurmh1XbkfoU3Mckc7uJ8TgfqOsSkD9QvouR9lF5hniw2Z5AjswFebYhdCwhng== testuser
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_521 b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_521
deleted file mode 100644
index c28151e5ab..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_521
+++ /dev/null
@@ -1,7 +0,0 @@
------BEGIN EC PRIVATE KEY-----
-MIHcAgEBBEIB4zI/MCFSfJ0wfyLwZPxG1vP2o3fF7fEuOTpK+fxbDHKYz6r4bNv3
-HkPQEVTIAqDl7r5Ebcx0BMeYr9oe69tPZIigBwYFK4EEACOhgYkDgYYABAChltEM
-zT8dXwIhQD2iuy7QbaBkhWMhpFaxztvzSQqoTZvBgBsOmSr9frFA93lSQoHD1Bge
-wuwBkNGm9lRcw0tEgABqifONkj07Qj2847MKS1iiVu1sHh7Ys3YimyfJc+nZRNi+
-W03nkcdvWd6PP8y/VENoV7+BtIO9txj8Dt5LYOtFgw==
------END EC PRIVATE KEY-----
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_521.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_521.pub
deleted file mode 100644
index 9bac1e80f0..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_521.pub
+++ /dev/null
@@ -1 +0,0 @@
-ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAChltEMzT8dXwIhQD2iuy7QbaBkhWMhpFaxztvzSQqoTZvBgBsOmSr9frFA93lSQoHD1BgewuwBkNGm9lRcw0tEgABqifONkj07Qj2847MKS1iiVu1sHh7Ys3YimyfJc+nZRNi+W03nkcdvWd6PP8y/VENoV7+BtIO9txj8Dt5LYOtFgw== testuser
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_521_testpass b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_521_testpass
deleted file mode 100644
index c1c1bbaced..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_521_testpass
+++ /dev/null
@@ -1,10 +0,0 @@
------BEGIN EC PRIVATE KEY-----
-Proc-Type: 4,ENCRYPTED
-DEK-Info: AES-128-CBC,7070032284B3C310353B8C352AB2D8CE
-
-UBgXTwobcLX1VFtQaLNiwwVzdN1+TlmhSRCnU+kv2EpunXxfvyOVS1mZTam9NyhE
-O0Mc7REi5hDHp8UYM7MP+wrwK+QM3D2Vm2/Rh0+acd4Gu2XGACJHWXGIyKwNsU0R
-ZddusHIi+979sHw3vSUFCvuDwc9YZBoujpzls7NYEWXiAVv6wd1RCtAynkBk/uvc
-1F7iHLuRttejBPvrb/a2AxY0pFpCuCVmGjuiS5bfVWBj7xLEplqdU6/95rd9pRwx
-e2uRlU0AFiQGNPStfhjgfCWnmf+aX3vAgVqkLMYKYQE=
------END EC PRIVATE KEY-----
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_521_testpass.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_521_testpass.pub
deleted file mode 100644
index 9bac1e80f0..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_521_testpass.pub
+++ /dev/null
@@ -1 +0,0 @@
-ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAChltEMzT8dXwIhQD2iuy7QbaBkhWMhpFaxztvzSQqoTZvBgBsOmSr9frFA93lSQoHD1BgewuwBkNGm9lRcw0tEgABqifONkj07Qj2847MKS1iiVu1sHh7Ys3YimyfJc+nZRNi+W03nkcdvWd6PP8y/VENoV7+BtIO9txj8Dt5LYOtFgw== testuser
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ed25519 b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ed25519
deleted file mode 100644
index 02afa54788..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ed25519
+++ /dev/null
@@ -1,7 +0,0 @@
------BEGIN OPENSSH PRIVATE KEY-----
-b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
-QyNTUxOQAAACBIJlrW8XB46iAVY0XqbjYKG8wJ95iILxOb5ONQhFBvPQAAAJC8jORLvIzk
-SwAAAAtzc2gtZWQyNTUxOQAAACBIJlrW8XB46iAVY0XqbjYKG8wJ95iILxOb5ONQhFBvPQ
-AAAECjklggj+glO2K60Ptg+aXYGBdvXtk9TQnKINhrEIxW9UgmWtbxcHjqIBVjRepuNgob
-zAn3mIgvE5vk41CEUG89AAAACHRlc3R1c2VyAQIDBAU=
------END OPENSSH PRIVATE KEY-----
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ed25519.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ed25519.pub
deleted file mode 100644
index 7857db5602..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ed25519.pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEgmWtbxcHjqIBVjRepuNgobzAn3mIgvE5vk41CEUG89 testuser
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ed25519_expensive_testpass b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ed25519_expensive_testpass
deleted file mode 100644
index 904cf302c2..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ed25519_expensive_testpass
+++ /dev/null
@@ -1,8 +0,0 @@
------BEGIN OPENSSH PRIVATE KEY-----
-b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABAsFN8vig
-Nw4/Ow6xbb7MAZAAABAAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIEZXZRjuttLufaP8
-wFD/i4lYPnKk01z46Jwv/9U4mPioAAAAkHLErPaXeC179rzXMaSwClstzsKvJ/Gqh2cY8d
-cWzymXtKZcivWMKesRHbC+1qRx53ofx15IzT5Fmg6NuNk4sm2s+lH8x8HN3CPWBfjGIelP
-iQUR6M6Y91mPigpRC2HUJmJIaFNdrRqFF84a5+qyK//tdy1fv4gNMLi5yPdXiL/Ttw05FS
-LkFikjfvSGZSO/MA==
------END OPENSSH PRIVATE KEY-----
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ed25519_expensive_testpass.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ed25519_expensive_testpass.pub
deleted file mode 100644
index 65038b5f4c..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ed25519_expensive_testpass.pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEZXZRjuttLufaP8wFD/i4lYPnKk01z46Jwv/9U4mPio test
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ed25519_testpass b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ed25519_testpass
deleted file mode 100644
index 7ad4a77056..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ed25519_testpass
+++ /dev/null
@@ -1,8 +0,0 @@
------BEGIN OPENSSH PRIVATE KEY-----
-b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABA4hLhtuV
-MNBBC+j45F4KFcAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIEgmWtbxcHjqIBVj
-RepuNgobzAn3mIgvE5vk41CEUG89AAAAkPH343T+NbHb05J/6CHnF9h7C11LJDHe2x9+HC
-dNB50fP9M+KJ/cC5cqIeHm8y0fg+wX2WLlJPjNVoSd5MciWCfUWO0k32ciVpoyrGCz5Gh6
-axKVVY42QjdgO0S2QxWClnAuMdkVdl2ke/PcGp4yqTTIruAAB0m3d0jZdKNT1Vziww0rQB
-+DOo7xQ9Tx99U+rA==
------END OPENSSH PRIVATE KEY-----
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ed25519_testpass.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ed25519_testpass.pub
deleted file mode 100644
index 7857db5602..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ed25519_testpass.pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEgmWtbxcHjqIBVjRepuNgobzAn3mIgvE5vk41CEUG89 testuser
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_1024 b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_1024
deleted file mode 100644
index 0b403674fa..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_1024
+++ /dev/null
@@ -1,15 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIICXAIBAAKBgQDGfj0Jmqj+CUb+WdFrlkRV49TJtNzvvMb/nX20zqgGm50cOIYr
-MzfFpSQN630pXeAidIgiV/PWAsipntQfSWPRG+RpB/wMKHVUNPJCJkjjRFEa56Yx
-gAhgNwF511K13x4p2tEN0r6wsfw1nos9VoO8XDBAu3lellAgBdufyCt8vwIDAQAB
-AoGBAKU+bNP1BGDQGmEfJv+5DlSuofP19MREVSpx0zfVnv45SFc5G0EVl4Wb0GMi
-O4VXmIM2nipxLBZrJOBI0HDnaQcx1zQR6tpvBO7BbAU0sflOvUDldUStTnz3TTQW
-2ECm2y8bsArNqkeLndqis3ICmYL1budhDdUYYcqv10IlbjPJAkEA6yE0zduCE2wM
-Ob7lcqiQCOiXeZ0KijHTmSZV4Fn4HRbp+XuxUpjSWFaoDTO0bncGNE+JYjywe64V
-XvEORb1hTQJBANgcjEoCrUFY7VYWx3f1tpN0Q6jwwcj67Sd+ysaZNgghTPU32GTa
-auGQFv+tifUQMyyVrhAfZ6s8myKOH5SWUDsCQGVvqOkaRq58UXXkDfZ+E81UEm0L
-u81Mm52ZdTjZd3mNNhlELIaWmUA0+kDfynpRbOLKYVl5FyX0PxH7ao3Zmo0CQFpL
-+1YFLk0KkggRdoCp+wI7ZvXUurN2HNcOxD0c0RWujFA9aD4jgNsEcIeeA/GQNkGf
-vN3hsVg793oFti5Ia/cCQAubCMvRqFTyXUBervPVC0kibO3OwYt2xN/7lQXAVSfm
-nRwV/46trioV3rMF84hpOk/46Qe5hqbWyQnL+dZljpY=
------END RSA PRIVATE KEY-----
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_1024.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_1024.pub
deleted file mode 100644
index 4aded97ab6..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_1024.pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDGfj0Jmqj+CUb+WdFrlkRV49TJtNzvvMb/nX20zqgGm50cOIYrMzfFpSQN630pXeAidIgiV/PWAsipntQfSWPRG+RpB/wMKHVUNPJCJkjjRFEa56YxgAhgNwF511K13x4p2tEN0r6wsfw1nos9VoO8XDBAu3lellAgBdufyCt8vw== testuser
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_1024_testpass b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_1024_testpass
deleted file mode 100644
index 0b66dc0aa9..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_1024_testpass
+++ /dev/null
@@ -1,18 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-Proc-Type: 4,ENCRYPTED
-DEK-Info: AES-128-CBC,4B8025AB7456E0A2B48408407C6E3FF4
-
-B9gztX+5QQPqMR/79eJHxjNdo9baoKjfWY+Ye7t1h7ucOPMCEXRSP8FwPwBfbzQh
-6W1AHOfiDCHTzArDRG9SXrFfRlU+8o5ffs/TStTNqde/AXJeNuM3pwbmqKV1m9oY
-oWelabmGtNUvGMAHMFm/2uk4BgS9Kjv71KnJg0cQQfIiPKTPBncJe/R5mf6O12rB
-ByOrrlDmjtgveZZsgggEZbU9Y9DYiHZp6yT0JepxIWNImQ/A9EeUPTQheVB2ECT6
-DLUOwRfyFhdvsfD2eXLK+u7T47keFny3rIfm1e8HC1y3X+T/nFxKGoShecx1NmEL
-HMgOKyFSwGSZh5jxE66dSQoc+rRZhCWSyPJEb9cjwp8JLON8oH3Yg+PIXYJhMFK+
-nghAIVXp3/H+cYXMN27j21cRGC7ePuF3YX242Gr+LSj42Wf4qCMTyvWur8WrSe6U
-iyrWJ8+w2J7O7rRHGM8v+GYGaiX1qIXFheM/774vsDmjuueOhkjiqs254gaap8xk
-LcJUuqJU2AL21+eW+R+EG3Rl/AbMIaQ4GFDpHfgEmmvVVoOvJunNQkDIP9JzKczO
-g7cN/EYLUC2TcdmNaiunB8RhXMiaTqw4kYJEzy4lsxk/xjubC7vlQKTvtnWCpob+
-WpHX/2FBdPPULt38AIk4HQq7vKvKw9TmvGeOvQmCUun7eCFFhxKrwNKO5YCXAHvs
-fv7JNGfrST4jwbqCvamuk+XTf0GkgJN83G7DT04EIzee6wwai/NRDybgYptJsj9G
-6wBpKH15BtkktuUzM1MCt5+T6Ccsg+d6xE6eStimwDxkXCjvgz/KlS+sPKe7uS4h
------END RSA PRIVATE KEY-----
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_1024_testpass.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_1024_testpass.pub
deleted file mode 100644
index 4aded97ab6..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_1024_testpass.pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDGfj0Jmqj+CUb+WdFrlkRV49TJtNzvvMb/nX20zqgGm50cOIYrMzfFpSQN630pXeAidIgiV/PWAsipntQfSWPRG+RpB/wMKHVUNPJCJkjjRFEa56YxgAhgNwF511K13x4p2tEN0r6wsfw1nos9VoO8XDBAu3lellAgBdufyCt8vw== testuser
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_2048 b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_2048
deleted file mode 100644
index a2d7d62310..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_2048
+++ /dev/null
@@ -1,27 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEowIBAAKCAQEA1sFEWiIp8SVO8/sDhKJ67O7tQdtDwsqWi9Fm238tAuy26OH+
-ylireX/qVcndU8Yr0qYShcwloEUaeNe77VgffZa2ZIUee75u8u+WGCYjea4RQ1bZ
-tDcioWkxl+xYfVuuKaA8CQn47XUdyoA/5P3DpDhaJl8KevaYupJNHOo9Lt2E5dVT
-93OksZBOQ6E3nNlsefP/hnFByiczlde2GIXP2sWLoxsiVsbI+CLeGtxQxPubX9yu
-vWrl/nv/yERR5ZBOEVY5N2+1BdT7DvOIMg2q60FpJv6zZpQi7Ov1iONMVafytIRW
-Ma2rPkpS83Ebxh5c92T3rgLUf5DcZjKvBgxtpwIDAQABAoIBAHeDZv6iNKU3FhFB
-iFuv8Kka7n7P/43QIKf/CTbuN6aBBenkm18QqZ0cStUjWkDc8FZyhaxgSDBBRNIr
-fTJA8IV78lVOoABNooEgRG98ChIVhRXsp4tbg7JAUJEzvqtE8k/IFKETI61CmCmx
-5d0SPGaP1du02KhFxAlQkgmdch85st+tRFv5GZXqiKbR6QlNaJgIXIoOlykVvnz6
-rnl6Q1SDutBOKGC8xFrDzFI8KxLFe3RFQxtHtsLRPcrrpukNSHICTMO4jtGXSZ12
-9Zh29ZtkouCDk+b176dGrJKfIBbxXtBGVXtkuo7rj8EWVWrJiiYbL2hcWD+Pw1VL
-0GWkaEECgYEA+RrE4nVkfdJ0Zgx+sACQqs4uKi/JuFHU69JnO7RB2lDwzQbIPKl7
-nn0ExJ4V9m035/3mqKReBIyMIjIhwXgLFiakNO/+GAWa4ycRMB3pV8WaVFCnWZEF
-oLRg1ukoLs01TfOszcux831n8zmPlz/NLTTkC26O3WXsVmnCSlPXd1MCgYEA3LMW
-B8ONEDFYACB8xKA5zn3jrKq/yVFfiQzEO87zSkgG1mQbsb5T8jggWiIHVyZKQUSk
-8ZkrwBKW+LwyRik1lVwawALmcvvN3VyCW5BukniErAUu8jb3+R2aFdrjzpiNqzMF
-M18BPDElirTXMjJusC7z/0I7+gyAu9ttYJY1id0CgYBqjIiqVIwnRV2ESNPndFZs
-uMQGR2qA7H+mXtjJMND6EKTvDXeYeuXlZJQlhXjfbtf64x9GAwgz6eoGtmq51h7n
-2p9iBUUqATu+7Xbsnd6xLFRWvCjYpq9BjeXeBtypKB0kupWvcPEstPdBkd1ZVHDu
-ZTElsqRpDq+IRrRUFoiTAQKBgQCxTGmRWSa08H8asv6o03M9EONbrlyedXHDXu8y
-gQHwFcbwasHY2+cCetZ6skWlXIxgvK2prXx5NDX2ovHcbXSvhauzv2C01NdAUvYi
-avh5ULp8mzlouoIhrgdAMXW7XdDJzRYLe/I5Ed5v/PG4UM2dWksIMISQT4UH5bKL
-2oAuPQKBgCQaJ2oc5qE/f6MiL0XfGSdY26gOZcVrm9L1XKXtyHkfj4xWYQ58DSYa
-vNZH3fGyfR+q7g1WgUmLib5etOjUjbVYRjIEov8xLA41UZZLNGRLc4VzgeCT73CW
-YvbxeN93fL0tgvKeyNVzIsWRazHMo+aQodlXvpPckHXYxYHS93W+
------END RSA PRIVATE KEY-----
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_2048.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_2048.pub
deleted file mode 100644
index b787e36483..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_2048.pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDWwURaIinxJU7z+wOEonrs7u1B20PCypaL0Wbbfy0C7Lbo4f7KWKt5f+pVyd1TxivSphKFzCWgRRp417vtWB99lrZkhR57vm7y75YYJiN5rhFDVtm0NyKhaTGX7Fh9W64poDwJCfjtdR3KgD/k/cOkOFomXwp69pi6kk0c6j0u3YTl1VP3c6SxkE5DoTec2Wx58/+GcUHKJzOV17YYhc/axYujGyJWxsj4It4a3FDE+5tf3K69auX+e//IRFHlkE4RVjk3b7UF1PsO84gyDarrQWkm/rNmlCLs6/WI40xVp/K0hFYxras+SlLzcRvGHlz3ZPeuAtR/kNxmMq8GDG2n testuser
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_2048_testpass b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_2048_testpass
deleted file mode 100644
index 7b3a3f4e58..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_2048_testpass
+++ /dev/null
@@ -1,30 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-Proc-Type: 4,ENCRYPTED
-DEK-Info: AES-128-CBC,DED10D02EF74A02F24F46AB44A84F4B3
-
-DL0M2dNu7cXNLE6KGPqEt3pSKiQw6ajlxYaaXyyAwvpZB0Pv44HUjXfhMONs5FH5
-rDjz1RSYDRdMF/h6FtltdEEareXwMtRTvP2wb0gsQKiYS5M9WeebM3TY55JmwS1U
-hhrPrEaP6hs6WEy9xp9DVxJN2y1MA5iss7M+fQ4/C6QeSp9On6bgCEvNPwdMTS4A
-3sLp+yzRvrefQmSi2SWbJoYlChitOMdc84iDJXDo951QQLX75GqMm41fFLHHrcTO
-7v/k/D7p/KLlNf43Ru+2yPNE7qyEK0pDSjvPnjPykIa6SWq3Qx2DnVdtZ7bWF8LA
-B349QmuE1r/YYHNvWnp0/5SztivJk3NMeTT29PIiZoHioo53Vtru6RcXYMOvHbh1
-maioVkgRl5gkhLC86o4V+3hiJQNrVCWMuT+lxLY2Tt6bFXulbf3WH69AEAFW4S4a
-e7zH4fwvkSwz+bFxg9B+Yynv42ke1a+tvDI+aDvsMmv9JUCy6G4Te+isXYxLdtT0
-nyqJ+wwP53AWS8gOvoUXzxxsEchTDtQnBQMWuSHEdFrk3OLGykNN6vZaxUROxpJf
-vcPl7JniWGhzDzUdHh0AQbLxXoZlv4YU1uO/+1OnrvIkuO5DCDg8v2sTFRW6sgiU
-JXm3QPJiU/bu3/FJ4XCU75cTcunZMXsL7TY9mURq7Y5FxcByuvSL2nlA7KfROTVq
-I6w+Ej+r99C1u0G63sk5b99Pm4cb2+V/sr7pslqlU9Yw1Z5hw55ibih04CiWZAhJ
-Az7s8ho4dY9E1n/XJSe26p14RPYU+w7WZuN6Xb04t3+BhF4Ubbsdn6F3lAVOrrWH
-6xNoncmIEYdfdcI089UPpV4/bIpdakXRIbaLmpshyU6aIRUXqYkzwduXcHUrxgq3
-1QCZHNvq1+9i5Wqj8JP8cZrq9YVldOeXdIIsm1SSepbDQ7820d5T4Dk6cj85BXYC
-6t12UNZ5mhzTvIAqbR3Who53jQ8cY0MSVXR6Jd6vPih2OhAnccnuJmRCNNJkL4mg
-pVcsSgYjoUx+w6Ou1muCIkkGpdEhLLwEnKFc0HUmPBToRqgiB1Aec+7oMv62XhXe
-yA26/dpT6N6SWYKN7MyDWUe2ilkmjXI+JrPCH+/w4FXh+GKafOn8XlcBnRWHVBEX
-ZQfYLckd1j9B6p7By7ed2H+8FxZLz3gthcSxRG89IP/EQImY/e9A3aoLrFX6C/W0
-Gd6JrIvzC2bZCvrq+VTYs3101j1xe6ZDJnq68HokjpG8P9DlFYDOpRetCjR7TuqN
-I5s606KAsGkt/jfbSNUMIEtuM0AC75m3TTJeWdfYh/PVYevUC+pUoreJ0ZsttQ2i
-D550sAAzU7PCzZQsDF1i2jv/YZ0wXz7+C7YFiGNmb3HmXH0Lb2HISJR5UL+x+hHY
-RArXtVubqjFz179pawzI0n03Z1OXiHolwer7C+Twmarv7SPe8rMU3HcHP25JeTAW
-mo0PxNGG3yQPlRZWpPz8LEWGo+fDqfA4kbqy4+Pvo7B8YFIQyE9QG+oBv+/7uqMU
-UOs1ZqsmvEUmvWMeQnWsjETmHKucbmTBm8ktsesb3sCKfY/pf8hAHbO6+9J3ebYf
------END RSA PRIVATE KEY-----
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_2048_testpass.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_2048_testpass.pub
deleted file mode 100644
index b787e36483..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_2048_testpass.pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDWwURaIinxJU7z+wOEonrs7u1B20PCypaL0Wbbfy0C7Lbo4f7KWKt5f+pVyd1TxivSphKFzCWgRRp417vtWB99lrZkhR57vm7y75YYJiN5rhFDVtm0NyKhaTGX7Fh9W64poDwJCfjtdR3KgD/k/cOkOFomXwp69pi6kk0c6j0u3YTl1VP3c6SxkE5DoTec2Wx58/+GcUHKJzOV17YYhc/axYujGyJWxsj4It4a3FDE+5tf3K69auX+e//IRFHlkE4RVjk3b7UF1PsO84gyDarrQWkm/rNmlCLs6/WI40xVp/K0hFYxras+SlLzcRvGHlz3ZPeuAtR/kNxmMq8GDG2n testuser
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_3072 b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_3072
deleted file mode 100644
index 10d622c905..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_3072
+++ /dev/null
@@ -1,39 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-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
------END RSA PRIVATE KEY-----
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_3072.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_3072.pub
deleted file mode 100644
index 686d3b06b1..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_3072.pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDUzzht4+crpxH0SL8fRLfpCF19SXSpQhlesc29L2L+elNl03WYLNbF40ebRglBamf0Co9kYb908a3cJAQvnZMpdrBj/SSz7inQkn3brSipUEUmtcTmVq1VAJ0hnUZHaIkveRktcddKRRHKAQv1oF84RRKYLhKQ1jQs4a7AxnZPJeIVYctj2V7UNTZQxt+Trn7ouDNT4UrM7iyD/NkPegH0D6f6jNJm/9gQy4+9QBugxQmu7+5zoPlTGHAnoZIo2RK3fElQqeyiGQJtECr9qey9UmoSyBlz6gpUWJ0s8/P2suOgSXfD5xSUzRNttdqq0VcKgTxLoIAkb8blGR+vDttRSSMZtitWqNHVbfZ2De3HNkxWiMjOiUHkta2xtljrbRv6EeTtWH4XdXDbKKcY2s8NWdUzAH6lEKw+RZK+Uu+lHgLvGqqIS5wHV4WrBZJWF8ODOS+1OJownszti6cnmkVaM13TItk2AhrlIRLOufnrjDCNzAFsxWJ+KYynem8UFus= testuser
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_3072_testpass b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_3072_testpass
deleted file mode 100644
index 353a24c206..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_3072_testpass
+++ /dev/null
@@ -1,42 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-Proc-Type: 4,ENCRYPTED
-DEK-Info: AES-128-CBC,040847DD0487D72145EB88CB09486EB0
-
-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
------END RSA PRIVATE KEY-----
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_3072_testpass.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_3072_testpass.pub
deleted file mode 100644
index 686d3b06b1..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_3072_testpass.pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDUzzht4+crpxH0SL8fRLfpCF19SXSpQhlesc29L2L+elNl03WYLNbF40ebRglBamf0Co9kYb908a3cJAQvnZMpdrBj/SSz7inQkn3brSipUEUmtcTmVq1VAJ0hnUZHaIkveRktcddKRRHKAQv1oF84RRKYLhKQ1jQs4a7AxnZPJeIVYctj2V7UNTZQxt+Trn7ouDNT4UrM7iyD/NkPegH0D6f6jNJm/9gQy4+9QBugxQmu7+5zoPlTGHAnoZIo2RK3fElQqeyiGQJtECr9qey9UmoSyBlz6gpUWJ0s8/P2suOgSXfD5xSUzRNttdqq0VcKgTxLoIAkb8blGR+vDttRSSMZtitWqNHVbfZ2De3HNkxWiMjOiUHkta2xtljrbRv6EeTtWH4XdXDbKKcY2s8NWdUzAH6lEKw+RZK+Uu+lHgLvGqqIS5wHV4WrBZJWF8ODOS+1OJownszti6cnmkVaM13TItk2AhrlIRLOufnrjDCNzAFsxWJ+KYynem8UFus= testuser
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_4096 b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_4096
deleted file mode 100644
index 1a10b388e6..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_4096
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-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
------END RSA PRIVATE KEY-----
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_4096.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_4096.pub
deleted file mode 100644
index 3c3c16feeb..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_4096.pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDDNtJeBHx0z8RTfpPaUApShGWiMqyk+EpV8O3s3emsYBzYvoA/TLcbUcsuAo8rb1LQLJ1yrKXr3hJP6672pjMMtCUVAdvEgbvo86YdeP3ZsXjuUlRE3GLvyGgQOdla0MbSuxQIEPUjjP61eNZXzWm/cGpWDmKVHq6o2C/dHNePaMvpD7fPBfF4zDuMndO66SF/nSGXFuUfhsEg4u5nJvi3xHgTJeasA+6kdpRlKLBvFoOtX6yB27/sbx2fIHR1UvcBQ1QSntauHY97CeOBRw1BCbIm4H3zAQ/f4atOyS2LGMgSYJ17+B8OyXknEHPNtQW2VDwlU6ef0kJDZTftxGCCxbfKiMXEYJT5slpfPTNKA+Z9H+tPuheAMpHvolnZVJMa4AWs9x1HISs+Dg8LoW1bSY3GfZLpErbyzrGlMPLAQO7wROGUohcac31cNfbqBjDnpmWYBolDopA/8XQCR/ydEBHOQ8m0hrbWIGtQdFcsXtgqcHAvIJSBMDdZIOA10/0Zrv7okLmAY9bkoYgqgrtJlj0vE2hXrqKCWnScYQzbtlTWtrCWXBwkDORtJpWIP+++siK7PTizj7kr6sCF7wJThRMFZQmBS+1NJXt39IF8UuxAkj9bXWf35IIhsELH2c437GQyQxBXKsw9agP6hhHH/BcYg7aqSQ956AbJvygpiw== testuser
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_4096_testpass b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_4096_testpass
deleted file mode 100644
index 96e29fc15c..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_4096_testpass
+++ /dev/null
@@ -1,54 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-Proc-Type: 4,ENCRYPTED
-DEK-Info: AES-128-CBC,1EFAFB79DD5E78C98C5A2204D6747AF8
-
-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
------END RSA PRIVATE KEY-----
diff --git a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_4096_testpass.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_4096_testpass.pub
deleted file mode 100644
index 3c3c16feeb..0000000000
--- a/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_4096_testpass.pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDDNtJeBHx0z8RTfpPaUApShGWiMqyk+EpV8O3s3emsYBzYvoA/TLcbUcsuAo8rb1LQLJ1yrKXr3hJP6672pjMMtCUVAdvEgbvo86YdeP3ZsXjuUlRE3GLvyGgQOdla0MbSuxQIEPUjjP61eNZXzWm/cGpWDmKVHq6o2C/dHNePaMvpD7fPBfF4zDuMndO66SF/nSGXFuUfhsEg4u5nJvi3xHgTJeasA+6kdpRlKLBvFoOtX6yB27/sbx2fIHR1UvcBQ1QSntauHY97CeOBRw1BCbIm4H3zAQ/f4atOyS2LGMgSYJ17+B8OyXknEHPNtQW2VDwlU6ef0kJDZTftxGCCxbfKiMXEYJT5slpfPTNKA+Z9H+tPuheAMpHvolnZVJMa4AWs9x1HISs+Dg8LoW1bSY3GfZLpErbyzrGlMPLAQO7wROGUohcac31cNfbqBjDnpmWYBolDopA/8XQCR/ydEBHOQ8m0hrbWIGtQdFcsXtgqcHAvIJSBMDdZIOA10/0Zrv7okLmAY9bkoYgqgrtJlj0vE2hXrqKCWnScYQzbtlTWtrCWXBwkDORtJpWIP+++siK7PTizj7kr6sCF7wJThRMFZQmBS+1NJXt39IF8UuxAkj9bXWf35IIhsELH2c437GQyQxBXKsw9agP6hhHH/BcYg7aqSQ956AbJvygpiw== testuser
diff --git a/org.eclipse.jgit.test/src/org/eclipse/jgit/transport/ssh/SshTestBase.java b/org.eclipse.jgit.test/src/org/eclipse/jgit/transport/ssh/SshTestBase.java
deleted file mode 100644
index c22c10cb7f..0000000000
--- a/org.eclipse.jgit.test/src/org/eclipse/jgit/transport/ssh/SshTestBase.java
+++ /dev/null
@@ -1,811 +0,0 @@
-/*
- * Copyright (C) 2018, Thomas Wolf and others
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Distribution License v. 1.0 which is available at
- * https://www.eclipse.org/org/documents/edl-v10.php.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-package org.eclipse.jgit.transport.ssh;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeTrue;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.util.List;
-import java.util.Locale;
-
-import org.eclipse.jgit.api.errors.TransportException;
-import org.eclipse.jgit.transport.CredentialItem;
-import org.eclipse.jgit.transport.JschConfigSessionFactory;
-import org.junit.Test;
-import org.junit.experimental.theories.DataPoints;
-import org.junit.experimental.theories.Theory;
-
-/**
- * The ssh tests. Concrete subclasses can re-use these tests by implementing the
- * abstract operations from {@link SshTestHarness}. This gives a way to test
- * different ssh clients against a unified test suite.
- */
-public abstract class SshTestBase extends SshTestHarness {
-
- @DataPoints
- public static String[] KEY_RESOURCES = { //
- "id_dsa", //
- "id_rsa_1024", //
- "id_rsa_2048", //
- "id_rsa_3072", //
- "id_rsa_4096", //
- "id_ecdsa_256", //
- "id_ecdsa_384", //
- "id_ecdsa_521", //
- "id_ed25519", //
- // And now encrypted. Passphrase is "testpass".
- "id_dsa_testpass", //
- "id_rsa_1024_testpass", //
- "id_rsa_2048_testpass", //
- "id_rsa_3072_testpass", //
- "id_rsa_4096_testpass", //
- "id_ecdsa_256_testpass", //
- "id_ecdsa_384_testpass", //
- "id_ecdsa_521_testpass", //
- "id_ed25519_testpass", //
- "id_ed25519_expensive_testpass" };
-
- protected File defaultCloneDir;
-
- @Override
- public void setUp() throws Exception {
- super.setUp();
- defaultCloneDir = new File(getTemporaryDirectory(), "cloned");
- }
-
- @Test(expected = TransportException.class)
- public void testSshWithoutConfig() throws Exception {
- cloneWith("ssh://" + TEST_USER + "@localhost:" + testPort
- + "/doesntmatter", defaultCloneDir, null);
- }
-
- @Test
- public void testSshWithGlobalIdentity() throws Exception {
- cloneWith(
- "ssh://" + TEST_USER + "@localhost:" + testPort
- + "/doesntmatter",
- defaultCloneDir, null,
- "IdentityFile " + privateKey1.getAbsolutePath());
- }
-
- @Test
- public void testSshWithDefaultIdentity() throws Exception {
- File idRsa = new File(privateKey1.getParentFile(), "id_rsa");
- Files.copy(privateKey1.toPath(), idRsa.toPath());
- // We expect the session factory to pick up these keys...
- cloneWith("ssh://" + TEST_USER + "@localhost:" + testPort
- + "/doesntmatter", defaultCloneDir, null);
- }
-
- @Test
- public void testSshWithConfig() throws Exception {
- cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, null, //
- "Host localhost", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "IdentityFile " + privateKey1.getAbsolutePath());
- }
-
- @Test
- public void testSshWithConfigEncryptedUnusedKey() throws Exception {
- // Copy the encrypted test key from the bundle.
- File encryptedKey = new File(sshDir, "id_dsa");
- copyTestResource("id_dsa_testpass", encryptedKey);
- TestCredentialsProvider provider = new TestCredentialsProvider(
- "testpass");
- cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, provider, //
- "Host localhost", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "IdentityFile " + privateKey1.getAbsolutePath());
- assertEquals("CredentialsProvider should not have been called", 0,
- provider.getLog().size());
- }
-
- @Test
- public void testSshWithConfigEncryptedUnusedKeyInConfigLast()
- throws Exception {
- // Copy the encrypted test key from the bundle.
- File encryptedKey = new File(sshDir, "id_dsa_test_key");
- copyTestResource("id_dsa_testpass", encryptedKey);
- TestCredentialsProvider provider = new TestCredentialsProvider(
- "testpass");
- cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, provider, //
- "Host localhost", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "IdentityFile " + privateKey1.getAbsolutePath(),
- "IdentityFile " + encryptedKey.getAbsolutePath());
- // This test passes with JSch per chance because JSch completely ignores
- // the second IdentityFile
- assertEquals("CredentialsProvider should not have been called", 0,
- provider.getLog().size());
- }
-
- @Test
- public void testSshWithConfigEncryptedUnusedKeyInConfigFirst()
- throws Exception {
- // Test cannot pass with JSch; it handles only one IdentityFile.
- // assumeTrue(!(getSessionFactory() instanceof
- // JschConfigSessionFactory)); gives in bazel a failure with "Never
- // found parameters that satisfied method assumptions."
- // In maven it's fine!?
- if (getSessionFactory() instanceof JschConfigSessionFactory) {
- return;
- }
- // Copy the encrypted test key from the bundle.
- File encryptedKey = new File(sshDir, "id_dsa_test_key");
- copyTestResource("id_dsa_testpass", encryptedKey);
- TestCredentialsProvider provider = new TestCredentialsProvider(
- "testpass");
- cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, provider, //
- "Host localhost", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "IdentityFile " + encryptedKey.getAbsolutePath(),
- "IdentityFile " + privateKey1.getAbsolutePath());
- assertEquals("CredentialsProvider should have been called once", 1,
- provider.getLog().size());
- }
-
- @Test
- public void testSshEncryptedUsedKeyCached() throws Exception {
- // Make sure we are asked for the password only once if we do several
- // operations with an encrypted key.
- File encryptedKey = new File(sshDir, "id_dsa_test_key");
- copyTestResource("id_dsa_testpass", encryptedKey);
- File encryptedPublicKey = new File(sshDir, "id_dsa_test_key.pub");
- copyTestResource("id_dsa_testpass.pub", encryptedPublicKey);
- server.setTestUserPublicKey(encryptedPublicKey.toPath());
- TestCredentialsProvider provider = new TestCredentialsProvider(
- "testpass");
- pushTo(provider,
- cloneWith("ssh://localhost/doesntmatter", //
- defaultCloneDir, provider, //
- "Host localhost", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "IdentityFile " + encryptedKey.getAbsolutePath()));
- assertEquals("CredentialsProvider should have been called once", 1,
- provider.getLog().size());
- }
-
- @Test(expected = TransportException.class)
- public void testSshEncryptedUsedKeyWrongPassword() throws Exception {
- File encryptedKey = new File(sshDir, "id_dsa_test_key");
- copyTestResource("id_dsa_testpass", encryptedKey);
- File encryptedPublicKey = new File(sshDir, "id_dsa_test_key.pub");
- copyTestResource("id_dsa_testpass.pub", encryptedPublicKey);
- server.setTestUserPublicKey(encryptedPublicKey.toPath());
- TestCredentialsProvider provider = new TestCredentialsProvider(
- "wrongpass");
- cloneWith("ssh://localhost/doesntmatter", //
- defaultCloneDir, provider, //
- "Host localhost", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "NumberOfPasswordPrompts 1", //
- "IdentityFile " + encryptedKey.getAbsolutePath());
- }
-
- @Test
- public void testSshEncryptedUsedKeySeveralPassword() throws Exception {
- File encryptedKey = new File(sshDir, "id_dsa_test_key");
- copyTestResource("id_dsa_testpass", encryptedKey);
- File encryptedPublicKey = new File(sshDir, "id_dsa_test_key.pub");
- copyTestResource("id_dsa_testpass.pub", encryptedPublicKey);
- server.setTestUserPublicKey(encryptedPublicKey.toPath());
- TestCredentialsProvider provider = new TestCredentialsProvider(
- "wrongpass", "wrongpass2", "testpass");
- cloneWith("ssh://localhost/doesntmatter", //
- defaultCloneDir, provider, //
- "Host localhost", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "IdentityFile " + encryptedKey.getAbsolutePath());
- assertEquals("CredentialsProvider should have been called 3 times", 3,
- provider.getLog().size());
- }
-
- @Test(expected = TransportException.class)
- public void testSshWithoutKnownHosts() throws Exception {
- assertTrue("Could not delete known_hosts", knownHosts.delete());
- cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, null, //
- "Host localhost", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "IdentityFile " + privateKey1.getAbsolutePath());
- }
-
- @Test
- public void testSshWithoutKnownHostsWithProviderAsk()
- throws Exception {
- File copiedHosts = new File(knownHosts.getParentFile(),
- "copiedKnownHosts");
- assertTrue("Failed to rename known_hosts",
- knownHosts.renameTo(copiedHosts));
- // The provider will answer "yes" to all questions, so we should be able
- // to connect and end up with a new known_hosts file with the host key.
- TestCredentialsProvider provider = new TestCredentialsProvider();
- cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, provider, //
- "Host localhost", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "IdentityFile " + privateKey1.getAbsolutePath());
- List messages = provider.getLog();
- assertFalse("Expected user interaction", messages.isEmpty());
- if (getSessionFactory() instanceof JschConfigSessionFactory) {
- // JSch doesn't create a non-existing file.
- assertEquals("Expected to be asked about the key", 1,
- messages.size());
- return;
- }
- assertEquals(
- "Expected to be asked about the key, and the file creation",
- 2, messages.size());
- assertTrue("~/.ssh/known_hosts should exist now", knownHosts.exists());
- // Instead of checking the file contents, let's just clone again
- // without provider. If it works, the server host key was written
- // correctly.
- File clonedAgain = new File(getTemporaryDirectory(), "cloned2");
- cloneWith("ssh://localhost/doesntmatter", clonedAgain, null, //
- "Host localhost", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "IdentityFile " + privateKey1.getAbsolutePath());
- }
-
- @Test
- public void testSshWithoutKnownHostsWithProviderAcceptNew()
- throws Exception {
- File copiedHosts = new File(knownHosts.getParentFile(),
- "copiedKnownHosts");
- assertTrue("Failed to rename known_hosts",
- knownHosts.renameTo(copiedHosts));
- TestCredentialsProvider provider = new TestCredentialsProvider();
- cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, provider, //
- "Host localhost", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "StrictHostKeyChecking accept-new", //
- "IdentityFile " + privateKey1.getAbsolutePath());
- if (getSessionFactory() instanceof JschConfigSessionFactory) {
- // JSch doesn't create new files.
- assertTrue("CredentialsProvider not called",
- provider.getLog().isEmpty());
- return;
- }
- assertEquals("Expected to be asked about the file creation", 1,
- provider.getLog().size());
- assertTrue("~/.ssh/known_hosts should exist now", knownHosts.exists());
- // Instead of checking the file contents, let's just clone again
- // without provider. If it works, the server host key was written
- // correctly.
- File clonedAgain = new File(getTemporaryDirectory(), "cloned2");
- cloneWith("ssh://localhost/doesntmatter", clonedAgain, null, //
- "Host localhost", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "IdentityFile " + privateKey1.getAbsolutePath());
- }
-
- @Test(expected = TransportException.class)
- public void testSshWithoutKnownHostsDeny() throws Exception {
- File copiedHosts = new File(knownHosts.getParentFile(),
- "copiedKnownHosts");
- assertTrue("Failed to rename known_hosts",
- knownHosts.renameTo(copiedHosts));
- cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, null, //
- "Host localhost", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "StrictHostKeyChecking yes", //
- "IdentityFile " + privateKey1.getAbsolutePath());
- }
-
- @Test(expected = TransportException.class)
- public void testSshModifiedHostKeyDeny()
- throws Exception {
- File copiedHosts = new File(knownHosts.getParentFile(),
- "copiedKnownHosts");
- assertTrue("Failed to rename known_hosts",
- knownHosts.renameTo(copiedHosts));
- // Now produce a new known_hosts file containing some other key.
- createKnownHostsFile(knownHosts, "localhost", testPort, publicKey1);
- cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, null, //
- "Host localhost", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "StrictHostKeyChecking yes", //
- "IdentityFile " + privateKey1.getAbsolutePath());
- }
-
- @Test(expected = TransportException.class)
- public void testSshModifiedHostKeyWithProviderDeny() throws Exception {
- File copiedHosts = new File(knownHosts.getParentFile(),
- "copiedKnownHosts");
- assertTrue("Failed to rename known_hosts",
- knownHosts.renameTo(copiedHosts));
- // Now produce a new known_hosts file containing some other key.
- createKnownHostsFile(knownHosts, "localhost", testPort, publicKey1);
- TestCredentialsProvider provider = new TestCredentialsProvider();
- try {
- cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, provider, //
- "Host localhost", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "StrictHostKeyChecking yes", //
- "IdentityFile " + privateKey1.getAbsolutePath());
- } catch (Exception e) {
- assertEquals("Expected to be told about the modified key", 1,
- provider.getLog().size());
- assertTrue("Only messages expected", provider.getLog().stream()
- .flatMap(l -> l.getItems().stream()).allMatch(
- c -> c instanceof CredentialItem.InformationalMessage));
- throw e;
- }
- }
-
- private void checkKnownHostsModifiedHostKey(File backup, File newFile,
- String wrongKey) throws IOException {
- List oldLines = Files.readAllLines(backup.toPath(), UTF_8);
- // Find the original entry. We should have that again in known_hosts.
- String oldKeyPart = null;
- for (String oldLine : oldLines) {
- if (oldLine.contains("[localhost]:")) {
- String[] parts = oldLine.split("\\s+");
- if (parts.length > 2) {
- oldKeyPart = parts[parts.length - 2] + ' '
- + parts[parts.length - 1];
- break;
- }
- }
- }
- assertNotNull("Old key not found", oldKeyPart);
- List newLines = Files.readAllLines(newFile.toPath(), UTF_8);
- assertFalse("Old host key still found in known_hosts file" + newFile,
- hasHostKey("localhost", testPort, wrongKey, newLines));
- assertTrue("New host key not found in known_hosts file" + newFile,
- hasHostKey("localhost", testPort, oldKeyPart, newLines));
-
- }
-
- @Test
- public void testSshModifiedHostKeyAllow() throws Exception {
- assertTrue("Failed to delete known_hosts", knownHosts.delete());
- createKnownHostsFile(knownHosts, "localhost", testPort, publicKey1);
- File backup = new File(getTemporaryDirectory(), "backupKnownHosts");
- Files.copy(knownHosts.toPath(), backup.toPath());
- cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, null, //
- "Host localhost", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "StrictHostKeyChecking no", //
- "IdentityFile " + privateKey1.getAbsolutePath());
- // File should not have been updated!
- String[] oldLines = Files
- .readAllLines(backup.toPath(), UTF_8)
- .toArray(new String[0]);
- String[] newLines = Files
- .readAllLines(knownHosts.toPath(), UTF_8)
- .toArray(new String[0]);
- assertArrayEquals("Known hosts file should not be modified", oldLines,
- newLines);
- }
-
- @Test
- public void testSshModifiedHostKeyAsk() throws Exception {
- File copiedHosts = new File(knownHosts.getParentFile(),
- "copiedKnownHosts");
- assertTrue("Failed to rename known_hosts",
- knownHosts.renameTo(copiedHosts));
- String wrongKeyPart = createKnownHostsFile(knownHosts, "localhost",
- testPort, publicKey1);
- TestCredentialsProvider provider = new TestCredentialsProvider();
- cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, provider, //
- "Host localhost", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "IdentityFile " + privateKey1.getAbsolutePath());
- checkKnownHostsModifiedHostKey(copiedHosts, knownHosts, wrongKeyPart);
- assertEquals("Expected to be asked about the modified key", 1,
- provider.getLog().size());
- }
-
- @Test
- public void testSshCloneWithConfigAndPush() throws Exception {
- pushTo(cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, null, //
- "Host localhost", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "IdentityFile " + privateKey1.getAbsolutePath()));
- }
-
- @Test
- public void testSftpWithConfig() throws Exception {
- cloneWith("sftp://localhost/.git", defaultCloneDir, null, //
- "Host localhost", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "IdentityFile " + privateKey1.getAbsolutePath());
- }
-
- @Test
- public void testSftpCloneWithConfigAndPush() throws Exception {
- pushTo(cloneWith("sftp://localhost/.git", defaultCloneDir, null, //
- "Host localhost", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "IdentityFile " + privateKey1.getAbsolutePath()));
- }
-
- @Test(expected = TransportException.class)
- public void testSshWithConfigWrongKey() throws Exception {
- cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, null, //
- "Host localhost", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "IdentityFile " + privateKey2.getAbsolutePath());
- }
-
- @Test
- public void testSshWithWrongUserNameInConfig() throws Exception {
- // Bug 526778
- cloneWith(
- "ssh://" + TEST_USER + "@localhost:" + testPort
- + "/doesntmatter",
- defaultCloneDir, null, //
- "Host localhost", //
- "HostName localhost", //
- "User sombody_else", //
- "IdentityFile " + privateKey1.getAbsolutePath());
- }
-
- @Test
- public void testSshWithWrongPortInConfig() throws Exception {
- // Bug 526778
- cloneWith(
- "ssh://" + TEST_USER + "@localhost:" + testPort
- + "/doesntmatter",
- defaultCloneDir, null, //
- "Host localhost", //
- "HostName localhost", //
- "Port 22", //
- "User " + TEST_USER, //
- "IdentityFile " + privateKey1.getAbsolutePath());
- }
-
- @Test
- public void testSshWithAliasInConfig() throws Exception {
- // Bug 531118
- cloneWith("ssh://git/doesntmatter", defaultCloneDir, null, //
- "Host git", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "IdentityFile " + privateKey1.getAbsolutePath(), "", //
- "Host localhost", //
- "HostName localhost", //
- "Port 22", //
- "User someone_else", //
- "IdentityFile " + privateKey2.getAbsolutePath());
- }
-
- @Test
- public void testSshWithUnknownCiphersInConfig() throws Exception {
- // Bug 535672
- cloneWith("ssh://git/doesntmatter", defaultCloneDir, null, //
- "Host git", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "IdentityFile " + privateKey1.getAbsolutePath(), //
- "Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr");
- }
-
- @Test
- public void testSshWithUnknownHostKeyAlgorithmsInConfig()
- throws Exception {
- // Bug 535672
- cloneWith("ssh://git/doesntmatter", defaultCloneDir, null, //
- "Host git", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "IdentityFile " + privateKey1.getAbsolutePath(), //
- "HostKeyAlgorithms foobar,ssh-rsa,ssh-dss");
- }
-
- @Test
- public void testSshWithUnknownKexAlgorithmsInConfig()
- throws Exception {
- // Bug 535672
- cloneWith("ssh://git/doesntmatter", defaultCloneDir, null, //
- "Host git", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "IdentityFile " + privateKey1.getAbsolutePath(), //
- "KexAlgorithms foobar,diffie-hellman-group14-sha1,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521");
- }
-
- @Test
- public void testSshWithMinimalHostKeyAlgorithmsInConfig()
- throws Exception {
- // Bug 537790
- cloneWith("ssh://git/doesntmatter", defaultCloneDir, null, //
- "Host git", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "IdentityFile " + privateKey1.getAbsolutePath(), //
- "HostKeyAlgorithms ssh-rsa,ssh-dss");
- }
-
- @Test
- public void testSshWithUnknownAuthInConfig() throws Exception {
- cloneWith("ssh://git/doesntmatter", defaultCloneDir, null, //
- "Host git", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "IdentityFile " + privateKey1.getAbsolutePath(), //
- "PreferredAuthentications gssapi-with-mic,hostbased,publickey,keyboard-interactive,password");
- }
-
- @Test(expected = TransportException.class)
- public void testSshWithNoMatchingAuthInConfig() throws Exception {
- // Server doesn't do password, and anyway we set no password.
- cloneWith("ssh://git/doesntmatter", defaultCloneDir, null, //
- "Host git", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "IdentityFile " + privateKey1.getAbsolutePath(), //
- "PreferredAuthentications password");
- }
-
- @Test
- public void testRsaHostKeySecond() throws Exception {
- // See https://git.eclipse.org/r/#/c/130402/ : server has EcDSA
- // (preferred), RSA, we have RSA in known_hosts: client and server
- // should agree on RSA.
- File newHostKey = new File(getTemporaryDirectory(), "newhostkey");
- copyTestResource("id_ecdsa_256", newHostKey);
- server.addHostKey(newHostKey.toPath(), true);
- cloneWith("ssh://git/doesntmatter", defaultCloneDir, null, //
- "Host git", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "IdentityFile " + privateKey1.getAbsolutePath());
- }
-
- @Test
- public void testEcDsaHostKey() throws Exception {
- // See https://git.eclipse.org/r/#/c/130402/ : server has RSA
- // (preferred), EcDSA, we have EcDSA in known_hosts: client and server
- // should agree on EcDSA.
- File newHostKey = new File(getTemporaryDirectory(), "newhostkey");
- copyTestResource("id_ecdsa_256", newHostKey);
- server.addHostKey(newHostKey.toPath(), false);
- File newHostKeyPub = new File(getTemporaryDirectory(),
- "newhostkey.pub");
- copyTestResource("id_ecdsa_256.pub", newHostKeyPub);
- createKnownHostsFile(knownHosts, "localhost", testPort, newHostKeyPub);
- cloneWith("ssh://git/doesntmatter", defaultCloneDir, null, //
- "Host git", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "IdentityFile " + privateKey1.getAbsolutePath());
- }
-
- @Test
- public void testPasswordAuth() throws Exception {
- server.enablePasswordAuthentication();
- TestCredentialsProvider provider = new TestCredentialsProvider(
- TEST_USER.toUpperCase(Locale.ROOT));
- cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
- "Host git", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "PreferredAuthentications password");
- }
-
- @Test
- public void testPasswordAuthSeveralTimes() throws Exception {
- server.enablePasswordAuthentication();
- TestCredentialsProvider provider = new TestCredentialsProvider(
- "wrongpass", "wrongpass", TEST_USER.toUpperCase(Locale.ROOT));
- cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
- "Host git", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "PreferredAuthentications password");
- }
-
- @Test(expected = TransportException.class)
- public void testPasswordAuthWrongPassword() throws Exception {
- server.enablePasswordAuthentication();
- TestCredentialsProvider provider = new TestCredentialsProvider(
- "wrongpass");
- cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
- "Host git", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "PreferredAuthentications password");
- }
-
- @Test(expected = TransportException.class)
- public void testPasswordAuthNoPassword() throws Exception {
- server.enablePasswordAuthentication();
- TestCredentialsProvider provider = new TestCredentialsProvider();
- cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
- "Host git", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "PreferredAuthentications password");
- }
-
- @Test(expected = TransportException.class)
- public void testPasswordAuthCorrectPasswordTooLate() throws Exception {
- server.enablePasswordAuthentication();
- TestCredentialsProvider provider = new TestCredentialsProvider(
- "wrongpass", "wrongpass", "wrongpass",
- TEST_USER.toUpperCase(Locale.ROOT));
- cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
- "Host git", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "PreferredAuthentications password");
- }
-
- @Test
- public void testKeyboardInteractiveAuth() throws Exception {
- server.enableKeyboardInteractiveAuthentication();
- TestCredentialsProvider provider = new TestCredentialsProvider(
- TEST_USER.toUpperCase(Locale.ROOT));
- cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
- "Host git", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "PreferredAuthentications keyboard-interactive");
- }
-
- @Test
- public void testKeyboardInteractiveAuthSeveralTimes() throws Exception {
- server.enableKeyboardInteractiveAuthentication();
- TestCredentialsProvider provider = new TestCredentialsProvider(
- "wrongpass", "wrongpass", TEST_USER.toUpperCase(Locale.ROOT));
- cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
- "Host git", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "PreferredAuthentications keyboard-interactive");
- }
-
- @Test(expected = TransportException.class)
- public void testKeyboardInteractiveAuthWrongPassword() throws Exception {
- server.enableKeyboardInteractiveAuthentication();
- TestCredentialsProvider provider = new TestCredentialsProvider(
- "wrongpass");
- cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
- "Host git", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "PreferredAuthentications keyboard-interactive");
- }
-
- @Test(expected = TransportException.class)
- public void testKeyboardInteractiveAuthNoPassword() throws Exception {
- server.enableKeyboardInteractiveAuthentication();
- TestCredentialsProvider provider = new TestCredentialsProvider();
- cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
- "Host git", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "PreferredAuthentications keyboard-interactive");
- }
-
- @Test(expected = TransportException.class)
- public void testKeyboardInteractiveAuthCorrectPasswordTooLate()
- throws Exception {
- server.enableKeyboardInteractiveAuthentication();
- TestCredentialsProvider provider = new TestCredentialsProvider(
- "wrongpass", "wrongpass", "wrongpass",
- TEST_USER.toUpperCase(Locale.ROOT));
- cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
- "Host git", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "PreferredAuthentications keyboard-interactive");
- }
-
- @Theory
- public void testSshKeys(String keyName) throws Exception {
- // JSch fails on ECDSA 384/521 keys. Compare
- // https://sourceforge.net/p/jsch/patches/10/
- assumeTrue(!(getSessionFactory() instanceof JschConfigSessionFactory
- && (keyName.contains("ed25519")
- || keyName.startsWith("id_ecdsa_384")
- || keyName.startsWith("id_ecdsa_521"))));
- File cloned = new File(getTemporaryDirectory(), "cloned");
- String keyFileName = keyName + "_key";
- File privateKey = new File(sshDir, keyFileName);
- copyTestResource(keyName, privateKey);
- File publicKey = new File(sshDir, keyFileName + ".pub");
- copyTestResource(keyName + ".pub", publicKey);
- server.setTestUserPublicKey(publicKey.toPath());
- TestCredentialsProvider provider = new TestCredentialsProvider(
- "testpass");
- pushTo(provider,
- cloneWith("ssh://localhost/doesntmatter", //
- cloned, provider, //
- "Host localhost", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "IdentityFile " + privateKey.getAbsolutePath()));
- int expectedCalls = keyName.endsWith("testpass") ? 1 : 0;
- assertEquals("Unexpected calls to CredentialsProvider", expectedCalls,
- provider.getLog().size());
- // Should now also work without credentials provider, even if the key
- // was encrypted.
- cloned = new File(getTemporaryDirectory(), "cloned2");
- pushTo(null,
- cloneWith("ssh://localhost/doesntmatter", //
- cloned, null, //
- "Host localhost", //
- "HostName localhost", //
- "Port " + testPort, //
- "User " + TEST_USER, //
- "IdentityFile " + privateKey.getAbsolutePath()));
- }
-}
diff --git a/org.eclipse.jgit.test/src/org/eclipse/jgit/transport/ssh/SshTestHarness.java b/org.eclipse.jgit.test/src/org/eclipse/jgit/transport/ssh/SshTestHarness.java
deleted file mode 100644
index 632c24b890..0000000000
--- a/org.eclipse.jgit.test/src/org/eclipse/jgit/transport/ssh/SshTestHarness.java
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- * Copyright (C) 2018, Thomas Wolf and others
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Distribution License v. 1.0 which is available at
- * https://www.eclipse.org/org/documents/edl-v10.php.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-package org.eclipse.jgit.transport.ssh;
-
-import static java.nio.charset.StandardCharsets.US_ASCII;
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.file.Files;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-
-import org.eclipse.jgit.api.CloneCommand;
-import org.eclipse.jgit.api.Git;
-import org.eclipse.jgit.api.PushCommand;
-import org.eclipse.jgit.api.ResetCommand.ResetType;
-import org.eclipse.jgit.errors.UnsupportedCredentialItem;
-import org.eclipse.jgit.junit.RepositoryTestCase;
-import org.eclipse.jgit.junit.ssh.SshTestGitServer;
-import org.eclipse.jgit.lib.Constants;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.revwalk.RevCommit;
-import org.eclipse.jgit.transport.CredentialItem;
-import org.eclipse.jgit.transport.CredentialsProvider;
-import org.eclipse.jgit.transport.PushResult;
-import org.eclipse.jgit.transport.RemoteRefUpdate;
-import org.eclipse.jgit.transport.SshSessionFactory;
-import org.eclipse.jgit.transport.URIish;
-import org.eclipse.jgit.util.FS;
-import org.junit.After;
-
-import com.jcraft.jsch.JSch;
-import com.jcraft.jsch.KeyPair;
-
-/**
- * Root class for ssh tests. Sets up the ssh test server. A set of pre-computed
- * keys for testing is provided in the bundle and can be used in test cases via
- * {@link #copyTestResource(String, File)}. These test key files names have four
- * components, separated by a single underscore: "id", the algorithm, the bits
- * (if variable), and the password if the private key is encrypted. For instance
- * "{@code id_ecdsa_384_testpass}" is an encrypted ECDSA-384 key. The passphrase
- * to decrypt is "testpass". The key "{@code id_ecdsa_384}" is the same but
- * unencrypted. All keys were generated and encrypted via ssh-keygen. Note that
- * DSA and ec25519 have no "bits" component. Available keys are listed in
- * {@link SshTestBase#KEY_RESOURCES}.
- */
-public abstract class SshTestHarness extends RepositoryTestCase {
-
- protected static final String TEST_USER = "testuser";
-
- protected File sshDir;
-
- protected File privateKey1;
-
- protected File privateKey2;
-
- protected File publicKey1;
-
- protected SshTestGitServer server;
-
- private SshSessionFactory factory;
-
- protected int testPort;
-
- protected File knownHosts;
-
- private File homeDir;
-
- @Override
- public void setUp() throws Exception {
- super.setUp();
- writeTrashFile("file.txt", "something");
- try (Git git = new Git(db)) {
- git.add().addFilepattern("file.txt").call();
- git.commit().setMessage("Initial commit").call();
- }
- mockSystemReader.setProperty("user.home",
- getTemporaryDirectory().getAbsolutePath());
- mockSystemReader.setProperty("HOME",
- getTemporaryDirectory().getAbsolutePath());
- homeDir = FS.DETECTED.userHome();
- FS.DETECTED.setUserHome(getTemporaryDirectory().getAbsoluteFile());
- sshDir = new File(getTemporaryDirectory(), ".ssh");
- assertTrue(sshDir.mkdir());
- File serverDir = new File(getTemporaryDirectory(), "srv");
- assertTrue(serverDir.mkdir());
- // Create two key pairs. Let's not call them "id_rsa".
- privateKey1 = new File(sshDir, "first_key");
- privateKey2 = new File(sshDir, "second_key");
- publicKey1 = createKeyPair(privateKey1);
- createKeyPair(privateKey2);
- ByteArrayOutputStream publicHostKey = new ByteArrayOutputStream();
- // Start a server with our test user and the first key.
- server = new SshTestGitServer(TEST_USER, publicKey1.toPath(), db,
- createHostKey(publicHostKey));
- testPort = server.start();
- assertTrue(testPort > 0);
- knownHosts = new File(sshDir, "known_hosts");
- Files.write(knownHosts.toPath(), Collections.singleton("[localhost]:"
- + testPort + ' '
- + publicHostKey.toString(US_ASCII.name())));
- factory = createSessionFactory();
- SshSessionFactory.setInstance(factory);
- }
-
- private static File createKeyPair(File privateKeyFile) throws Exception {
- // Found no way to do this with MINA sshd except rolling it all
- // ourselves...
- JSch jsch = new JSch();
- KeyPair pair = KeyPair.genKeyPair(jsch, KeyPair.RSA, 2048);
- try (OutputStream out = new FileOutputStream(privateKeyFile)) {
- pair.writePrivateKey(out);
- }
- File publicKeyFile = new File(privateKeyFile.getParentFile(),
- privateKeyFile.getName() + ".pub");
- try (OutputStream out = new FileOutputStream(publicKeyFile)) {
- pair.writePublicKey(out, TEST_USER);
- }
- return publicKeyFile;
- }
-
- private static byte[] createHostKey(OutputStream publicKey)
- throws Exception {
- JSch jsch = new JSch();
- KeyPair pair = KeyPair.genKeyPair(jsch, KeyPair.RSA, 2048);
- pair.writePublicKey(publicKey, "");
- try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
- pair.writePrivateKey(out);
- out.flush();
- return out.toByteArray();
- }
- }
-
- /**
- * Creates a new known_hosts file with one entry for the given host and port
- * taken from the given public key file.
- *
- * @param file
- * to write the known_hosts file to
- * @param host
- * for the entry
- * @param port
- * for the entry
- * @param publicKey
- * to use
- * @return the public-key part of the line
- * @throws IOException
- */
- protected static String createKnownHostsFile(File file, String host,
- int port, File publicKey) throws IOException {
- List lines = Files.readAllLines(publicKey.toPath(), UTF_8);
- assertEquals("Public key has too many lines", 1, lines.size());
- String pubKey = lines.get(0);
- // Strip off the comment.
- String[] parts = pubKey.split("\\s+");
- assertTrue("Unexpected key content",
- parts.length == 2 || parts.length == 3);
- String keyPart = parts[0] + ' ' + parts[1];
- String line = '[' + host + "]:" + port + ' ' + keyPart;
- Files.write(file.toPath(), Collections.singletonList(line));
- return keyPart;
- }
-
- /**
- * Checks whether there is a line for the given host and port that also
- * matches the given key part in the list of lines.
- *
- * @param host
- * to look for
- * @param port
- * to look for
- * @param keyPart
- * to look for
- * @param lines
- * to look in
- * @return {@code true} if found, {@code false} otherwise
- */
- protected boolean hasHostKey(String host, int port, String keyPart,
- List lines) {
- String h = '[' + host + "]:" + port;
- return lines.stream()
- .anyMatch(l -> l.contains(h) && l.contains(keyPart));
- }
-
- @After
- public void shutdownServer() throws Exception {
- if (server != null) {
- server.stop();
- server = null;
- }
- FS.DETECTED.setUserHome(homeDir);
- SshSessionFactory.setInstance(null);
- factory = null;
- }
-
- protected abstract SshSessionFactory createSessionFactory();
-
- protected SshSessionFactory getSessionFactory() {
- return factory;
- }
-
- protected abstract void installConfig(String... config);
-
- /**
- * Copies a test data file contained in the test bundle to the given file.
- * Equivalent to {@link #copyTestResource(Class, String, File)} with
- * {@code SshTestHarness.class} as first parameter.
- *
- * @param resourceName
- * of the test resource to copy
- * @param to
- * file to copy the resource to
- * @throws IOException
- * if the resource cannot be copied
- */
- protected void copyTestResource(String resourceName, File to)
- throws IOException {
- copyTestResource(SshTestHarness.class, resourceName, to);
- }
-
- /**
- * Copies a test data file contained in the test bundle to the given file,
- * using {@link Class#getResourceAsStream(String)} to get the test resource.
- *
- * @param loader
- * {@link Class} to use to load the resource
- * @param resourceName
- * of the test resource to copy
- * @param to
- * file to copy the resource to
- * @throws IOException
- * if the resource cannot be copied
- */
- protected void copyTestResource(Class> loader, String resourceName,
- File to) throws IOException {
- try (InputStream in = loader.getResourceAsStream(resourceName)) {
- Files.copy(in, to.toPath());
- }
- }
-
- protected File cloneWith(String uri, File to, CredentialsProvider provider,
- String... config) throws Exception {
- installConfig(config);
- CloneCommand clone = Git.cloneRepository().setCloneAllBranches(true)
- .setDirectory(to).setURI(uri);
- if (provider != null) {
- clone.setCredentialsProvider(provider);
- }
- try (Git git = clone.call()) {
- Repository repo = git.getRepository();
- assertNotNull(repo.resolve("master"));
- assertNotEquals(db.getWorkTree(),
- git.getRepository().getWorkTree());
- assertTrue(new File(git.getRepository().getWorkTree(), "file.txt")
- .exists());
- return repo.getWorkTree();
- }
- }
-
- protected void pushTo(File localClone) throws Exception {
- pushTo(null, localClone);
- }
-
- protected void pushTo(CredentialsProvider provider, File localClone)
- throws Exception {
- RevCommit commit;
- File newFile = null;
- try (Git git = Git.open(localClone)) {
- // Write a new file and modify a file.
- Repository local = git.getRepository();
- newFile = File.createTempFile("new", "sshtest",
- local.getWorkTree());
- write(newFile, "something new");
- File existingFile = new File(local.getWorkTree(), "file.txt");
- write(existingFile, "something else");
- git.add().addFilepattern("file.txt")
- .addFilepattern(newFile.getName())
- .call();
- commit = git.commit().setMessage("Local commit").call();
- // Push
- PushCommand push = git.push().setPushAll();
- if (provider != null) {
- push.setCredentialsProvider(provider);
- }
- Iterable results = push.call();
- for (PushResult result : results) {
- for (RemoteRefUpdate u : result.getRemoteUpdates()) {
- assertEquals(
- "Could not update " + u.getRemoteName() + ' '
- + u.getMessage(),
- RemoteRefUpdate.Status.OK, u.getStatus());
- }
- }
- }
- // Now check "master" in the remote repo directly:
- assertEquals("Unexpected remote commit", commit, db.resolve("master"));
- assertEquals("Unexpected remote commit", commit,
- db.resolve(Constants.HEAD));
- File remoteFile = new File(db.getWorkTree(), newFile.getName());
- assertFalse("File should not exist on remote", remoteFile.exists());
- try (Git git = new Git(db)) {
- git.reset().setMode(ResetType.HARD).setRef(Constants.HEAD).call();
- }
- assertTrue("File does not exist on remote", remoteFile.exists());
- checkFile(remoteFile, "something new");
- }
-
- protected static class TestCredentialsProvider extends CredentialsProvider {
-
- private final List stringStore;
-
- private final Iterator strings;
-
- public TestCredentialsProvider(String... strings) {
- if (strings == null || strings.length == 0) {
- stringStore = Collections.emptyList();
- } else {
- stringStore = Arrays.asList(strings);
- }
- this.strings = stringStore.iterator();
- }
-
- @Override
- public boolean isInteractive() {
- return true;
- }
-
- @Override
- public boolean supports(CredentialItem... items) {
- return true;
- }
-
- @Override
- public boolean get(URIish uri, CredentialItem... items)
- throws UnsupportedCredentialItem {
- System.out.println("URI: " + uri);
- for (CredentialItem item : items) {
- System.out.println(item.getClass().getSimpleName() + ' '
- + item.getPromptText());
- }
- logItems(uri, items);
- for (CredentialItem item : items) {
- if (item instanceof CredentialItem.InformationalMessage) {
- continue;
- }
- if (item instanceof CredentialItem.YesNoType) {
- ((CredentialItem.YesNoType) item).setValue(true);
- } else if (item instanceof CredentialItem.CharArrayType) {
- if (strings.hasNext()) {
- ((CredentialItem.CharArrayType) item)
- .setValue(strings.next().toCharArray());
- } else {
- return false;
- }
- } else if (item instanceof CredentialItem.StringType) {
- if (strings.hasNext()) {
- ((CredentialItem.StringType) item)
- .setValue(strings.next());
- } else {
- return false;
- }
- } else {
- return false;
- }
- }
- return true;
- }
-
- private List log = new ArrayList<>();
-
- private void logItems(URIish uri, CredentialItem... items) {
- log.add(new LogEntry(uri, Arrays.asList(items)));
- }
-
- public List getLog() {
- return log;
- }
- }
-
- protected static class LogEntry {
-
- private URIish uri;
-
- private List items;
-
- public LogEntry(URIish uri, List items) {
- this.uri = uri;
- this.items = items;
- }
-
- public URIish getURIish() {
- return uri;
- }
-
- public List getItems() {
- return items;
- }
- }
-}
diff --git a/org.eclipse.jgit.test/tests.bzl b/org.eclipse.jgit.test/tests.bzl
index d030316452..34df07d5e6 100644
--- a/org.eclipse.jgit.test/tests.bzl
+++ b/org.eclipse.jgit.test/tests.bzl
@@ -34,26 +34,10 @@ def tests(tests):
additional_deps = [
"//org.eclipse.jgit:insecure_cipher_factory",
]
- if src.endswith("OpenSshConfigTest.java"):
- additional_deps = [
- "//lib:jsch",
- ]
- if src.endswith("JschConfigSessionFactoryTest.java"):
- additional_deps = [
- "//lib:jsch",
- ]
if src.endswith("SecurityManagerMissingPermissionsTest.java"):
additional_deps = [
"//lib:log4j",
]
- if src.endswith("JSchSshTest.java"):
- additional_deps = [
- "//lib:jsch",
- "//lib:jzlib",
- "//lib:sshd-osgi",
- "//lib:sshd-sftp",
- ":sshd-helpers",
- ]
if src.endswith("JDKHttpConnectionTest.java"):
additional_deps = [
"//lib:mockito",
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/JSchSshTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/JSchSshTest.java
deleted file mode 100644
index 52d21d355b..0000000000
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/JSchSshTest.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2018, Thomas Wolf and others
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Distribution License v. 1.0 which is available at
- * https://www.eclipse.org/org/documents/edl-v10.php.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-package org.eclipse.jgit.transport;
-
-import static org.junit.Assert.assertTrue;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.nio.file.Files;
-import java.util.Arrays;
-
-import org.eclipse.jgit.errors.TransportException;
-import org.eclipse.jgit.lib.Constants;
-import org.eclipse.jgit.transport.OpenSshConfig.Host;
-import org.eclipse.jgit.transport.ssh.SshTestBase;
-import org.eclipse.jgit.util.FS;
-import org.junit.experimental.theories.Theories;
-import org.junit.runner.RunWith;
-
-import com.jcraft.jsch.JSch;
-import com.jcraft.jsch.JSchException;
-import com.jcraft.jsch.Session;
-
-@RunWith(Theories.class)
-public class JSchSshTest extends SshTestBase {
-
- private class TestSshSessionFactory extends JschConfigSessionFactory {
-
- @Override
- protected void configure(Host hc, Session session) {
- // Nothing
- }
-
- @Override
- public synchronized RemoteSession getSession(URIish uri,
- CredentialsProvider credentialsProvider, FS fs, int tms)
- throws TransportException {
- return super.getSession(uri, credentialsProvider, fs, tms);
- }
-
- @Override
- protected JSch createDefaultJSch(FS fs) throws JSchException {
- JSch defaultJSch = super.createDefaultJSch(fs);
- if (knownHosts.exists()) {
- defaultJSch.setKnownHosts(knownHosts.getAbsolutePath());
- }
- return defaultJSch;
- }
- }
-
- @Override
- protected SshSessionFactory createSessionFactory() {
- return new TestSshSessionFactory();
- }
-
- @Override
- protected void installConfig(String... config) {
- SshSessionFactory factory = getSessionFactory();
- assertTrue(factory instanceof JschConfigSessionFactory);
- JschConfigSessionFactory j = (JschConfigSessionFactory) factory;
- try {
- j.setConfig(createConfig(config));
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- private OpenSshConfig createConfig(String... content) throws IOException {
- File configFile = new File(sshDir, Constants.CONFIG);
- if (content != null) {
- Files.write(configFile.toPath(), Arrays.asList(content));
- }
- return new OpenSshConfig(getTemporaryDirectory(), configFile);
- }
-
-}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/JschConfigSessionFactoryTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/JschConfigSessionFactoryTest.java
deleted file mode 100644
index 5618be0790..0000000000
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/JschConfigSessionFactoryTest.java
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * Copyright (C) 2018, Thomas Wolf and others
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Distribution License v. 1.0 which is available at
- * https://www.eclipse.org/org/documents/edl-v10.php.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-package org.eclipse.jgit.transport;
-
-import static org.junit.Assert.assertEquals;
-
-import java.io.File;
-import java.nio.file.Files;
-import java.util.Arrays;
-import java.util.concurrent.TimeUnit;
-
-import org.eclipse.jgit.junit.MockSystemReader;
-import org.eclipse.jgit.util.FS;
-import org.eclipse.jgit.util.SystemReader;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.jcraft.jsch.Session;
-
-/**
- * Tests for correctly interpreting ssh config values when Jsch sessions are
- * used.
- */
-public class JschConfigSessionFactoryTest {
-
- File tmpConfigFile;
-
- OpenSshConfig tmpConfig;
-
- DefaultSshSessionFactory factory = new DefaultSshSessionFactory();
-
- @Before
- public void setup() {
- SystemReader.setInstance(new MockSystemReader());
- }
-
- @After
- public void removeTmpConfig() {
- SystemReader.setInstance(null);
- if (tmpConfigFile == null) {
- return;
- }
- if (tmpConfigFile.exists() && !tmpConfigFile.delete()) {
- tmpConfigFile.deleteOnExit();
- }
- tmpConfigFile = null;
- }
-
- @Test
- public void testNoConfigEntry() throws Exception {
- tmpConfigFile = File.createTempFile("jsch", "test");
- tmpConfig = new OpenSshConfig(tmpConfigFile.getParentFile(),
- tmpConfigFile);
- factory.setConfig(tmpConfig);
- Session session = createSession("ssh://egit/egit/egit");
- assertEquals("egit", session.getHost());
- // No user in URI, none in ssh config: default is OS user name
- assertEquals(SystemReader.getInstance().getProperty("user.name"),
- session.getUserName());
- assertEquals(22, session.getPort());
- }
-
- @Test
- public void testAlias() throws Exception {
- tmpConfigFile = createConfig("Host egit", "Hostname git.eclipse.org",
- "User foo", "Port 29418");
- tmpConfig = new OpenSshConfig(tmpConfigFile.getParentFile(),
- tmpConfigFile);
- factory.setConfig(tmpConfig);
- Session session = createSession("ssh://egit/egit/egit");
- assertEquals("git.eclipse.org", session.getHost());
- assertEquals("foo", session.getUserName());
- assertEquals(29418, session.getPort());
- }
-
- @Test
- public void testAliasWithUser() throws Exception {
- tmpConfigFile = createConfig("Host egit", "Hostname git.eclipse.org",
- "User foo", "Port 29418");
- tmpConfig = new OpenSshConfig(tmpConfigFile.getParentFile(),
- tmpConfigFile);
- factory.setConfig(tmpConfig);
- Session session = createSession("ssh://bar@egit/egit/egit");
- assertEquals("git.eclipse.org", session.getHost());
- assertEquals("bar", session.getUserName());
- assertEquals(29418, session.getPort());
- }
-
- @Test
- public void testAliasWithPort() throws Exception {
- tmpConfigFile = createConfig("Host egit", "Hostname git.eclipse.org",
- "User foo", "Port 29418");
- tmpConfig = new OpenSshConfig(tmpConfigFile.getParentFile(),
- tmpConfigFile);
- factory.setConfig(tmpConfig);
- Session session = createSession("ssh://bar@egit:22/egit/egit");
- assertEquals("git.eclipse.org", session.getHost());
- assertEquals("bar", session.getUserName());
- assertEquals(22, session.getPort());
- }
-
- @Test
- public void testAliasIdentical() throws Exception {
- tmpConfigFile = createConfig("Host git.eclipse.org",
- "Hostname git.eclipse.org", "User foo", "Port 29418");
- tmpConfig = new OpenSshConfig(tmpConfigFile.getParentFile(),
- tmpConfigFile);
- factory.setConfig(tmpConfig);
- Session session = createSession("ssh://git.eclipse.org/egit/egit");
- assertEquals("git.eclipse.org", session.getHost());
- assertEquals("foo", session.getUserName());
- assertEquals(29418, session.getPort());
- }
-
- @Test
- public void testAliasIdenticalWithUser() throws Exception {
- tmpConfigFile = createConfig("Host git.eclipse.org",
- "Hostname git.eclipse.org", "User foo", "Port 29418");
- tmpConfig = new OpenSshConfig(tmpConfigFile.getParentFile(),
- tmpConfigFile);
- factory.setConfig(tmpConfig);
- Session session = createSession("ssh://bar@git.eclipse.org/egit/egit");
- assertEquals("git.eclipse.org", session.getHost());
- assertEquals("bar", session.getUserName());
- assertEquals(29418, session.getPort());
- }
-
- @Test
- public void testAliasIdenticalWithPort() throws Exception {
- tmpConfigFile = createConfig("Host git.eclipse.org",
- "Hostname git.eclipse.org", "User foo", "Port 29418");
- tmpConfig = new OpenSshConfig(tmpConfigFile.getParentFile(),
- tmpConfigFile);
- factory.setConfig(tmpConfig);
- Session session = createSession(
- "ssh://bar@git.eclipse.org:300/egit/egit");
- assertEquals("git.eclipse.org", session.getHost());
- assertEquals("bar", session.getUserName());
- assertEquals(300, session.getPort());
- }
-
- @Test
- public void testConnectTimout() throws Exception {
- tmpConfigFile = createConfig("Host git.eclipse.org",
- "Hostname git.eclipse.org", "User foo", "Port 29418",
- "ConnectTimeout 10");
- tmpConfig = new OpenSshConfig(tmpConfigFile.getParentFile(),
- tmpConfigFile);
- factory.setConfig(tmpConfig);
- Session session = createSession("ssh://git.eclipse.org/something");
- assertEquals("git.eclipse.org", session.getHost());
- assertEquals("foo", session.getUserName());
- assertEquals(29418, session.getPort());
- assertEquals(TimeUnit.SECONDS.toMillis(10), session.getTimeout());
- }
-
- @Test
- public void testAliasCaseDifferenceUpcase() throws Exception {
- tmpConfigFile = createConfig("Host Bitbucket.org",
- "Hostname bitbucket.org", "User foo", "Port 29418",
- "ConnectTimeout 10", //
- "Host bitbucket.org", "Hostname bitbucket.org", "User bar",
- "Port 22", "ConnectTimeout 5");
- tmpConfig = new OpenSshConfig(tmpConfigFile.getParentFile(),
- tmpConfigFile);
- factory.setConfig(tmpConfig);
- Session session = createSession("ssh://Bitbucket.org/something");
- assertEquals("bitbucket.org", session.getHost());
- assertEquals("foo", session.getUserName());
- assertEquals(29418, session.getPort());
- assertEquals(TimeUnit.SECONDS.toMillis(10), session.getTimeout());
- }
-
- @Test
- public void testAliasCaseDifferenceLowcase() throws Exception {
- tmpConfigFile = createConfig("Host Bitbucket.org",
- "Hostname bitbucket.org", "User foo", "Port 29418",
- "ConnectTimeout 10", //
- "Host bitbucket.org", "Hostname bitbucket.org", "User bar",
- "Port 22", "ConnectTimeout 5");
- tmpConfig = new OpenSshConfig(tmpConfigFile.getParentFile(),
- tmpConfigFile);
- factory.setConfig(tmpConfig);
- Session session = createSession("ssh://bitbucket.org/something");
- assertEquals("bitbucket.org", session.getHost());
- assertEquals("bar", session.getUserName());
- assertEquals(22, session.getPort());
- assertEquals(TimeUnit.SECONDS.toMillis(5), session.getTimeout());
- }
-
- @Test
- public void testAliasCaseDifferenceUpcaseInverted() throws Exception {
- tmpConfigFile = createConfig("Host bitbucket.org",
- "Hostname bitbucket.org", "User bar", "Port 22",
- "ConnectTimeout 5", //
- "Host Bitbucket.org", "Hostname bitbucket.org", "User foo",
- "Port 29418", "ConnectTimeout 10");
- tmpConfig = new OpenSshConfig(tmpConfigFile.getParentFile(),
- tmpConfigFile);
- factory.setConfig(tmpConfig);
- Session session = createSession("ssh://Bitbucket.org/something");
- assertEquals("bitbucket.org", session.getHost());
- assertEquals("foo", session.getUserName());
- assertEquals(29418, session.getPort());
- assertEquals(TimeUnit.SECONDS.toMillis(10), session.getTimeout());
- }
-
- @Test
- public void testAliasCaseDifferenceLowcaseInverted() throws Exception {
- tmpConfigFile = createConfig("Host bitbucket.org",
- "Hostname bitbucket.org", "User bar", "Port 22",
- "ConnectTimeout 5", //
- "Host Bitbucket.org", "Hostname bitbucket.org", "User foo",
- "Port 29418", "ConnectTimeout 10");
- tmpConfig = new OpenSshConfig(tmpConfigFile.getParentFile(),
- tmpConfigFile);
- factory.setConfig(tmpConfig);
- Session session = createSession("ssh://bitbucket.org/something");
- assertEquals("bitbucket.org", session.getHost());
- assertEquals("bar", session.getUserName());
- assertEquals(22, session.getPort());
- assertEquals(TimeUnit.SECONDS.toMillis(5), session.getTimeout());
- }
-
- private File createConfig(String... lines) throws Exception {
- File f = File.createTempFile("jsch", "test");
- Files.write(f.toPath(), Arrays.asList(lines));
- return f;
- }
-
- private Session createSession(String uriText) throws Exception {
- // For this test to make sense, these few lines must correspond to the
- // code in JschConfigSessionFactory.getSession(). Because of
- // side-effects we cannot encapsulate that there properly and so we have
- // to duplicate this bit here. We also can't test getSession() itself
- // since it would try to actually connect to a server.
- URIish uri = new URIish(uriText);
- String host = uri.getHost();
- String user = uri.getUser();
- String password = uri.getPass();
- int port = uri.getPort();
- OpenSshConfig.Host hostConfig = tmpConfig.lookup(host);
- if (port <= 0) {
- port = hostConfig.getPort();
- }
- if (user == null) {
- user = hostConfig.getUser();
- }
- return factory.createSession(null, FS.DETECTED, user, password, host,
- port, hostConfig);
- }
-}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/OpenSshConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/OpenSshConfigTest.java
deleted file mode 100644
index d3cfacfbf3..0000000000
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/OpenSshConfigTest.java
+++ /dev/null
@@ -1,469 +0,0 @@
-/*
- * Copyright (C) 2008, 2017 Google Inc. and others
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Distribution License v. 1.0 which is available at
- * https://www.eclipse.org/org/documents/edl-v10.php.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-package org.eclipse.jgit.transport;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.time.Instant;
-import java.util.concurrent.TimeUnit;
-
-import org.eclipse.jgit.junit.RepositoryTestCase;
-import org.eclipse.jgit.lib.Constants;
-import org.eclipse.jgit.transport.OpenSshConfig.Host;
-import org.eclipse.jgit.util.FS;
-import org.eclipse.jgit.util.FileUtils;
-import org.eclipse.jgit.util.SystemReader;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.jcraft.jsch.ConfigRepository;
-import com.jcraft.jsch.ConfigRepository.Config;
-
-public class OpenSshConfigTest extends RepositoryTestCase {
- private File home;
-
- private File configFile;
-
- private OpenSshConfig osc;
-
- @Override
- @Before
- public void setUp() throws Exception {
- super.setUp();
-
- home = new File(trash, "home");
- FileUtils.mkdir(home);
-
- configFile = new File(new File(home, ".ssh"), Constants.CONFIG);
- FileUtils.mkdir(configFile.getParentFile());
-
- mockSystemReader.setProperty(Constants.OS_USER_NAME_KEY, "jex_junit");
- osc = new OpenSshConfig(home, configFile);
- }
-
- private void config(String data) throws IOException {
- FS fs = FS.DETECTED;
- long resolution = FS.getFileStoreAttributes(configFile.toPath())
- .getFsTimestampResolution().toNanos();
- Instant lastMtime = fs.lastModifiedInstant(configFile);
- do {
- try (final OutputStreamWriter fw = new OutputStreamWriter(
- new FileOutputStream(configFile), UTF_8)) {
- fw.write(data);
- TimeUnit.NANOSECONDS.sleep(resolution);
- } catch (InterruptedException e) {
- Thread.interrupted();
- }
- } while (lastMtime.equals(fs.lastModifiedInstant(configFile)));
- }
-
- @Test
- public void testNoConfig() {
- final Host h = osc.lookup("repo.or.cz");
- assertNotNull(h);
- assertEquals("repo.or.cz", h.getHostName());
- assertEquals("jex_junit", h.getUser());
- assertEquals(22, h.getPort());
- assertEquals(1, h.getConnectionAttempts());
- assertNull(h.getIdentityFile());
- }
-
- @Test
- public void testSeparatorParsing() throws Exception {
- config("Host\tfirst\n" +
- "\tHostName\tfirst.tld\n" +
- "\n" +
- "Host second\n" +
- " HostName\tsecond.tld\n" +
- "Host=third\n" +
- "HostName=third.tld\n\n\n" +
- "\t Host = fourth\n\n\n" +
- " \t HostName\t=fourth.tld\n" +
- "Host\t = last\n" +
- "HostName \t last.tld");
- assertNotNull(osc.lookup("first"));
- assertEquals("first.tld", osc.lookup("first").getHostName());
- assertNotNull(osc.lookup("second"));
- assertEquals("second.tld", osc.lookup("second").getHostName());
- assertNotNull(osc.lookup("third"));
- assertEquals("third.tld", osc.lookup("third").getHostName());
- assertNotNull(osc.lookup("fourth"));
- assertEquals("fourth.tld", osc.lookup("fourth").getHostName());
- assertNotNull(osc.lookup("last"));
- assertEquals("last.tld", osc.lookup("last").getHostName());
- }
-
- @Test
- public void testQuoteParsing() throws Exception {
- config("Host \"good\"\n" +
- " HostName=\"good.tld\"\n" +
- " Port=\"6007\"\n" +
- " User=\"gooduser\"\n" +
- "Host multiple unquoted and \"quoted\" \"hosts\"\n" +
- " Port=\"2222\"\n" +
- "Host \"spaced\"\n" +
- "# Bad host name, but testing preservation of spaces\n" +
- " HostName=\" spaced\ttld \"\n" +
- "# Misbalanced quotes\n" +
- "Host \"bad\"\n" +
- "# OpenSSH doesn't allow this but ...\n" +
- " HostName=bad.tld\"\n");
- assertEquals("good.tld", osc.lookup("good").getHostName());
- assertEquals("gooduser", osc.lookup("good").getUser());
- assertEquals(6007, osc.lookup("good").getPort());
- assertEquals(2222, osc.lookup("multiple").getPort());
- assertEquals(2222, osc.lookup("quoted").getPort());
- assertEquals(2222, osc.lookup("and").getPort());
- assertEquals(2222, osc.lookup("unquoted").getPort());
- assertEquals(2222, osc.lookup("hosts").getPort());
- assertEquals(" spaced\ttld ", osc.lookup("spaced").getHostName());
- assertEquals("bad.tld\"", osc.lookup("bad").getHostName());
- }
-
- @Test
- public void testCaseInsensitiveKeyLookup() throws Exception {
- config("Host orcz\n" + "Port 29418\n"
- + "\tHostName repo.or.cz\nStrictHostKeyChecking yes\n");
- final Host h = osc.lookup("orcz");
- Config c = h.getConfig();
- String exactCase = c.getValue("StrictHostKeyChecking");
- assertEquals("yes", exactCase);
- assertEquals(exactCase, c.getValue("stricthostkeychecking"));
- assertEquals(exactCase, c.getValue("STRICTHOSTKEYCHECKING"));
- assertEquals(exactCase, c.getValue("sTrIcThostKEYcheckING"));
- assertNull(c.getValue("sTrIcThostKEYcheckIN"));
- }
-
- @Test
- public void testAlias_DoesNotMatch() throws Exception {
- config("Host orcz\n" + "Port 29418\n" + "\tHostName repo.or.cz\n");
- final Host h = osc.lookup("repo.or.cz");
- assertNotNull(h);
- assertEquals("repo.or.cz", h.getHostName());
- assertEquals("jex_junit", h.getUser());
- assertEquals(22, h.getPort());
- assertNull(h.getIdentityFile());
- final Host h2 = osc.lookup("orcz");
- assertEquals("repo.or.cz", h.getHostName());
- assertEquals("jex_junit", h.getUser());
- assertEquals(29418, h2.getPort());
- assertNull(h.getIdentityFile());
- }
-
- @Test
- public void testAlias_OptionsSet() throws Exception {
- config("Host orcz\n" + "\tHostName repo.or.cz\n" + "\tPort 2222\n"
- + "\tUser jex\n" + "\tIdentityFile .ssh/id_jex\n"
- + "\tForwardX11 no\n");
- final Host h = osc.lookup("orcz");
- assertNotNull(h);
- assertEquals("repo.or.cz", h.getHostName());
- assertEquals("jex", h.getUser());
- assertEquals(2222, h.getPort());
- assertEquals(new File(home, ".ssh/id_jex"), h.getIdentityFile());
- }
-
- @Test
- public void testAlias_OptionsKeywordCaseInsensitive() throws Exception {
- config("hOsT orcz\n" + "\thOsTnAmE repo.or.cz\n" + "\tPORT 2222\n"
- + "\tuser jex\n" + "\tidentityfile .ssh/id_jex\n"
- + "\tForwardX11 no\n");
- final Host h = osc.lookup("orcz");
- assertNotNull(h);
- assertEquals("repo.or.cz", h.getHostName());
- assertEquals("jex", h.getUser());
- assertEquals(2222, h.getPort());
- assertEquals(new File(home, ".ssh/id_jex"), h.getIdentityFile());
- }
-
- @Test
- public void testAlias_OptionsInherit() throws Exception {
- config("Host orcz\n" + "\tHostName repo.or.cz\n" + "\n" + "Host *\n"
- + "\tHostName not.a.host.example.com\n" + "\tPort 2222\n"
- + "\tUser jex\n" + "\tIdentityFile .ssh/id_jex\n"
- + "\tForwardX11 no\n");
- final Host h = osc.lookup("orcz");
- assertNotNull(h);
- assertEquals("repo.or.cz", h.getHostName());
- assertEquals("jex", h.getUser());
- assertEquals(2222, h.getPort());
- assertEquals(new File(home, ".ssh/id_jex"), h.getIdentityFile());
- }
-
- @Test
- public void testAlias_PreferredAuthenticationsDefault() throws Exception {
- final Host h = osc.lookup("orcz");
- assertNotNull(h);
- assertNull(h.getPreferredAuthentications());
- }
-
- @Test
- public void testAlias_PreferredAuthentications() throws Exception {
- config("Host orcz\n" + "\tPreferredAuthentications publickey\n");
- final Host h = osc.lookup("orcz");
- assertNotNull(h);
- assertEquals("publickey", h.getPreferredAuthentications());
- }
-
- @Test
- public void testAlias_InheritPreferredAuthentications() throws Exception {
- config("Host orcz\n" + "\tHostName repo.or.cz\n" + "\n" + "Host *\n"
- + "\tPreferredAuthentications publickey, hostbased\n");
- final Host h = osc.lookup("orcz");
- assertNotNull(h);
- assertEquals("publickey,hostbased", h.getPreferredAuthentications());
- }
-
- @Test
- public void testAlias_BatchModeDefault() throws Exception {
- final Host h = osc.lookup("orcz");
- assertNotNull(h);
- assertFalse(h.isBatchMode());
- }
-
- @Test
- public void testAlias_BatchModeYes() throws Exception {
- config("Host orcz\n" + "\tBatchMode yes\n");
- final Host h = osc.lookup("orcz");
- assertNotNull(h);
- assertTrue(h.isBatchMode());
- }
-
- @Test
- public void testAlias_InheritBatchMode() throws Exception {
- config("Host orcz\n" + "\tHostName repo.or.cz\n" + "\n" + "Host *\n"
- + "\tBatchMode yes\n");
- final Host h = osc.lookup("orcz");
- assertNotNull(h);
- assertTrue(h.isBatchMode());
- }
-
- @Test
- public void testAlias_ConnectionAttemptsDefault() throws Exception {
- final Host h = osc.lookup("orcz");
- assertNotNull(h);
- assertEquals(1, h.getConnectionAttempts());
- }
-
- @Test
- public void testAlias_ConnectionAttempts() throws Exception {
- config("Host orcz\n" + "\tConnectionAttempts 5\n");
- final Host h = osc.lookup("orcz");
- assertNotNull(h);
- assertEquals(5, h.getConnectionAttempts());
- }
-
- @Test
- public void testAlias_invalidConnectionAttempts() throws Exception {
- config("Host orcz\n" + "\tConnectionAttempts -1\n");
- final Host h = osc.lookup("orcz");
- assertNotNull(h);
- assertEquals(1, h.getConnectionAttempts());
- }
-
- @Test
- public void testAlias_badConnectionAttempts() throws Exception {
- config("Host orcz\n" + "\tConnectionAttempts xxx\n");
- final Host h = osc.lookup("orcz");
- assertNotNull(h);
- assertEquals(1, h.getConnectionAttempts());
- }
-
- @Test
- public void testDefaultBlock() throws Exception {
- config("ConnectionAttempts 5\n\nHost orcz\nConnectionAttempts 3\n");
- final Host h = osc.lookup("orcz");
- assertNotNull(h);
- assertEquals(5, h.getConnectionAttempts());
- }
-
- @Test
- public void testHostCaseInsensitive() throws Exception {
- config("hOsT orcz\nConnectionAttempts 3\n");
- final Host h = osc.lookup("orcz");
- assertNotNull(h);
- assertEquals(3, h.getConnectionAttempts());
- }
-
- @Test
- public void testListValueSingle() throws Exception {
- config("Host orcz\nUserKnownHostsFile /foo/bar\n");
- final ConfigRepository.Config c = osc.getConfig("orcz");
- assertNotNull(c);
- assertEquals("/foo/bar", c.getValue("UserKnownHostsFile"));
- }
-
- @Test
- public void testListValueMultiple() throws Exception {
- // Tilde expansion occurs within the parser
- config("Host orcz\nUserKnownHostsFile \"~/foo/ba z\" /foo/bar \n");
- final ConfigRepository.Config c = osc.getConfig("orcz");
- assertNotNull(c);
- assertArrayEquals(new Object[] { new File(home, "foo/ba z").getPath(),
- "/foo/bar" },
- c.getValues("UserKnownHostsFile"));
- }
-
- @Test
- public void testRepeatedLookupsWithModification() throws Exception {
- config("Host orcz\n" + "\tConnectionAttempts -1\n");
- final Host h1 = osc.lookup("orcz");
- assertNotNull(h1);
- assertEquals(1, h1.getConnectionAttempts());
- config("Host orcz\n" + "\tConnectionAttempts 5\n");
- final Host h2 = osc.lookup("orcz");
- assertNotNull(h2);
- assertNotSame(h1, h2);
- assertEquals(5, h2.getConnectionAttempts());
- assertEquals(1, h1.getConnectionAttempts());
- assertNotSame(h1.getConfig(), h2.getConfig());
- }
-
- @Test
- public void testIdentityFile() throws Exception {
- config("Host orcz\nIdentityFile \"~/foo/ba z\"\nIdentityFile /foo/bar");
- final Host h = osc.lookup("orcz");
- assertNotNull(h);
- File f = h.getIdentityFile();
- assertNotNull(f);
- // Host does tilde replacement
- assertEquals(new File(home, "foo/ba z"), f);
- final ConfigRepository.Config c = h.getConfig();
- // Config does tilde replacement, too
- assertArrayEquals(new Object[] { new File(home, "foo/ba z").getPath(),
- "/foo/bar" },
- c.getValues("IdentityFile"));
- }
-
- @Test
- public void testMultiIdentityFile() throws Exception {
- config("IdentityFile \"~/foo/ba z\"\nHost orcz\nIdentityFile /foo/bar\nHOST *\nIdentityFile /foo/baz");
- final Host h = osc.lookup("orcz");
- assertNotNull(h);
- File f = h.getIdentityFile();
- assertNotNull(f);
- // Host does tilde replacement
- assertEquals(new File(home, "foo/ba z"), f);
- final ConfigRepository.Config c = h.getConfig();
- // Config does tilde replacement, too
- assertArrayEquals(new Object[] { new File(home, "foo/ba z").getPath(),
- "/foo/bar", "/foo/baz" },
- c.getValues("IdentityFile"));
- }
-
- @Test
- public void testNegatedPattern() throws Exception {
- config("Host repo.or.cz\nIdentityFile ~/foo/bar\nHOST !*.or.cz\nIdentityFile /foo/baz");
- final Host h = osc.lookup("repo.or.cz");
- assertNotNull(h);
- assertEquals(new File(home, "foo/bar"), h.getIdentityFile());
- assertArrayEquals(new Object[] { new File(home, "foo/bar").getPath() },
- h.getConfig().getValues("IdentityFile"));
- }
-
- @Test
- public void testPattern() throws Exception {
- config("Host repo.or.cz\nIdentityFile ~/foo/bar\nHOST *.or.cz\nIdentityFile /foo/baz");
- final Host h = osc.lookup("repo.or.cz");
- assertNotNull(h);
- assertEquals(new File(home, "foo/bar"), h.getIdentityFile());
- assertArrayEquals(new Object[] { new File(home, "foo/bar").getPath(),
- "/foo/baz" },
- h.getConfig().getValues("IdentityFile"));
- }
-
- @Test
- public void testMultiHost() throws Exception {
- config("Host orcz *.or.cz\nIdentityFile ~/foo/bar\nHOST *.or.cz\nIdentityFile /foo/baz");
- final Host h1 = osc.lookup("repo.or.cz");
- assertNotNull(h1);
- assertEquals(new File(home, "foo/bar"), h1.getIdentityFile());
- assertArrayEquals(new Object[] { new File(home, "foo/bar").getPath(),
- "/foo/baz" },
- h1.getConfig().getValues("IdentityFile"));
- final Host h2 = osc.lookup("orcz");
- assertNotNull(h2);
- assertEquals(new File(home, "foo/bar"), h2.getIdentityFile());
- assertArrayEquals(new Object[] { new File(home, "foo/bar").getPath() },
- h2.getConfig().getValues("IdentityFile"));
- }
-
- @Test
- public void testEqualsSign() throws Exception {
- config("Host=orcz\n\tConnectionAttempts = 5\n\tUser=\t foobar\t\n");
- final Host h = osc.lookup("orcz");
- assertNotNull(h);
- assertEquals(5, h.getConnectionAttempts());
- assertEquals("foobar", h.getUser());
- }
-
- @Test
- public void testMissingArgument() throws Exception {
- config("Host=orcz\n\tSendEnv\nIdentityFile\t\nForwardX11\n\tUser=\t foobar\t\n");
- final Host h = osc.lookup("orcz");
- assertNotNull(h);
- assertEquals("foobar", h.getUser());
- assertArrayEquals(new String[0], h.getConfig().getValues("SendEnv"));
- assertNull(h.getIdentityFile());
- assertNull(h.getConfig().getValue("ForwardX11"));
- }
-
- @Test
- public void testHomeDirUserReplacement() throws Exception {
- config("Host=orcz\n\tIdentityFile %d/.ssh/%u_id_dsa");
- final Host h = osc.lookup("orcz");
- assertNotNull(h);
- assertEquals(new File(new File(home, ".ssh"), "jex_junit_id_dsa"),
- h.getIdentityFile());
- }
-
- @Test
- public void testHostnameReplacement() throws Exception {
- config("Host=orcz\nHost *.*\n\tHostname %h\nHost *\n\tHostname %h.example.org");
- final Host h = osc.lookup("orcz");
- assertNotNull(h);
- assertEquals("orcz.example.org", h.getHostName());
- }
-
- @Test
- public void testRemoteUserReplacement() throws Exception {
- config("Host=orcz\n\tUser foo\n" + "Host *.*\n\tHostname %h\n"
- + "Host *\n\tHostname %h.ex%%20ample.org\n\tIdentityFile ~/.ssh/%h_%r_id_dsa");
- final Host h = osc.lookup("orcz");
- assertNotNull(h);
- assertEquals(
- new File(new File(home, ".ssh"),
- "orcz.ex%20ample.org_foo_id_dsa"),
- h.getIdentityFile());
- }
-
- @Test
- public void testLocalhostFQDNReplacement() throws Exception {
- String localhost = SystemReader.getInstance().getHostname();
- config("Host=orcz\n\tIdentityFile ~/.ssh/%l_id_dsa");
- final Host h = osc.lookup("orcz");
- assertNotNull(h);
- assertEquals(
- new File(new File(home, ".ssh"), localhost + "_id_dsa"),
- h.getIdentityFile());
- }
-}
diff --git a/org.eclipse.jgit/.settings/.api_filters b/org.eclipse.jgit/.settings/.api_filters
index be1d521aad..e2565bd6b3 100644
--- a/org.eclipse.jgit/.settings/.api_filters
+++ b/org.eclipse.jgit/.settings/.api_filters
@@ -1,5 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -8,6 +48,14 @@
+
+
+
+
+
+
+
+
diff --git a/org.eclipse.jgit/BUILD b/org.eclipse.jgit/BUILD
index 19aba52549..f7970976b0 100644
--- a/org.eclipse.jgit/BUILD
+++ b/org.eclipse.jgit/BUILD
@@ -21,8 +21,6 @@ java_library(
deps = [
":insecure_cipher_factory",
"//lib:javaewah",
- "//lib:jsch",
- "//lib:jzlib",
"//lib:slf4j-api",
],
)
diff --git a/org.eclipse.jgit/META-INF/MANIFEST.MF b/org.eclipse.jgit/META-INF/MANIFEST.MF
index 1479cf99a1..22454bad41 100644
--- a/org.eclipse.jgit/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit/META-INF/MANIFEST.MF
@@ -23,8 +23,12 @@ Export-Package: org.eclipse.jgit.annotations;version="5.8.0",
org.eclipse.jgit.revwalk.filter,
org.eclipse.jgit.blame,
org.eclipse.jgit.merge",
- org.eclipse.jgit.api.errors;version="5.8.0";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.errors",
- org.eclipse.jgit.attributes;version="5.8.0";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.treewalk",
+ org.eclipse.jgit.api.errors;version="5.8.0";
+ uses:="org.eclipse.jgit.lib,
+ org.eclipse.jgit.errors",
+ org.eclipse.jgit.attributes;version="5.8.0";
+ uses:="org.eclipse.jgit.lib,
+ org.eclipse.jgit.treewalk",
org.eclipse.jgit.blame;version="5.8.0";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.revwalk,
@@ -49,7 +53,8 @@ Export-Package: org.eclipse.jgit.annotations;version="5.8.0",
org.eclipse.jgit.dircache,
org.eclipse.jgit.lib,
org.eclipse.jgit.internal.storage.pack",
- org.eclipse.jgit.events;version="5.8.0";uses:="org.eclipse.jgit.lib",
+ org.eclipse.jgit.events;version="5.8.0";
+ uses:="org.eclipse.jgit.lib",
org.eclipse.jgit.fnmatch;version="5.8.0",
org.eclipse.jgit.gitrepo;version="5.8.0";
uses:="org.xml.sax.helpers,
@@ -60,10 +65,17 @@ Export-Package: org.eclipse.jgit.annotations;version="5.8.0",
org.eclipse.jgit.gitrepo.internal;version="5.8.0";x-internal:=true,
org.eclipse.jgit.hooks;version="5.8.0";uses:="org.eclipse.jgit.lib",
org.eclipse.jgit.ignore;version="5.8.0",
- org.eclipse.jgit.ignore.internal;version="5.8.0";x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal;version="5.8.0";x-friends:="org.eclipse.jgit.test,org.eclipse.jgit.http.test",
- org.eclipse.jgit.internal.fsck;version="5.8.0";x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.ketch;version="5.8.0";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
+ org.eclipse.jgit.ignore.internal;version="5.8.0";
+ x-friends:="org.eclipse.jgit.test",
+ org.eclipse.jgit.internal;version="5.8.0";
+ x-friends:="org.eclipse.jgit.test,
+ org.eclipse.jgit.http.test",
+ org.eclipse.jgit.internal.fsck;version="5.8.0";
+ x-friends:="org.eclipse.jgit.test",
+ org.eclipse.jgit.internal.ketch;version="5.8.0";
+ x-friends:="org.eclipse.jgit.junit,
+ org.eclipse.jgit.test,
+ org.eclipse.jgit.pgm",
org.eclipse.jgit.internal.revwalk;version="5.8.0";x-internal:=true,
org.eclipse.jgit.internal.storage.dfs;version="5.8.0";
x-friends:="org.eclipse.jgit.test,
@@ -79,19 +91,34 @@ Export-Package: org.eclipse.jgit.annotations;version="5.8.0",
org.eclipse.jgit.pgm,
org.eclipse.jgit.pgm.test,
org.eclipse.jgit.ssh.apache",
- org.eclipse.jgit.internal.storage.io;version="5.8.0";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.storage.pack;version="5.8.0";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
+ org.eclipse.jgit.internal.storage.io;version="5.8.0";
+ x-friends:="org.eclipse.jgit.junit,
+ org.eclipse.jgit.test,
+ org.eclipse.jgit.pgm",
+ org.eclipse.jgit.internal.storage.pack;version="5.8.0";
+ x-friends:="org.eclipse.jgit.junit,
+ org.eclipse.jgit.test,
+ org.eclipse.jgit.pgm",
org.eclipse.jgit.internal.storage.reftable;version="5.8.0";
x-friends:="org.eclipse.jgit.http.test,
org.eclipse.jgit.junit,
org.eclipse.jgit.test,
org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.storage.reftree;version="5.8.0";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
+ org.eclipse.jgit.internal.storage.reftree;version="5.8.0";
+ x-friends:="org.eclipse.jgit.junit,
+ org.eclipse.jgit.test,
+ org.eclipse.jgit.pgm",
org.eclipse.jgit.internal.submodule;version="5.8.0";x-internal:=true,
- org.eclipse.jgit.internal.transport.connectivity;version="5.8.0";x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.transport.http;version="5.8.0";x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.transport.parser;version="5.8.0";x-friends:="org.eclipse.jgit.http.server,org.eclipse.jgit.test",
- org.eclipse.jgit.internal.transport.ssh;version="5.8.0";x-friends:="org.eclipse.jgit.ssh.apache",
+ org.eclipse.jgit.internal.transport.connectivity;version="5.8.0";
+ x-friends:="org.eclipse.jgit.test",
+ org.eclipse.jgit.internal.transport.http;version="5.8.0";
+ x-friends:="org.eclipse.jgit.test",
+ org.eclipse.jgit.internal.transport.parser;version="5.8.0";
+ x-friends:="org.eclipse.jgit.http.server,
+ org.eclipse.jgit.test",
+ org.eclipse.jgit.internal.transport.ssh;version="5.8.0";
+ x-friends:="org.eclipse.jgit.ssh.apache,
+ org.eclipse.jgit.ssh.jsch",
org.eclipse.jgit.lib;version="5.8.0";
uses:="org.eclipse.jgit.transport,
org.eclipse.jgit.util.sha1,
@@ -106,7 +133,8 @@ Export-Package: org.eclipse.jgit.annotations;version="5.8.0",
org.eclipse.jgit.util,
org.eclipse.jgit.submodule,
org.eclipse.jgit.util.time",
- org.eclipse.jgit.lib.internal;version="5.8.0";x-friends:="org.eclipse.jgit.test",
+ org.eclipse.jgit.lib.internal;version="5.8.0";
+ x-friends:="org.eclipse.jgit.test",
org.eclipse.jgit.merge;version="5.8.0";
uses:="org.eclipse.jgit.dircache,
org.eclipse.jgit.lib,
@@ -122,17 +150,27 @@ Export-Package: org.eclipse.jgit.annotations;version="5.8.0",
org.eclipse.jgit.revwalk,
org.eclipse.jgit.treewalk,
org.eclipse.jgit.merge",
- org.eclipse.jgit.patch;version="5.8.0";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.diff",
- org.eclipse.jgit.revplot;version="5.8.0";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.revwalk",
+ org.eclipse.jgit.patch;version="5.8.0";
+ uses:="org.eclipse.jgit.lib,
+ org.eclipse.jgit.diff",
+ org.eclipse.jgit.revplot;version="5.8.0";
+ uses:="org.eclipse.jgit.lib,
+ org.eclipse.jgit.revwalk",
org.eclipse.jgit.revwalk;version="5.8.0";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.diff,
org.eclipse.jgit.treewalk.filter,
org.eclipse.jgit.revwalk.filter,
org.eclipse.jgit.treewalk",
- org.eclipse.jgit.revwalk.filter;version="5.8.0";uses:="org.eclipse.jgit.revwalk,org.eclipse.jgit.lib,org.eclipse.jgit.util",
- org.eclipse.jgit.storage.file;version="5.8.0";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.util",
- org.eclipse.jgit.storage.pack;version="5.8.0";uses:="org.eclipse.jgit.lib",
+ org.eclipse.jgit.revwalk.filter;version="5.8.0";
+ uses:="org.eclipse.jgit.revwalk,
+ org.eclipse.jgit.lib,
+ org.eclipse.jgit.util",
+ org.eclipse.jgit.storage.file;version="5.8.0";
+ uses:="org.eclipse.jgit.lib,
+ org.eclipse.jgit.util",
+ org.eclipse.jgit.storage.pack;version="5.8.0";
+ uses:="org.eclipse.jgit.lib",
org.eclipse.jgit.submodule;version="5.8.0";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.diff,
@@ -147,15 +185,16 @@ Export-Package: org.eclipse.jgit.annotations;version="5.8.0",
org.eclipse.jgit.transport.http,
org.eclipse.jgit.internal.storage.file,
org.eclipse.jgit.treewalk,
- org.eclipse.jgit.internal.transport.ssh,
org.eclipse.jgit.util,
org.eclipse.jgit.internal.storage.pack,
org.eclipse.jgit.transport.resolver,
org.eclipse.jgit.storage.pack,
- org.eclipse.jgit.errors,
- com.jcraft.jsch",
- org.eclipse.jgit.transport.http;version="5.8.0";uses:="javax.net.ssl",
- org.eclipse.jgit.transport.resolver;version="5.8.0";uses:="org.eclipse.jgit.transport,org.eclipse.jgit.lib",
+ org.eclipse.jgit.errors",
+ org.eclipse.jgit.transport.http;version="5.8.0";
+ uses:="javax.net.ssl",
+ org.eclipse.jgit.transport.resolver;version="5.8.0";
+ uses:="org.eclipse.jgit.transport,
+ org.eclipse.jgit.lib",
org.eclipse.jgit.treewalk;version="5.8.0";
uses:="org.eclipse.jgit.dircache,
org.eclipse.jgit.lib,
@@ -163,7 +202,8 @@ Export-Package: org.eclipse.jgit.annotations;version="5.8.0",
org.eclipse.jgit.revwalk,
org.eclipse.jgit.treewalk.filter,
org.eclipse.jgit.util",
- org.eclipse.jgit.treewalk.filter;version="5.8.0";uses:="org.eclipse.jgit.treewalk",
+ org.eclipse.jgit.treewalk.filter;version="5.8.0";
+ uses:="org.eclipse.jgit.treewalk",
org.eclipse.jgit.util;version="5.8.0";
uses:="org.eclipse.jgit.transport,
org.eclipse.jgit.hooks,
@@ -177,12 +217,14 @@ Export-Package: org.eclipse.jgit.annotations;version="5.8.0",
org.eclipse.jgit.treewalk,
javax.net.ssl,
org.eclipse.jgit.util.time",
- org.eclipse.jgit.util.io;version="5.8.0";uses:="org.eclipse.jgit.attributes,org.eclipse.jgit.lib,org.eclipse.jgit.treewalk",
+ org.eclipse.jgit.util.io;version="5.8.0";
+ uses:="org.eclipse.jgit.attributes,
+ org.eclipse.jgit.lib,
+ org.eclipse.jgit.treewalk",
org.eclipse.jgit.util.sha1;version="5.8.0",
org.eclipse.jgit.util.time;version="5.8.0"
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)",
- com.jcraft.jsch;version="[0.1.37,0.2.0)",
javax.crypto,
javax.net.ssl,
org.slf4j;version="[1.7.0,2.0.0)",
diff --git a/org.eclipse.jgit/pom.xml b/org.eclipse.jgit/pom.xml
index 025ab82a05..c73eddcd64 100644
--- a/org.eclipse.jgit/pom.xml
+++ b/org.eclipse.jgit/pom.xml
@@ -36,16 +36,6 @@
-
- com.jcraft
- jsch
-
-
-
- com.jcraft
- jzlib
-
-
com.googlecode.javaewah
JavaEWAH
diff --git a/org.eclipse.jgit/resources/META-INF/services/org.eclipse.jgit.transport.SshSessionFactory b/org.eclipse.jgit/resources/META-INF/services/org.eclipse.jgit.transport.SshSessionFactory
deleted file mode 100644
index 1f8828457b..0000000000
--- a/org.eclipse.jgit/resources/META-INF/services/org.eclipse.jgit.transport.SshSessionFactory
+++ /dev/null
@@ -1 +0,0 @@
-org.eclipse.jgit.transport.DefaultSshSessionFactory
diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
index c6e62b4404..e6da551bb7 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
@@ -621,7 +621,6 @@ sourceRefDoesntResolveToAnyObject=Source ref {0} doesn''t resolve to any object.
sourceRefNotSpecifiedForRefspec=Source ref not specified for refspec: {0}
squashCommitNotUpdatingHEAD=Squash commit -- not updating HEAD
sshCommandFailed=Execution of ssh command ''{0}'' failed with error ''{1}''
-sshUserNameError=Jsch error: failed to set SSH user name correctly to ''{0}''; using ''{1}'' picked up from SSH config file.
sslFailureExceptionMessage=Secure connection to {0} could not be established because of SSL problems
sslFailureInfo=A secure connection to {0} could not be established because the server''s certificate could not be validated.
sslFailureCause=SSL reported: {0}
@@ -682,7 +681,6 @@ transportProtoLocal=Local Git Repository
transportProtoSFTP=SFTP
transportProtoSSH=SSH
transportProtoTest=Test
-transportSSHRetryInterrupt=Interrupted while waiting for retry
treeEntryAlreadyExists=Tree entry "{0}" already exists.
treeFilterMarkerTooManyFilters=Too many markTreeFilters passed, maximum number is {0} (passed {1})
treeWalkMustHaveExactlyTwoTrees=TreeWalk should have exactly two trees.
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
index 9d122ba12f..782a3f872d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
@@ -649,7 +649,6 @@ public class JGitText extends TranslationBundle {
/***/ public String sourceRefNotSpecifiedForRefspec;
/***/ public String squashCommitNotUpdatingHEAD;
/***/ public String sshCommandFailed;
- /***/ public String sshUserNameError;
/***/ public String sslFailureExceptionMessage;
/***/ public String sslFailureInfo;
/***/ public String sslFailureCause;
@@ -710,7 +709,6 @@ public class JGitText extends TranslationBundle {
/***/ public String transportProtoSSH;
/***/ public String transportProtoTest;
/***/ public String transportProvidedRefWithNoObjectId;
- /***/ public String transportSSHRetryInterrupt;
/***/ public String treeEntryAlreadyExists;
/***/ public String treeFilterMarkerTooManyFilters;
/***/ public String treeWalkMustHaveExactlyTwoTrees;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/CredentialsProviderUserInfo.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/CredentialsProviderUserInfo.java
deleted file mode 100644
index 10646b9e7a..0000000000
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/CredentialsProviderUserInfo.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2010, Google Inc. and others
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Distribution License v. 1.0 which is available at
- * https://www.eclipse.org/org/documents/edl-v10.php.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-package org.eclipse.jgit.transport;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import com.jcraft.jsch.Session;
-import com.jcraft.jsch.UIKeyboardInteractive;
-import com.jcraft.jsch.UserInfo;
-
-/**
- * A JSch {@link com.jcraft.jsch.UserInfo} adapter for a
- * {@link org.eclipse.jgit.transport.CredentialsProvider}.
- */
-public class CredentialsProviderUserInfo implements UserInfo,
- UIKeyboardInteractive {
- private final URIish uri;
-
- private final CredentialsProvider provider;
-
- private String password;
-
- private String passphrase;
-
- /**
- * Wrap a CredentialsProvider to make it suitable for use with JSch.
- *
- * @param session
- * the JSch session this UserInfo will support authentication on.
- * @param credentialsProvider
- * the provider that will perform the authentication.
- */
- public CredentialsProviderUserInfo(Session session,
- CredentialsProvider credentialsProvider) {
- this.uri = createURI(session);
- this.provider = credentialsProvider;
- }
-
- private static URIish createURI(Session session) {
- URIish uri = new URIish();
- uri = uri.setScheme("ssh"); //$NON-NLS-1$
- uri = uri.setUser(session.getUserName());
- uri = uri.setHost(session.getHost());
- uri = uri.setPort(session.getPort());
- return uri;
- }
-
- /** {@inheritDoc} */
- @Override
- public String getPassword() {
- return password;
- }
-
- /** {@inheritDoc} */
- @Override
- public String getPassphrase() {
- return passphrase;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean promptPassphrase(String msg) {
- CredentialItem.StringType v = newPrompt(msg);
- if (provider.get(uri, v)) {
- passphrase = v.getValue();
- return true;
- }
- passphrase = null;
- return false;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean promptPassword(String msg) {
- CredentialItem.Password p = new CredentialItem.Password(msg);
- if (provider.get(uri, p)) {
- password = new String(p.getValue());
- return true;
- }
- password = null;
- return false;
- }
-
- private CredentialItem.StringType newPrompt(String msg) {
- return new CredentialItem.StringType(msg, true);
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean promptYesNo(String msg) {
- CredentialItem.YesNoType v = new CredentialItem.YesNoType(msg);
- return provider.get(uri, v) && v.getValue();
- }
-
- /** {@inheritDoc} */
- @Override
- public void showMessage(String msg) {
- provider.get(uri, new CredentialItem.InformationalMessage(msg));
- }
-
- /** {@inheritDoc} */
- @Override
- public String[] promptKeyboardInteractive(String destination, String name,
- String instruction, String[] prompt, boolean[] echo) {
- CredentialItem.StringType[] v = new CredentialItem.StringType[prompt.length];
- for (int i = 0; i < prompt.length; i++)
- v[i] = new CredentialItem.StringType(prompt[i], !echo[i]);
-
- List items = new ArrayList<>();
- if (instruction != null && instruction.length() > 0)
- items.add(new CredentialItem.InformationalMessage(instruction));
- items.addAll(Arrays.asList(v));
-
- if (!provider.get(uri, items))
- return null; // cancel
-
- String[] result = new String[v.length];
- for (int i = 0; i < v.length; i++)
- result[i] = v[i].getValue();
- return result;
- }
-}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/DefaultSshSessionFactory.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/DefaultSshSessionFactory.java
deleted file mode 100644
index afa0a11c24..0000000000
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/DefaultSshSessionFactory.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2009, Constantine Plotnikov
- * Copyright (C) 2009, Google Inc.
- * Copyright (C) 2008, Robin Rosenberg
- * Copyright (C) 2008, Shawn O. Pearce and others
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Distribution License v. 1.0 which is available at
- * https://www.eclipse.org/org/documents/edl-v10.php.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-package org.eclipse.jgit.transport;
-
-import com.jcraft.jsch.Session;
-
-/**
- * Loads known hosts and private keys from $HOME/.ssh
.
- *
- * This is the default implementation used by JGit and provides most of the
- * compatibility necessary to match OpenSSH, a popular implementation of SSH
- * used by C Git.
- *
- * If user interactivity is required by SSH (e.g. to obtain a password), the
- * connection will immediately fail.
- *
- * @since 5.7
- */
-public class DefaultSshSessionFactory extends JschConfigSessionFactory {
- /** {@inheritDoc} */
- @Override
- protected void configure(OpenSshConfig.Host hc, Session session) {
- // No additional configuration required.
- }
-}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschConfigSessionFactory.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschConfigSessionFactory.java
deleted file mode 100644
index 718c8f6115..0000000000
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschConfigSessionFactory.java
+++ /dev/null
@@ -1,530 +0,0 @@
-/*
- * Copyright (C) 2018, Sasa Zivkov
- * Copyright (C) 2016, Mark Ingram
- * Copyright (C) 2009, Constantine Plotnikov
- * Copyright (C) 2008-2009, Google Inc.
- * Copyright (C) 2009, Google, Inc.
- * Copyright (C) 2009, JetBrains s.r.o.
- * Copyright (C) 2008, Robin Rosenberg
- * Copyright (C) 2008, Shawn O. Pearce and others
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Distribution License v. 1.0 which is available at
- * https://www.eclipse.org/org/documents/edl-v10.php.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-package org.eclipse.jgit.transport;
-
-import static java.util.stream.Collectors.joining;
-import static java.util.stream.Collectors.toList;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.net.ConnectException;
-import java.net.UnknownHostException;
-import java.text.MessageFormat;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Stream;
-
-import org.eclipse.jgit.errors.TransportException;
-import org.eclipse.jgit.internal.JGitText;
-import org.eclipse.jgit.util.FS;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.jcraft.jsch.ConfigRepository;
-import com.jcraft.jsch.ConfigRepository.Config;
-import com.jcraft.jsch.HostKey;
-import com.jcraft.jsch.HostKeyRepository;
-import com.jcraft.jsch.JSch;
-import com.jcraft.jsch.JSchException;
-import com.jcraft.jsch.Session;
-
-/**
- * The base session factory that loads known hosts and private keys from
- * $HOME/.ssh
.
- *
- * This is the default implementation used by JGit and provides most of the
- * compatibility necessary to match OpenSSH, a popular implementation of SSH
- * used by C Git.
- *
- * The factory does not provide UI behavior. Override the method
- * {@link #configure(org.eclipse.jgit.transport.OpenSshConfig.Host, Session)} to
- * supply appropriate {@link com.jcraft.jsch.UserInfo} to the session.
- */
-public abstract class JschConfigSessionFactory extends SshSessionFactory {
-
- private static final Logger LOG = LoggerFactory
- .getLogger(JschConfigSessionFactory.class);
-
- /**
- * We use different Jsch instances for hosts that have an IdentityFile
- * configured in ~/.ssh/config. Jsch by default would cache decrypted keys
- * only per session, which results in repeated password prompts. Using
- * different Jsch instances, we can cache the keys on these instances so
- * that they will be re-used for successive sessions, and thus the user is
- * prompted for a key password only once while Eclipse runs.
- */
- private final Map byIdentityFile = new HashMap<>();
-
- private JSch defaultJSch;
-
- private OpenSshConfig config;
-
- /** {@inheritDoc} */
- @Override
- public synchronized RemoteSession getSession(URIish uri,
- CredentialsProvider credentialsProvider, FS fs, int tms)
- throws TransportException {
-
- String user = uri.getUser();
- final String pass = uri.getPass();
- String host = uri.getHost();
- int port = uri.getPort();
-
- try {
- if (config == null)
- config = OpenSshConfig.get(fs);
-
- final OpenSshConfig.Host hc = config.lookup(host);
- if (port <= 0)
- port = hc.getPort();
- if (user == null)
- user = hc.getUser();
-
- Session session = createSession(credentialsProvider, fs, user,
- pass, host, port, hc);
-
- int retries = 0;
- while (!session.isConnected()) {
- try {
- retries++;
- session.connect(tms);
- } catch (JSchException e) {
- session.disconnect();
- session = null;
- // Make sure our known_hosts is not outdated
- knownHosts(getJSch(hc, fs), fs);
-
- if (isAuthenticationCanceled(e)) {
- throw e;
- } else if (isAuthenticationFailed(e)
- && credentialsProvider != null) {
- // if authentication failed maybe credentials changed at
- // the remote end therefore reset credentials and retry
- if (retries < 3) {
- credentialsProvider.reset(uri);
- session = createSession(credentialsProvider, fs,
- user, pass, host, port, hc);
- } else
- throw e;
- } else if (retries >= hc.getConnectionAttempts()) {
- throw e;
- } else {
- try {
- Thread.sleep(1000);
- session = createSession(credentialsProvider, fs,
- user, pass, host, port, hc);
- } catch (InterruptedException e1) {
- throw new TransportException(
- JGitText.get().transportSSHRetryInterrupt,
- e1);
- }
- }
- }
- }
-
- return new JschSession(session, uri);
-
- } catch (JSchException je) {
- final Throwable c = je.getCause();
- if (c instanceof UnknownHostException) {
- throw new TransportException(uri, JGitText.get().unknownHost,
- je);
- }
- if (c instanceof ConnectException) {
- throw new TransportException(uri, c.getMessage(), je);
- }
- throw new TransportException(uri, je.getMessage(), je);
- }
-
- }
-
- private static boolean isAuthenticationFailed(JSchException e) {
- return e.getCause() == null && e.getMessage().equals("Auth fail"); //$NON-NLS-1$
- }
-
- private static boolean isAuthenticationCanceled(JSchException e) {
- return e.getCause() == null && e.getMessage().equals("Auth cancel"); //$NON-NLS-1$
- }
-
- // Package visibility for tests
- Session createSession(CredentialsProvider credentialsProvider,
- FS fs, String user, final String pass, String host, int port,
- final OpenSshConfig.Host hc) throws JSchException {
- final Session session = createSession(hc, user, host, port, fs);
- // Jsch will have overridden the explicit user by the one from the SSH
- // config file...
- setUserName(session, user);
- // Jsch will also have overridden the port.
- if (port > 0 && port != session.getPort()) {
- session.setPort(port);
- }
- // We retry already in getSession() method. JSch must not retry
- // on its own.
- session.setConfig("MaxAuthTries", "1"); //$NON-NLS-1$ //$NON-NLS-2$
- if (pass != null)
- session.setPassword(pass);
- final String strictHostKeyCheckingPolicy = hc
- .getStrictHostKeyChecking();
- if (strictHostKeyCheckingPolicy != null)
- session.setConfig("StrictHostKeyChecking", //$NON-NLS-1$
- strictHostKeyCheckingPolicy);
- final String pauth = hc.getPreferredAuthentications();
- if (pauth != null)
- session.setConfig("PreferredAuthentications", pauth); //$NON-NLS-1$
- if (credentialsProvider != null
- && (!hc.isBatchMode() || !credentialsProvider.isInteractive())) {
- session.setUserInfo(new CredentialsProviderUserInfo(session,
- credentialsProvider));
- }
- safeConfig(session, hc.getConfig());
- if (hc.getConfig().getValue("HostKeyAlgorithms") == null) { //$NON-NLS-1$
- setPreferredKeyTypesOrder(session);
- }
- configure(hc, session);
- return session;
- }
-
- private void safeConfig(Session session, Config cfg) {
- // Ensure that Jsch checks all configured algorithms, not just its
- // built-in ones. Otherwise it may propose an algorithm for which it
- // doesn't have an implementation, and then run into an NPE if that
- // algorithm ends up being chosen.
- copyConfigValueToSession(session, cfg, "Ciphers", "CheckCiphers"); //$NON-NLS-1$ //$NON-NLS-2$
- copyConfigValueToSession(session, cfg, "KexAlgorithms", "CheckKexes"); //$NON-NLS-1$ //$NON-NLS-2$
- copyConfigValueToSession(session, cfg, "HostKeyAlgorithms", //$NON-NLS-1$
- "CheckSignatures"); //$NON-NLS-1$
- }
-
- private static void setPreferredKeyTypesOrder(Session session) {
- HostKeyRepository hkr = session.getHostKeyRepository();
- HostKey[] hostKeys = hkr.getHostKey(hostName(session), null);
-
- if (hostKeys == null) {
- return;
- }
-
- List known = Stream.of(hostKeys)
- .map(HostKey::getType)
- .collect(toList());
-
- if (!known.isEmpty()) {
- String serverHostKey = "server_host_key"; //$NON-NLS-1$
- String current = session.getConfig(serverHostKey);
- if (current == null) {
- session.setConfig(serverHostKey, String.join(",", known)); //$NON-NLS-1$
- return;
- }
-
- String knownFirst = Stream.concat(
- known.stream(),
- Stream.of(current.split(",")) //$NON-NLS-1$
- .filter(s -> !known.contains(s)))
- .collect(joining(",")); //$NON-NLS-1$
- session.setConfig(serverHostKey, knownFirst);
- }
- }
-
- private static String hostName(Session s) {
- if (s.getPort() == SshConstants.SSH_DEFAULT_PORT) {
- return s.getHost();
- }
- return String.format("[%s]:%d", s.getHost(), //$NON-NLS-1$
- Integer.valueOf(s.getPort()));
- }
-
- private void copyConfigValueToSession(Session session, Config cfg,
- String from, String to) {
- String value = cfg.getValue(from);
- if (value != null) {
- session.setConfig(to, value);
- }
- }
-
- private void setUserName(Session session, String userName) {
- // Jsch 0.1.54 picks up the user name from the ssh config, even if an
- // explicit user name was given! We must correct that if ~/.ssh/config
- // has a different user name.
- if (userName == null || userName.isEmpty()
- || userName.equals(session.getUserName())) {
- return;
- }
- try {
- Class>[] parameterTypes = { String.class };
- Method method = Session.class.getDeclaredMethod("setUserName", //$NON-NLS-1$
- parameterTypes);
- method.setAccessible(true);
- method.invoke(session, userName);
- } catch (NullPointerException | IllegalAccessException
- | IllegalArgumentException | InvocationTargetException
- | NoSuchMethodException | SecurityException e) {
- LOG.error(MessageFormat.format(JGitText.get().sshUserNameError,
- userName, session.getUserName()), e);
- }
- }
-
- /**
- * Create a new remote session for the requested address.
- *
- * @param hc
- * host configuration
- * @param user
- * login to authenticate as.
- * @param host
- * server name to connect to.
- * @param port
- * port number of the SSH daemon (typically 22).
- * @param fs
- * the file system abstraction which will be necessary to
- * perform certain file system operations.
- * @return new session instance, but otherwise unconfigured.
- * @throws com.jcraft.jsch.JSchException
- * the session could not be created.
- */
- protected Session createSession(final OpenSshConfig.Host hc,
- final String user, final String host, final int port, FS fs)
- throws JSchException {
- return getJSch(hc, fs).getSession(user, host, port);
- }
-
- /**
- * Provide additional configuration for the JSch instance. This method could
- * be overridden to supply a preferred
- * {@link com.jcraft.jsch.IdentityRepository}.
- *
- * @param jsch
- * jsch instance
- * @since 4.5
- */
- protected void configureJSch(JSch jsch) {
- // No additional configuration required.
- }
-
- /**
- * Provide additional configuration for the session based on the host
- * information. This method could be used to supply
- * {@link com.jcraft.jsch.UserInfo}.
- *
- * @param hc
- * host configuration
- * @param session
- * session to configure
- */
- protected abstract void configure(OpenSshConfig.Host hc, Session session);
-
- /**
- * Obtain the JSch used to create new sessions.
- *
- * @param hc
- * host configuration
- * @param fs
- * the file system abstraction which will be necessary to
- * perform certain file system operations.
- * @return the JSch instance to use.
- * @throws com.jcraft.jsch.JSchException
- * the user configuration could not be created.
- */
- protected JSch getJSch(OpenSshConfig.Host hc, FS fs) throws JSchException {
- if (defaultJSch == null) {
- defaultJSch = createDefaultJSch(fs);
- if (defaultJSch.getConfigRepository() == null) {
- defaultJSch.setConfigRepository(
- new JschBugFixingConfigRepository(config));
- }
- for (Object name : defaultJSch.getIdentityNames())
- byIdentityFile.put((String) name, defaultJSch);
- }
-
- final File identityFile = hc.getIdentityFile();
- if (identityFile == null)
- return defaultJSch;
-
- final String identityKey = identityFile.getAbsolutePath();
- JSch jsch = byIdentityFile.get(identityKey);
- if (jsch == null) {
- jsch = new JSch();
- configureJSch(jsch);
- if (jsch.getConfigRepository() == null) {
- jsch.setConfigRepository(defaultJSch.getConfigRepository());
- }
- jsch.setHostKeyRepository(defaultJSch.getHostKeyRepository());
- jsch.addIdentity(identityKey);
- byIdentityFile.put(identityKey, jsch);
- }
- return jsch;
- }
-
- /**
- * Create default instance of jsch
- *
- * @param fs
- * the file system abstraction which will be necessary to perform
- * certain file system operations.
- * @return the new default JSch implementation.
- * @throws com.jcraft.jsch.JSchException
- * known host keys cannot be loaded.
- */
- protected JSch createDefaultJSch(FS fs) throws JSchException {
- final JSch jsch = new JSch();
- JSch.setConfig("ssh-rsa", JSch.getConfig("signature.rsa")); //$NON-NLS-1$ //$NON-NLS-2$
- JSch.setConfig("ssh-dss", JSch.getConfig("signature.dss")); //$NON-NLS-1$ //$NON-NLS-2$
- configureJSch(jsch);
- knownHosts(jsch, fs);
- identities(jsch, fs);
- return jsch;
- }
-
- private static void knownHosts(JSch sch, FS fs) throws JSchException {
- final File home = fs.userHome();
- if (home == null)
- return;
- final File known_hosts = new File(new File(home, ".ssh"), "known_hosts"); //$NON-NLS-1$ //$NON-NLS-2$
- try (FileInputStream in = new FileInputStream(known_hosts)) {
- sch.setKnownHosts(in);
- } catch (FileNotFoundException none) {
- // Oh well. They don't have a known hosts in home.
- } catch (IOException err) {
- // Oh well. They don't have a known hosts in home.
- }
- }
-
- private static void identities(JSch sch, FS fs) {
- final File home = fs.userHome();
- if (home == null)
- return;
- final File sshdir = new File(home, ".ssh"); //$NON-NLS-1$
- if (sshdir.isDirectory()) {
- loadIdentity(sch, new File(sshdir, "identity")); //$NON-NLS-1$
- loadIdentity(sch, new File(sshdir, "id_rsa")); //$NON-NLS-1$
- loadIdentity(sch, new File(sshdir, "id_dsa")); //$NON-NLS-1$
- }
- }
-
- private static void loadIdentity(JSch sch, File priv) {
- if (priv.isFile()) {
- try {
- sch.addIdentity(priv.getAbsolutePath());
- } catch (JSchException e) {
- // Instead, pretend the key doesn't exist.
- }
- }
- }
-
- private static class JschBugFixingConfigRepository
- implements ConfigRepository {
-
- private final ConfigRepository base;
-
- public JschBugFixingConfigRepository(ConfigRepository base) {
- this.base = base;
- }
-
- @Override
- public Config getConfig(String host) {
- return new JschBugFixingConfig(base.getConfig(host));
- }
-
- /**
- * A {@link com.jcraft.jsch.ConfigRepository.Config} that transforms
- * some values from the config file into the format Jsch 0.1.54 expects.
- * This is a work-around for bugs in Jsch.
- *
- * Additionally, this config hides the IdentityFile config entries from
- * Jsch; we manage those ourselves. Otherwise Jsch would cache passwords
- * (or rather, decrypted keys) only for a single session, resulting in
- * multiple password prompts for user operations that use several Jsch
- * sessions.
- */
- private static class JschBugFixingConfig implements Config {
-
- private static final String[] NO_IDENTITIES = {};
-
- private final Config real;
-
- public JschBugFixingConfig(Config delegate) {
- real = delegate;
- }
-
- @Override
- public String getHostname() {
- return real.getHostname();
- }
-
- @Override
- public String getUser() {
- return real.getUser();
- }
-
- @Override
- public int getPort() {
- return real.getPort();
- }
-
- @Override
- public String getValue(String key) {
- String k = key.toUpperCase(Locale.ROOT);
- if ("IDENTITYFILE".equals(k)) { //$NON-NLS-1$
- return null;
- }
- String result = real.getValue(key);
- if (result != null) {
- if ("SERVERALIVEINTERVAL".equals(k) //$NON-NLS-1$
- || "CONNECTTIMEOUT".equals(k)) { //$NON-NLS-1$
- // These values are in seconds. Jsch 0.1.54 passes them
- // on as is to java.net.Socket.setSoTimeout(), which
- // expects milliseconds. So convert here to
- // milliseconds.
- try {
- int timeout = Integer.parseInt(result);
- result = Long.toString(
- TimeUnit.SECONDS.toMillis(timeout));
- } catch (NumberFormatException e) {
- // Ignore
- }
- }
- }
- return result;
- }
-
- @Override
- public String[] getValues(String key) {
- String k = key.toUpperCase(Locale.ROOT);
- if ("IDENTITYFILE".equals(k)) { //$NON-NLS-1$
- return NO_IDENTITIES;
- }
- return real.getValues(key);
- }
- }
- }
-
- /**
- * Set the {@link OpenSshConfig} to use. Intended for use in tests.
- *
- * @param config
- * to use
- */
- synchronized void setConfig(OpenSshConfig config) {
- this.config = config;
- }
-}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschSession.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschSession.java
deleted file mode 100644
index d7270343cb..0000000000
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschSession.java
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
- * Copyright (C) 2009, Constantine Plotnikov
- * Copyright (C) 2008-2009, Google Inc.
- * Copyright (C) 2009, Google, Inc.
- * Copyright (C) 2009, JetBrains s.r.o.
- * Copyright (C) 2008, Robin Rosenberg
- * Copyright (C) 2008, Shawn O. Pearce and others
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Distribution License v. 1.0 which is available at
- * https://www.eclipse.org/org/documents/edl-v10.php.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-package org.eclipse.jgit.transport;
-
-import java.io.BufferedOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.TimeUnit;
-
-import org.eclipse.jgit.errors.TransportException;
-import org.eclipse.jgit.internal.JGitText;
-import org.eclipse.jgit.util.io.IsolatedOutputStream;
-
-import com.jcraft.jsch.Channel;
-import com.jcraft.jsch.ChannelExec;
-import com.jcraft.jsch.ChannelSftp;
-import com.jcraft.jsch.JSchException;
-import com.jcraft.jsch.Session;
-import com.jcraft.jsch.SftpException;
-
-/**
- * Run remote commands using Jsch.
- *
- * This class is the default session implementation using Jsch. Note that
- * {@link org.eclipse.jgit.transport.JschConfigSessionFactory} is used to create
- * the actual session passed to the constructor.
- */
-public class JschSession implements RemoteSession {
- final Session sock;
- final URIish uri;
-
- /**
- * Create a new session object by passing the real Jsch session and the URI
- * information.
- *
- * @param session
- * the real Jsch session created elsewhere.
- * @param uri
- * the URI information for the remote connection
- */
- public JschSession(Session session, URIish uri) {
- sock = session;
- this.uri = uri;
- }
-
- /** {@inheritDoc} */
- @Override
- public Process exec(String command, int timeout) throws IOException {
- return new JschProcess(command, timeout);
- }
-
- /** {@inheritDoc} */
- @Override
- public void disconnect() {
- if (sock.isConnected())
- sock.disconnect();
- }
-
- /**
- * A kludge to allow {@link org.eclipse.jgit.transport.TransportSftp} to get
- * an Sftp channel from Jsch. Ideally, this method would be generic, which
- * would require implementing generic Sftp channel operations in the
- * RemoteSession class.
- *
- * @return a channel suitable for Sftp operations.
- * @throws com.jcraft.jsch.JSchException
- * on problems getting the channel.
- * @deprecated since 5.2; use {@link #getFtpChannel()} instead
- */
- @Deprecated
- public Channel getSftpChannel() throws JSchException {
- return sock.openChannel("sftp"); //$NON-NLS-1$
- }
-
- /**
- * {@inheritDoc}
- *
- * @since 5.2
- */
- @Override
- public FtpChannel getFtpChannel() {
- return new JschFtpChannel();
- }
-
- /**
- * Implementation of Process for running a single command using Jsch.
- *
- * Uses the Jsch session to do actual command execution and manage the
- * execution.
- */
- private class JschProcess extends Process {
- private ChannelExec channel;
-
- final int timeout;
-
- private InputStream inputStream;
-
- private OutputStream outputStream;
-
- private InputStream errStream;
-
- /**
- * Opens a channel on the session ("sock") for executing the given
- * command, opens streams, and starts command execution.
- *
- * @param commandName
- * the command to execute
- * @param tms
- * the timeout value, in seconds, for the command.
- * @throws TransportException
- * on problems opening a channel or connecting to the remote
- * host
- * @throws IOException
- * on problems opening streams
- */
- JschProcess(String commandName, int tms)
- throws TransportException, IOException {
- timeout = tms;
- try {
- channel = (ChannelExec) sock.openChannel("exec"); //$NON-NLS-1$
- channel.setCommand(commandName);
- setupStreams();
- channel.connect(timeout > 0 ? timeout * 1000 : 0);
- if (!channel.isConnected()) {
- closeOutputStream();
- throw new TransportException(uri,
- JGitText.get().connectionFailed);
- }
- } catch (JSchException e) {
- closeOutputStream();
- throw new TransportException(uri, e.getMessage(), e);
- }
- }
-
- private void closeOutputStream() {
- if (outputStream != null) {
- try {
- outputStream.close();
- } catch (IOException ioe) {
- // ignore
- }
- }
- }
-
- private void setupStreams() throws IOException {
- inputStream = channel.getInputStream();
-
- // JSch won't let us interrupt writes when we use our InterruptTimer
- // to break out of a long-running write operation. To work around
- // that we spawn a background thread to shuttle data through a pipe,
- // as we can issue an interrupted write out of that. Its slower, so
- // we only use this route if there is a timeout.
- OutputStream out = channel.getOutputStream();
- if (timeout <= 0) {
- outputStream = out;
- } else {
- IsolatedOutputStream i = new IsolatedOutputStream(out);
- outputStream = new BufferedOutputStream(i, 16 * 1024);
- }
-
- errStream = channel.getErrStream();
- }
-
- @Override
- public InputStream getInputStream() {
- return inputStream;
- }
-
- @Override
- public OutputStream getOutputStream() {
- return outputStream;
- }
-
- @Override
- public InputStream getErrorStream() {
- return errStream;
- }
-
- @Override
- public int exitValue() {
- if (isRunning())
- throw new IllegalStateException();
- return channel.getExitStatus();
- }
-
- private boolean isRunning() {
- return channel.getExitStatus() < 0 && channel.isConnected();
- }
-
- @Override
- public void destroy() {
- if (channel.isConnected())
- channel.disconnect();
- closeOutputStream();
- }
-
- @Override
- public int waitFor() throws InterruptedException {
- while (isRunning())
- Thread.sleep(100);
- return exitValue();
- }
- }
-
- private class JschFtpChannel implements FtpChannel {
-
- private ChannelSftp ftp;
-
- @Override
- public void connect(int timeout, TimeUnit unit) throws IOException {
- try {
- ftp = (ChannelSftp) sock.openChannel("sftp"); //$NON-NLS-1$
- ftp.connect((int) unit.toMillis(timeout));
- } catch (JSchException e) {
- ftp = null;
- throw new IOException(e.getLocalizedMessage(), e);
- }
- }
-
- @Override
- public void disconnect() {
- ftp.disconnect();
- ftp = null;
- }
-
- private T map(Callable op) throws IOException {
- try {
- return op.call();
- } catch (Exception e) {
- if (e instanceof SftpException) {
- throw new FtpChannel.FtpException(e.getLocalizedMessage(),
- ((SftpException) e).id, e);
- }
- throw new IOException(e.getLocalizedMessage(), e);
- }
- }
-
- @Override
- public boolean isConnected() {
- return ftp != null && sock.isConnected();
- }
-
- @Override
- public void cd(String path) throws IOException {
- map(() -> {
- ftp.cd(path);
- return null;
- });
- }
-
- @Override
- public String pwd() throws IOException {
- return map(() -> ftp.pwd());
- }
-
- @Override
- public Collection ls(String path) throws IOException {
- return map(() -> {
- List result = new ArrayList<>();
- for (Object e : ftp.ls(path)) {
- ChannelSftp.LsEntry entry = (ChannelSftp.LsEntry) e;
- result.add(new DirEntry() {
-
- @Override
- public String getFilename() {
- return entry.getFilename();
- }
-
- @Override
- public long getModifiedTime() {
- return entry.getAttrs().getMTime();
- }
-
- @Override
- public boolean isDirectory() {
- return entry.getAttrs().isDir();
- }
- });
- }
- return result;
- });
- }
-
- @Override
- public void rmdir(String path) throws IOException {
- map(() -> {
- ftp.rm(path);
- return null;
- });
- }
-
- @Override
- public void mkdir(String path) throws IOException {
- map(() -> {
- ftp.mkdir(path);
- return null;
- });
- }
-
- @Override
- public InputStream get(String path) throws IOException {
- return map(() -> ftp.get(path));
- }
-
- @Override
- public OutputStream put(String path) throws IOException {
- return map(() -> ftp.put(path));
- }
-
- @Override
- public void rm(String path) throws IOException {
- map(() -> {
- ftp.rm(path);
- return null;
- });
- }
-
- @Override
- public void rename(String from, String to) throws IOException {
- map(() -> {
- // Plain FTP rename will fail if "to" exists. Jsch knows about
- // the FTP extension "posix-rename@openssh.com", which will
- // remove "to" first if it exists.
- if (hasPosixRename()) {
- ftp.rename(from, to);
- } else if (!to.equals(from)) {
- // Try to remove "to" first. With git, we typically get this
- // when a lock file is moved over the file locked. Note that
- // the check for to being equal to from may still fail in
- // the general case, but for use with JGit's TransportSftp
- // it should be good enough.
- delete(to);
- ftp.rename(from, to);
- }
- return null;
- });
- }
-
- /**
- * Determine whether the server has the posix-rename extension.
- *
- * @return {@code true} if it is supported, {@code false} otherwise
- * @see OpenSSH
- * deviations and extensions to the published SSH protocol
- * @see stdio.h:
- * rename()
- */
- private boolean hasPosixRename() {
- return "1".equals(ftp.getExtension("posix-rename@openssh.com")); //$NON-NLS-1$//$NON-NLS-2$
- }
- }
-}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/OpenSshConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/OpenSshConfig.java
deleted file mode 100644
index a628897a59..0000000000
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/OpenSshConfig.java
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * Copyright (C) 2008, 2018, Google Inc. and others
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Distribution License v. 1.0 which is available at
- * https://www.eclipse.org/org/documents/edl-v10.php.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-package org.eclipse.jgit.transport;
-
-import static org.eclipse.jgit.internal.transport.ssh.OpenSshConfigFile.positive;
-
-import java.io.File;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-
-import org.eclipse.jgit.internal.transport.ssh.OpenSshConfigFile;
-import org.eclipse.jgit.internal.transport.ssh.OpenSshConfigFile.HostEntry;
-import org.eclipse.jgit.util.FS;
-
-import com.jcraft.jsch.ConfigRepository;
-
-/**
- * Fairly complete configuration parser for the OpenSSH ~/.ssh/config file.
- *
- * JSch does have its own config file parser
- * {@link com.jcraft.jsch.OpenSSHConfig} since version 0.1.50, but it has a
- * number of problems:
- *
- * - it splits lines of the format "keyword = value" wrongly: you'd end up
- * with the value "= value".
- *
- its "Host" keyword is not case insensitive.
- *
- it doesn't handle quoted values.
- *
- JSch's OpenSSHConfig doesn't monitor for config file changes.
- *
- *
- * This parser makes the critical options available to
- * {@link org.eclipse.jgit.transport.SshSessionFactory} via
- * {@link org.eclipse.jgit.transport.OpenSshConfig.Host} objects returned by
- * {@link #lookup(String)}, and implements a fully conforming
- * {@link com.jcraft.jsch.ConfigRepository} providing
- * {@link com.jcraft.jsch.ConfigRepository.Config}s via
- * {@link #getConfig(String)}.
- *
- *
- * @see OpenSshConfigFile
- */
-public class OpenSshConfig implements ConfigRepository {
-
- /**
- * Obtain the user's configuration data.
- *
- * The configuration file is always returned to the caller, even if no file
- * exists in the user's home directory at the time the call was made. Lookup
- * requests are cached and are automatically updated if the user modifies
- * the configuration file since the last time it was cached.
- *
- * @param fs
- * the file system abstraction which will be necessary to
- * perform certain file system operations.
- * @return a caching reader of the user's configuration file.
- */
- public static OpenSshConfig get(FS fs) {
- File home = fs.userHome();
- if (home == null)
- home = new File(".").getAbsoluteFile(); //$NON-NLS-1$
-
- final File config = new File(new File(home, SshConstants.SSH_DIR),
- SshConstants.CONFIG);
- return new OpenSshConfig(home, config);
- }
-
- /** The base file. */
- private OpenSshConfigFile configFile;
-
- OpenSshConfig(File h, File cfg) {
- configFile = new OpenSshConfigFile(h, cfg,
- SshSessionFactory.getLocalUserName());
- }
-
- /**
- * Locate the configuration for a specific host request.
- *
- * @param hostName
- * the name the user has supplied to the SSH tool. This may be a
- * real host name, or it may just be a "Host" block in the
- * configuration file.
- * @return r configuration for the requested name. Never null.
- */
- public Host lookup(String hostName) {
- HostEntry entry = configFile.lookup(hostName, -1, null);
- return new Host(entry, hostName, configFile.getLocalUserName());
- }
-
- /**
- * Configuration of one "Host" block in the configuration file.
- *
- * If returned from {@link OpenSshConfig#lookup(String)} some or all of the
- * properties may not be populated. The properties which are not populated
- * should be defaulted by the caller.
- *
- * When returned from {@link OpenSshConfig#lookup(String)} any wildcard
- * entries which appear later in the configuration file will have been
- * already merged into this block.
- */
- public static class Host {
- String hostName;
-
- int port;
-
- File identityFile;
-
- String user;
-
- String preferredAuthentications;
-
- Boolean batchMode;
-
- String strictHostKeyChecking;
-
- int connectionAttempts;
-
- private HostEntry entry;
-
- private Config config;
-
- // See com.jcraft.jsch.OpenSSHConfig. Translates some command-line keys
- // to ssh-config keys.
- private static final Map KEY_MAP = new TreeMap<>(
- String.CASE_INSENSITIVE_ORDER);
-
- static {
- KEY_MAP.put("kex", SshConstants.KEX_ALGORITHMS); //$NON-NLS-1$
- KEY_MAP.put("server_host_key", SshConstants.HOST_KEY_ALGORITHMS); //$NON-NLS-1$
- KEY_MAP.put("cipher.c2s", SshConstants.CIPHERS); //$NON-NLS-1$
- KEY_MAP.put("cipher.s2c", SshConstants.CIPHERS); //$NON-NLS-1$
- KEY_MAP.put("mac.c2s", SshConstants.MACS); //$NON-NLS-1$
- KEY_MAP.put("mac.s2c", SshConstants.MACS); //$NON-NLS-1$
- KEY_MAP.put("compression.s2c", SshConstants.COMPRESSION); //$NON-NLS-1$
- KEY_MAP.put("compression.c2s", SshConstants.COMPRESSION); //$NON-NLS-1$
- KEY_MAP.put("compression_level", "CompressionLevel"); //$NON-NLS-1$ //$NON-NLS-2$
- KEY_MAP.put("MaxAuthTries", //$NON-NLS-1$
- SshConstants.NUMBER_OF_PASSWORD_PROMPTS);
- }
-
- private static String mapKey(String key) {
- String k = KEY_MAP.get(key);
- return k != null ? k : key;
- }
-
- /**
- * Creates a new uninitialized {@link Host}.
- */
- public Host() {
- // For API backwards compatibility with pre-4.9 JGit
- }
-
- Host(HostEntry entry, String hostName, String localUserName) {
- this.entry = entry;
- complete(hostName, localUserName);
- }
-
- /**
- * @return the value StrictHostKeyChecking property, the valid values
- * are "yes" (unknown hosts are not accepted), "no" (unknown
- * hosts are always accepted), and "ask" (user should be asked
- * before accepting the host)
- */
- public String getStrictHostKeyChecking() {
- return strictHostKeyChecking;
- }
-
- /**
- * @return the real IP address or host name to connect to; never null.
- */
- public String getHostName() {
- return hostName;
- }
-
- /**
- * @return the real port number to connect to; never 0.
- */
- public int getPort() {
- return port;
- }
-
- /**
- * @return path of the private key file to use for authentication; null
- * if the caller should use default authentication strategies.
- */
- public File getIdentityFile() {
- return identityFile;
- }
-
- /**
- * @return the real user name to connect as; never null.
- */
- public String getUser() {
- return user;
- }
-
- /**
- * @return the preferred authentication methods, separated by commas if
- * more than one authentication method is preferred.
- */
- public String getPreferredAuthentications() {
- return preferredAuthentications;
- }
-
- /**
- * @return true if batch (non-interactive) mode is preferred for this
- * host connection.
- */
- public boolean isBatchMode() {
- return batchMode != null && batchMode.booleanValue();
- }
-
- /**
- * @return the number of tries (one per second) to connect before
- * exiting. The argument must be an integer. This may be useful
- * in scripts if the connection sometimes fails. The default is
- * 1.
- * @since 3.4
- */
- public int getConnectionAttempts() {
- return connectionAttempts;
- }
-
-
- private void complete(String initialHostName, String localUserName) {
- // Try to set values from the options.
- hostName = entry.getValue(SshConstants.HOST_NAME);
- user = entry.getValue(SshConstants.USER);
- port = positive(entry.getValue(SshConstants.PORT));
- connectionAttempts = positive(
- entry.getValue(SshConstants.CONNECTION_ATTEMPTS));
- strictHostKeyChecking = entry
- .getValue(SshConstants.STRICT_HOST_KEY_CHECKING);
- batchMode = Boolean.valueOf(OpenSshConfigFile
- .flag(entry.getValue(SshConstants.BATCH_MODE)));
- preferredAuthentications = entry
- .getValue(SshConstants.PREFERRED_AUTHENTICATIONS);
- // Fill in defaults if still not set
- if (hostName == null || hostName.isEmpty()) {
- hostName = initialHostName;
- }
- if (user == null || user.isEmpty()) {
- user = localUserName;
- }
- if (port <= 0) {
- port = SshConstants.SSH_DEFAULT_PORT;
- }
- if (connectionAttempts <= 0) {
- connectionAttempts = 1;
- }
- List identityFiles = entry
- .getValues(SshConstants.IDENTITY_FILE);
- if (identityFiles != null && !identityFiles.isEmpty()) {
- identityFile = new File(identityFiles.get(0));
- }
- }
-
- Config getConfig() {
- if (config == null) {
- config = new Config() {
-
- @Override
- public String getHostname() {
- return Host.this.getHostName();
- }
-
- @Override
- public String getUser() {
- return Host.this.getUser();
- }
-
- @Override
- public int getPort() {
- return Host.this.getPort();
- }
-
- @Override
- public String getValue(String key) {
- // See com.jcraft.jsch.OpenSSHConfig.MyConfig.getValue()
- // for this special case.
- if (key.equals("compression.s2c") //$NON-NLS-1$
- || key.equals("compression.c2s")) { //$NON-NLS-1$
- if (!OpenSshConfigFile.flag(
- Host.this.entry.getValue(mapKey(key)))) {
- return "none,zlib@openssh.com,zlib"; //$NON-NLS-1$
- }
- return "zlib@openssh.com,zlib,none"; //$NON-NLS-1$
- }
- return Host.this.entry.getValue(mapKey(key));
- }
-
- @Override
- public String[] getValues(String key) {
- List values = Host.this.entry
- .getValues(mapKey(key));
- if (values == null) {
- return new String[0];
- }
- return values.toArray(new String[0]);
- }
- };
- }
- return config;
- }
-
- @Override
- @SuppressWarnings("nls")
- public String toString() {
- return "Host [hostName=" + hostName + ", port=" + port
- + ", identityFile=" + identityFile + ", user=" + user
- + ", preferredAuthentications=" + preferredAuthentications
- + ", batchMode=" + batchMode + ", strictHostKeyChecking="
- + strictHostKeyChecking + ", connectionAttempts="
- + connectionAttempts + ", entry=" + entry + "]";
- }
- }
-
- /**
- * {@inheritDoc}
- *
- * Retrieves the full {@link com.jcraft.jsch.ConfigRepository.Config Config}
- * for the given host name. Should be called only by Jsch and tests.
- *
- * @since 4.9
- */
- @Override
- public Config getConfig(String hostName) {
- Host host = lookup(hostName);
- return host.getConfig();
- }
-
- /** {@inheritDoc} */
- @Override
- public String toString() {
- return "OpenSshConfig [configFile=" + configFile + ']'; //$NON-NLS-1$
- }
-}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshSessionFactory.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshSessionFactory.java
index e6d2042422..ef845f4dce 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshSessionFactory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshSessionFactory.java
@@ -43,11 +43,12 @@ public abstract class SshSessionFactory {
}
return null;
}
+
/**
* Get the currently configured JVM-wide factory.
*
- * A factory is always available. By default the factory will read from the
- * user's $HOME/.ssh
and assume OpenSSH compatibility.
+ * By default the factory will read from the user's $HOME/.ssh
+ * and assume OpenSSH compatibility.
*
* @return factory the current factory for this JVM.
*/
@@ -60,7 +61,7 @@ public abstract class SshSessionFactory {
*
* @param newFactory
* factory for future sessions to be created through. If null the
- * default factory will be restored.s
+ * default factory will be restored.
*/
public static void setInstance(SshSessionFactory newFactory) {
if (newFactory != null) {
@@ -109,6 +110,15 @@ public abstract class SshSessionFactory {
CredentialsProvider credentialsProvider, FS fs, int tms)
throws TransportException;
+ /**
+ * The name of the type of session factory.
+ *
+ * @return the name of the type of session factory.
+ *
+ * @since 5.8
+ */
+ public abstract String getType();
+
/**
* Close (or recycle) a session to a host.
*
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java
index 947c4c3222..b9cb2484d8 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java
@@ -50,6 +50,8 @@ import org.eclipse.jgit.util.io.StreamCopyThread;
* enumeration, save file modification and hook execution.
*/
public class TransportGitSsh extends SshTransport implements PackTransport {
+ private static final String EXT = "ext"; //$NON-NLS-1$
+
static final TransportProtocol PROTO_SSH = new TransportProtocol() {
private final String[] schemeNames = { "ssh", "ssh+git", "git+ssh" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
@@ -127,6 +129,11 @@ public class TransportGitSsh extends SshTransport implements PackTransport {
throws TransportException {
return new ExtSession();
}
+
+ @Override
+ public String getType() {
+ return EXT;
+ }
});
}
}
diff --git a/pom.xml b/pom.xml
index eddb040a54..a0f6d77329 100644
--- a/pom.xml
+++ b/pom.xml
@@ -992,6 +992,7 @@
org.eclipse.jgit.http.apache
org.eclipse.jgit.http.server
org.eclipse.jgit.ssh.apache
+ org.eclipse.jgit.ssh.jsch
org.eclipse.jgit.pgm
org.eclipse.jgit.lfs
org.eclipse.jgit.lfs.server
@@ -1007,6 +1008,7 @@
org.eclipse.jgit.lfs.test
org.eclipse.jgit.lfs.server.test
org.eclipse.jgit.ssh.apache.test
+ org.eclipse.jgit.ssh.jsch.test
org.eclipse.jgit.coverage
org.eclipse.jgit.benchmarks
--
cgit v1.2.3