diff options
author | Matthias Sohn <matthias.sohn@sap.com> | 2021-09-09 14:41:30 +0200 |
---|---|---|
committer | Matthias Sohn <matthias.sohn@sap.com> | 2021-09-13 23:53:34 +0200 |
commit | a19494b735528b6eb678ac9dbc6a92b8db8560ab (patch) | |
tree | 29df569134d27876ad3b32a8f3f6daf4dffde5b5 /org.eclipse.jgit.ssh.apache | |
parent | b9653ccdad437c5449f8eaf0c4e9cfdd2afe4519 (diff) | |
parent | a3a8de310847963bd8fadba33de17abd974ae710 (diff) | |
download | jgit-a19494b735528b6eb678ac9dbc6a92b8db8560ab.tar.gz jgit-a19494b735528b6eb678ac9dbc6a92b8db8560ab.zip |
Merge branch 'master' into next
* master: (38 commits)
Revert "DFS block cache: Refactor to enable parallel index loading"
GitServlet: allow to override default error handlers
Silence API error for new interface method ProtocolV2Hook#onObjectInfo
transport: add object-info capability
Ignore IllegalStateException if JVM is already shutting down
Update orbit to R20210825222808 for 2021-09
Update spotbugs-maven-plugin to 4.3.0
Update ant to 1.10.11 also in pom.xml
DFS block cache: add additional stats to DfsReaderIoStats
Update Orbit to S20210817231813
[gpg] Better GPG home directory determination
FS: cleanup use of final modifier
Ensure FS#searchPath only selects executable files
RevWalk: getMergedInto's result is wrong on the second call
DFS block cache: Refactor to enable parallel index loading
[test] Create keystore with the keytool of the running JDK
[gpg] Update to Bouncy Castle 1.69
[test] Create keystore with the keytool of the running JDK
[sshd] Minor code clean-up
Support commit.template config property
...
Change-Id: I9f99e9a513a23c0c0d252334e79c351512d7355e
Diffstat (limited to 'org.eclipse.jgit.ssh.apache')
10 files changed, 259 insertions, 483 deletions
diff --git a/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF b/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF index 89b5133afc..03b0462711 100644 --- a/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF @@ -33,53 +33,53 @@ Export-Package: org.eclipse.jgit.internal.transport.sshd;version="6.0.0";x-inter org.apache.sshd.client.session, org.apache.sshd.client.keyverifier" Import-Package: net.i2p.crypto.eddsa;version="[0.3.0,0.4.0)", - org.apache.sshd.agent;version="[2.6.0,2.7.0)", - org.apache.sshd.client;version="[2.6.0,2.7.0)", - org.apache.sshd.client.auth;version="[2.6.0,2.7.0)", - org.apache.sshd.client.auth.keyboard;version="[2.6.0,2.7.0)", - org.apache.sshd.client.auth.password;version="[2.6.0,2.7.0)", - org.apache.sshd.client.auth.pubkey;version="[2.6.0,2.7.0)", - org.apache.sshd.client.channel;version="[2.6.0,2.7.0)", - org.apache.sshd.client.config.hosts;version="[2.6.0,2.7.0)", - org.apache.sshd.client.config.keys;version="[2.6.0,2.7.0)", - org.apache.sshd.client.future;version="[2.6.0,2.7.0)", - org.apache.sshd.client.keyverifier;version="[2.6.0,2.7.0)", - org.apache.sshd.client.session;version="[2.6.0,2.7.0)", - org.apache.sshd.client.session.forward;version="[2.6.0,2.7.0)", - org.apache.sshd.common;version="[2.6.0,2.7.0)", - org.apache.sshd.common.auth;version="[2.6.0,2.7.0)", - org.apache.sshd.common.channel;version="[2.6.0,2.7.0)", - org.apache.sshd.common.compression;version="[2.6.0,2.7.0)", - org.apache.sshd.common.config.keys;version="[2.6.0,2.7.0)", - org.apache.sshd.common.config.keys.loader;version="[2.6.0,2.7.0)", - org.apache.sshd.common.config.keys.loader.openssh.kdf;version="[2.6.0,2.7.0)", - org.apache.sshd.common.digest;version="[2.6.0,2.7.0)", - org.apache.sshd.common.forward;version="[2.6.0,2.7.0)", - org.apache.sshd.common.future;version="[2.6.0,2.7.0)", - org.apache.sshd.common.helpers;version="[2.6.0,2.7.0)", - org.apache.sshd.common.io;version="[2.6.0,2.7.0)", - org.apache.sshd.common.kex;version="[2.6.0,2.7.0)", - org.apache.sshd.common.kex.extension;version="[2.6.0,2.7.0)", - org.apache.sshd.common.kex.extension.parser;version="[2.6.0,2.7.0)", - org.apache.sshd.common.keyprovider;version="[2.6.0,2.7.0)", - org.apache.sshd.common.mac;version="[2.6.0,2.7.0)", - org.apache.sshd.common.random;version="[2.6.0,2.7.0)", - org.apache.sshd.common.session;version="[2.6.0,2.7.0)", - org.apache.sshd.common.session.helpers;version="[2.6.0,2.7.0)", - org.apache.sshd.common.signature;version="[2.6.0,2.7.0)", - org.apache.sshd.common.util;version="[2.6.0,2.7.0)", - org.apache.sshd.common.util.buffer;version="[2.6.0,2.7.0)", - org.apache.sshd.common.util.closeable;version="[2.6.0,2.7.0)", - org.apache.sshd.common.util.io;version="[2.6.0,2.7.0)", - org.apache.sshd.common.util.io.resource;version="[2.6.0,2.7.0)", - org.apache.sshd.common.util.logging;version="[2.6.0,2.7.0)", - org.apache.sshd.common.util.net;version="[2.6.0,2.7.0)", - org.apache.sshd.common.util.security;version="[2.6.0,2.7.0)", - org.apache.sshd.core;version="[2.6.0,2.7.0)", - org.apache.sshd.server.auth;version="[2.6.0,2.7.0)", - org.apache.sshd.sftp;version="[2.6.0,2.7.0)", - org.apache.sshd.sftp.client;version="[2.6.0,2.7.0)", - org.apache.sshd.sftp.common;version="[2.6.0,2.7.0)", + org.apache.sshd.agent;version="[2.7.0,2.8.0)", + org.apache.sshd.client;version="[2.7.0,2.8.0)", + org.apache.sshd.client.auth;version="[2.7.0,2.8.0)", + org.apache.sshd.client.auth.keyboard;version="[2.7.0,2.8.0)", + org.apache.sshd.client.auth.password;version="[2.7.0,2.8.0)", + org.apache.sshd.client.auth.pubkey;version="[2.7.0,2.8.0)", + org.apache.sshd.client.channel;version="[2.7.0,2.8.0)", + org.apache.sshd.client.config.hosts;version="[2.7.0,2.8.0)", + org.apache.sshd.client.config.keys;version="[2.7.0,2.8.0)", + org.apache.sshd.client.future;version="[2.7.0,2.8.0)", + org.apache.sshd.client.keyverifier;version="[2.7.0,2.8.0)", + org.apache.sshd.client.session;version="[2.7.0,2.8.0)", + org.apache.sshd.client.session.forward;version="[2.7.0,2.8.0)", + org.apache.sshd.common;version="[2.7.0,2.8.0)", + org.apache.sshd.common.auth;version="[2.7.0,2.8.0)", + org.apache.sshd.common.channel;version="[2.7.0,2.8.0)", + org.apache.sshd.common.compression;version="[2.7.0,2.8.0)", + org.apache.sshd.common.config.keys;version="[2.7.0,2.8.0)", + org.apache.sshd.common.config.keys.loader;version="[2.7.0,2.8.0)", + org.apache.sshd.common.config.keys.loader.openssh.kdf;version="[2.7.0,2.8.0)", + org.apache.sshd.common.digest;version="[2.7.0,2.8.0)", + org.apache.sshd.common.forward;version="[2.7.0,2.8.0)", + org.apache.sshd.common.future;version="[2.7.0,2.8.0)", + org.apache.sshd.common.helpers;version="[2.7.0,2.8.0)", + org.apache.sshd.common.io;version="[2.7.0,2.8.0)", + org.apache.sshd.common.kex;version="[2.7.0,2.8.0)", + org.apache.sshd.common.kex.extension;version="[2.7.0,2.8.0)", + org.apache.sshd.common.kex.extension.parser;version="[2.7.0,2.8.0)", + org.apache.sshd.common.keyprovider;version="[2.7.0,2.8.0)", + org.apache.sshd.common.mac;version="[2.7.0,2.8.0)", + org.apache.sshd.common.random;version="[2.7.0,2.8.0)", + org.apache.sshd.common.session;version="[2.7.0,2.8.0)", + org.apache.sshd.common.session.helpers;version="[2.7.0,2.8.0)", + org.apache.sshd.common.signature;version="[2.7.0,2.8.0)", + org.apache.sshd.common.util;version="[2.7.0,2.8.0)", + org.apache.sshd.common.util.buffer;version="[2.7.0,2.8.0)", + org.apache.sshd.common.util.closeable;version="[2.7.0,2.8.0)", + org.apache.sshd.common.util.io;version="[2.7.0,2.8.0)", + org.apache.sshd.common.util.io.resource;version="[2.7.0,2.8.0)", + org.apache.sshd.common.util.logging;version="[2.7.0,2.8.0)", + org.apache.sshd.common.util.net;version="[2.7.0,2.8.0)", + org.apache.sshd.common.util.security;version="[2.7.0,2.8.0)", + org.apache.sshd.core;version="[2.7.0,2.8.0)", + org.apache.sshd.server.auth;version="[2.7.0,2.8.0)", + org.apache.sshd.sftp;version="[2.7.0,2.8.0)", + org.apache.sshd.sftp.client;version="[2.7.0,2.8.0)", + org.apache.sshd.sftp.common;version="[2.7.0,2.8.0)", org.eclipse.jgit.annotations;version="[6.0.0,6.1.0)", org.eclipse.jgit.errors;version="[6.0.0,6.1.0)", org.eclipse.jgit.fnmatch;version="[6.0.0,6.1.0)", diff --git a/org.eclipse.jgit.ssh.apache/resources/org/eclipse/jgit/internal/transport/sshd/SshdText.properties b/org.eclipse.jgit.ssh.apache/resources/org/eclipse/jgit/internal/transport/sshd/SshdText.properties index 5bc0867674..defcbdcfc1 100644 --- a/org.eclipse.jgit.ssh.apache/resources/org/eclipse/jgit/internal/transport/sshd/SshdText.properties +++ b/org.eclipse.jgit.ssh.apache/resources/org/eclipse/jgit/internal/transport/sshd/SshdText.properties @@ -8,6 +8,7 @@ configInvalidProxyJump=Ssh config, host ''{0}'': Cannot parse ProxyJump ''{1}'' configNoKnownAlgorithms=Ssh config ''{0}'' ''{1}'' resulted in empty list (none known, or all known removed); using default. configProxyJumpNotSsh=Non-ssh URI in ProxyJump ssh config configProxyJumpWithPath=ProxyJump ssh config: jump host specification must not have a path +configUnknownAlgorithm=Ssh config {0}: ignoring unknown algorithm ''{1}'' in {2} {3} ftpCloseFailed=Closing the SFTP channel failed gssapiFailure=GSS-API error for mechanism OID {0} gssapiInitFailure=GSS-API initialization failure for mechanism {0} diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitClientSession.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitClientSession.java index f9e80121ed..f7b37d7816 100644 --- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitClientSession.java +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitClientSession.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018, 2019 Thomas Wolf <thomas.wolf@paranor.ch> and others + * Copyright (C) 2018, 2021 Thomas Wolf <thomas.wolf@paranor.ch> 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 @@ -16,7 +16,6 @@ import java.io.IOException; import java.io.StreamCorruptedException; import java.net.SocketAddress; import java.nio.charset.StandardCharsets; -import java.security.GeneralSecurityException; import java.security.PublicKey; import java.util.ArrayList; import java.util.Collection; @@ -29,17 +28,27 @@ import java.util.Map; import java.util.Objects; import java.util.Set; +import org.apache.sshd.client.ClientBuilder; import org.apache.sshd.client.ClientFactoryManager; import org.apache.sshd.client.config.hosts.HostConfigEntry; import org.apache.sshd.client.keyverifier.ServerKeyVerifier; import org.apache.sshd.client.session.ClientSessionImpl; import org.apache.sshd.common.AttributeRepository; import org.apache.sshd.common.FactoryManager; +import org.apache.sshd.common.NamedResource; import org.apache.sshd.common.PropertyResolver; import org.apache.sshd.common.config.keys.KeyUtils; import org.apache.sshd.common.io.IoSession; import org.apache.sshd.common.io.IoWriteFuture; +import org.apache.sshd.common.kex.BuiltinDHFactories; +import org.apache.sshd.common.kex.DHFactory; import org.apache.sshd.common.kex.KexProposalOption; +import org.apache.sshd.common.kex.KeyExchangeFactory; +import org.apache.sshd.common.kex.extension.KexExtensionHandler; +import org.apache.sshd.common.kex.extension.KexExtensionHandler.AvailabilityPhase; +import org.apache.sshd.common.kex.extension.KexExtensions; +import org.apache.sshd.common.keyprovider.KeyPairProvider; +import org.apache.sshd.common.signature.BuiltinSignatures; import org.apache.sshd.common.util.Readable; import org.apache.sshd.common.util.buffer.Buffer; import org.eclipse.jgit.errors.InvalidPatternException; @@ -70,6 +79,8 @@ public class JGitClientSession extends ClientSessionImpl { */ private static final int DEFAULT_MAX_IDENTIFICATION_SIZE = 64 * 1024; + private static final AttributeKey<Boolean> INITIAL_KEX_DONE = new AttributeKey<>(); + private HostConfigEntry hostConfig; private CredentialsProvider credentialsProvider; @@ -136,51 +147,38 @@ public class JGitClientSession extends ClientSessionImpl { } @Override - protected IoWriteFuture sendIdentification(String ident) - throws IOException { + protected IoWriteFuture sendIdentification(String ident, + List<String> extraLines) throws Exception { StatefulProxyConnector proxy = proxyHandler; if (proxy != null) { - try { - // We must not block here; the framework starts reading messages - // from the peer only once the initial sendKexInit() following - // this call to sendIdentification() has returned! - proxy.runWhenDone(() -> { - JGitClientSession.super.sendIdentification(ident); - return null; - }); - // Called only from the ClientSessionImpl constructor, where the - // return value is ignored. + // We must not block here; the framework starts reading messages + // from the peer only once the initial sendKexInit() following + // this call to sendIdentification() has returned! + proxy.runWhenDone(() -> { + JGitClientSession.super.sendIdentification(ident, extraLines); return null; - } catch (IOException e) { - throw e; - } catch (Exception other) { - throw new IOException(other.getLocalizedMessage(), other); - } + }); + // Called only from the ClientSessionImpl constructor, where the + // return value is ignored. + return null; } - return super.sendIdentification(ident); + return super.sendIdentification(ident, extraLines); } @Override - protected byte[] sendKexInit() - throws IOException, GeneralSecurityException { + protected byte[] sendKexInit() throws Exception { StatefulProxyConnector proxy = proxyHandler; if (proxy != null) { - try { - // We must not block here; the framework starts reading messages - // from the peer only once the initial sendKexInit() has - // returned! - proxy.runWhenDone(() -> { - JGitClientSession.super.sendKexInit(); - return null; - }); - // This is called only from the ClientSessionImpl - // constructor, where the return value is ignored. + // We must not block here; the framework starts reading messages + // from the peer only once the initial sendKexInit() has + // returned! + proxy.runWhenDone(() -> { + JGitClientSession.super.sendKexInit(); return null; - } catch (IOException | GeneralSecurityException e) { - throw e; - } catch (Exception other) { - throw new IOException(other.getLocalizedMessage(), other); - } + }); + // This is called only from the ClientSessionImpl + // constructor, where the return value is ignored. + return null; } return super.sendKexInit(); } @@ -219,6 +217,32 @@ public class JGitClientSession extends ClientSessionImpl { return result; } + Set<String> getAllAvailableSignatureAlgorithms() { + Set<String> allAvailable = new HashSet<>(); + BuiltinSignatures.VALUES.forEach(s -> allAvailable.add(s.getName())); + BuiltinSignatures.getRegisteredExtensions() + .forEach(s -> allAvailable.add(s.getName())); + return allAvailable; + } + + private void setNewFactories(Collection<String> defaultFactories, + Collection<String> finalFactories) { + // If new factory names were added make sure we actually have factories + // for them all. + // + // But add new ones at the end: we don't want to change the order for + // pubkey auth, and any new ones added here were not included in the + // default set for some reason, such as being deprecated or weak. + // + // The order for KEX is determined by the order in the proposal string, + // but the order in pubkey auth is determined by the order in the + // factory list (possibly overridden via ssh config + // PubkeyAcceptedAlgorithms; see JGitPublicKeyAuthentication). + Set<String> resultSet = new LinkedHashSet<>(defaultFactories); + resultSet.addAll(finalFactories); + setSignatureFactoriesNames(resultSet); + } + @Override protected String resolveAvailableSignaturesProposal( FactoryManager manager) { @@ -229,16 +253,17 @@ public class JGitClientSession extends ClientSessionImpl { .getProperty(SshConstants.HOST_KEY_ALGORITHMS); if (!StringUtils.isEmptyOrNull(algorithms)) { List<String> result = modifyAlgorithmList(defaultSignatures, - algorithms, SshConstants.HOST_KEY_ALGORITHMS); + getAllAvailableSignatureAlgorithms(), algorithms, + SshConstants.HOST_KEY_ALGORITHMS); if (!result.isEmpty()) { if (log.isDebugEnabled()) { log.debug(SshConstants.HOST_KEY_ALGORITHMS + ' ' + result); } + setNewFactories(defaultSignatures, result); return String.join(",", result); //$NON-NLS-1$ } log.warn(format(SshdText.get().configNoKnownAlgorithms, - SshConstants.HOST_KEY_ALGORITHMS, - algorithms)); + SshConstants.HOST_KEY_ALGORITHMS, algorithms)); } // No HostKeyAlgorithms; using default -- change order to put existing // keys first. @@ -253,6 +278,11 @@ public class JGitClientSession extends ClientSessionImpl { if (key != null) { String keyType = KeyUtils.getKeyType(key); if (keyType != null) { + if (KeyPairProvider.SSH_RSA.equals(keyType)) { + // Add all available signatures for ssh-rsa. + reordered.add(KeyUtils.RSA_SHA512_KEY_TYPE_ALIAS); + reordered.add(KeyUtils.RSA_SHA256_KEY_TYPE_ALIAS); + } reordered.add(keyType); } } @@ -261,6 +291,10 @@ public class JGitClientSession extends ClientSessionImpl { if (log.isDebugEnabled()) { log.debug(SshConstants.HOST_KEY_ALGORITHMS + ' ' + reordered); } + // Make sure we actually have factories for them all. + if (reordered.size() > defaultSignatures.size()) { + setNewFactories(defaultSignatures, reordered); + } return String.join(",", reordered); //$NON-NLS-1$ } if (log.isDebugEnabled()) { @@ -270,15 +304,87 @@ public class JGitClientSession extends ClientSessionImpl { return String.join(",", defaultSignatures); //$NON-NLS-1$ } + private List<String> determineKexProposal() { + List<KeyExchangeFactory> kexFactories = getKeyExchangeFactories(); + List<String> defaultKexMethods = NamedResource + .getNameList(kexFactories); + HostConfigEntry config = resolveAttribute( + JGitSshClient.HOST_CONFIG_ENTRY); + String algorithms = config.getProperty(SshConstants.KEX_ALGORITHMS); + if (!StringUtils.isEmptyOrNull(algorithms)) { + Set<String> allAvailable = new HashSet<>(); + BuiltinDHFactories.VALUES + .forEach(s -> allAvailable.add(s.getName())); + BuiltinDHFactories.getRegisteredExtensions() + .forEach(s -> allAvailable.add(s.getName())); + List<String> result = modifyAlgorithmList(defaultKexMethods, + allAvailable, algorithms, SshConstants.KEX_ALGORITHMS); + if (!result.isEmpty()) { + // If new ones were added, update the installed factories + Set<String> configuredKexMethods = new HashSet<>( + defaultKexMethods); + List<KeyExchangeFactory> newKexFactories = new ArrayList<>(); + result.forEach(name -> { + if (!configuredKexMethods.contains(name)) { + DHFactory factory = BuiltinDHFactories + .resolveFactory(name); + if (factory == null) { + // Should not occur here + if (log.isDebugEnabled()) { + log.debug( + "determineKexProposal({}) unknown KEX algorithm {} ignored", //$NON-NLS-1$ + this, name); + } + } else { + newKexFactories + .add(ClientBuilder.DH2KEX.apply(factory)); + } + } + }); + if (!newKexFactories.isEmpty()) { + newKexFactories.addAll(kexFactories); + setKeyExchangeFactories(newKexFactories); + } + return result; + } + log.warn(format(SshdText.get().configNoKnownAlgorithms, + SshConstants.KEX_ALGORITHMS, algorithms)); + } + return defaultKexMethods; + } + + @Override + protected String resolveSessionKexProposal(String hostKeyTypes) + throws IOException { + String kexMethods = String.join(",", determineKexProposal()); //$NON-NLS-1$ + Boolean isRekey = getAttribute(INITIAL_KEX_DONE); + if (isRekey == null || !isRekey.booleanValue()) { + // First time + KexExtensionHandler extHandler = getKexExtensionHandler(); + if (extHandler != null && extHandler.isKexExtensionsAvailable(this, + AvailabilityPhase.PROPOSAL)) { + if (kexMethods.isEmpty()) { + kexMethods = KexExtensions.CLIENT_KEX_EXTENSION; + } else { + kexMethods += ',' + KexExtensions.CLIENT_KEX_EXTENSION; + } + } + setAttribute(INITIAL_KEX_DONE, Boolean.TRUE); + } + if (log.isDebugEnabled()) { + log.debug(SshConstants.KEX_ALGORITHMS + ' ' + kexMethods); + } + return kexMethods; + } + /** * Modifies a given algorithm list according to a list from the ssh config, - * including remove ('-') and reordering ('^') operators. Addition ('+') is - * not handled since we have no way of adding dynamically implementations, - * and the defaultList is supposed to contain all known implementations - * already. + * including add ('+'), remove ('-') and reordering ('^') operators. * * @param defaultList * to modify + * @param allAvailable + * all available values * @param fromConfig * telling how to modify the {@code defaultList}, must not be * {@code null} or empty @@ -288,22 +394,22 @@ public class JGitClientSession extends ClientSessionImpl { * set */ public List<String> modifyAlgorithmList(List<String> defaultList, - String fromConfig, String overrideKey) { + Set<String> allAvailable, String fromConfig, String overrideKey) { Set<String> defaults = new LinkedHashSet<>(); defaults.addAll(defaultList); switch (fromConfig.charAt(0)) { case '+': - // Additions make not much sense -- it's either in - // defaultList already, or we have no implementation for - // it. No point in proposing it. - return defaultList; + List<String> newSignatures = filteredList(allAvailable, overrideKey, + fromConfig.substring(1)); + defaults.addAll(newSignatures); + return new ArrayList<>(defaults); case '-': // This takes wildcard patterns! removeFromList(defaults, overrideKey, fromConfig.substring(1)); return new ArrayList<>(defaults); case '^': // Specified entries go to the front of the default list - List<String> allSignatures = filteredList(defaults, + List<String> allSignatures = filteredList(allAvailable, overrideKey, fromConfig.substring(1)); Set<String> atFront = new HashSet<>(allSignatures); for (String sig : defaults) { @@ -315,7 +421,7 @@ public class JGitClientSession extends ClientSessionImpl { default: // Default is overridden -- only accept the ones for which we do // have an implementation. - return filteredList(defaults, fromConfig); + return filteredList(allAvailable, overrideKey, fromConfig); } } @@ -342,11 +448,15 @@ public class JGitClientSession extends ClientSessionImpl { } } - private List<String> filteredList(Set<String> known, String values) { + private List<String> filteredList(Set<String> known, String key, + String values) { List<String> newNames = new ArrayList<>(); for (String newValue : values.split("\\s*,\\s*")) { //$NON-NLS-1$ if (known.contains(newValue)) { newNames.add(newValue); + } else { + log.warn(format(SshdText.get().configUnknownAlgorithm, this, + newValue, key, values)); } } return newNames; diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitKexExtensionHandler.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitKexExtensionHandler.java deleted file mode 100644 index 9446aaa7d6..0000000000 --- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitKexExtensionHandler.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (C) 2021 Thomas Wolf <thomas.wolf@paranor.ch> 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.internal.transport.sshd; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; - -import org.apache.sshd.common.AttributeRepository.AttributeKey; -import org.apache.sshd.common.NamedFactory; -import org.apache.sshd.common.kex.KexProposalOption; -import org.apache.sshd.common.kex.extension.KexExtensionHandler; -import org.apache.sshd.common.kex.extension.KexExtensions; -import org.apache.sshd.common.kex.extension.parser.ServerSignatureAlgorithms; -import org.apache.sshd.common.session.Session; -import org.apache.sshd.common.signature.Signature; -import org.apache.sshd.common.util.logging.AbstractLoggingBean; -import org.eclipse.jgit.util.StringUtils; - -/** - * Do not use the DefaultClientKexExtensionHandler from sshd; it doesn't work - * properly because of misconceptions. See SSHD-1141. - * - * @see <a href="https://issues.apache.org/jira/browse/SSHD-1141">SSHD-1141</a> - */ -public class JGitKexExtensionHandler extends AbstractLoggingBean - implements KexExtensionHandler { - - /** Singleton instance. */ - public static final JGitKexExtensionHandler INSTANCE = new JGitKexExtensionHandler(); - - /** - * Session {@link AttributeKey} used to store whether the extension - * indicator was already sent. - */ - private static final AttributeKey<Boolean> CLIENT_PROPOSAL_MADE = new AttributeKey<>(); - - /** - * Session {@link AttributeKey} storing the algorithms announced by the - * server as known. - */ - public static final AttributeKey<Set<String>> SERVER_ALGORITHMS = new AttributeKey<>(); - - private JGitKexExtensionHandler() { - // No public instantiation for singleton - } - - @Override - public boolean isKexExtensionsAvailable(Session session, - AvailabilityPhase phase) throws IOException { - return !AvailabilityPhase.PREKEX.equals(phase); - } - - @Override - public void handleKexInitProposal(Session session, boolean initiator, - Map<KexProposalOption, String> proposal) throws IOException { - // If it's the very first time, we may add the marker telling the server - // that we are ready to handle SSH_MSG_EXT_INFO - if (session == null || session.isServerSession() || !initiator) { - return; - } - if (session.getAttribute(CLIENT_PROPOSAL_MADE) != null) { - return; - } - String kexAlgorithms = proposal.get(KexProposalOption.SERVERKEYS); - if (StringUtils.isEmptyOrNull(kexAlgorithms)) { - return; - } - List<String> algorithms = new ArrayList<>(); - // We're a client. We mustn't send the server extension, and we should - // send the client extension only once. - for (String algo : kexAlgorithms.split(",")) { //$NON-NLS-1$ - if (KexExtensions.CLIENT_KEX_EXTENSION.equalsIgnoreCase(algo) - || KexExtensions.SERVER_KEX_EXTENSION - .equalsIgnoreCase(algo)) { - continue; - } - algorithms.add(algo); - } - // Tell the server that we want to receive SSH2_MSG_EXT_INFO - algorithms.add(KexExtensions.CLIENT_KEX_EXTENSION); - if (log.isDebugEnabled()) { - log.debug( - "handleKexInitProposal({}): proposing HostKeyAlgorithms {}", //$NON-NLS-1$ - session, algorithms); - } - proposal.put(KexProposalOption.SERVERKEYS, - String.join(",", algorithms)); //$NON-NLS-1$ - session.setAttribute(CLIENT_PROPOSAL_MADE, Boolean.TRUE); - } - - @Override - public boolean handleKexExtensionRequest(Session session, int index, - int count, String name, byte[] data) throws IOException { - if (ServerSignatureAlgorithms.NAME.equals(name)) { - handleServerSignatureAlgorithms(session, - ServerSignatureAlgorithms.INSTANCE.parseExtension(data)); - } - return true; - } - - /** - * Perform updates after a server-sig-algs extension has been received. - * - * @param session - * the message was received for - * @param serverAlgorithms - * signature algorithm names announced by the server - */ - protected void handleServerSignatureAlgorithms(Session session, - Collection<String> serverAlgorithms) { - if (log.isDebugEnabled()) { - log.debug("handleServerSignatureAlgorithms({}): {}", session, //$NON-NLS-1$ - serverAlgorithms); - } - // Client determines order; server says what it supports. Re-order - // such that supported ones are at the front, in client order, - // followed by unsupported ones, also in client order. - if (serverAlgorithms != null && !serverAlgorithms.isEmpty()) { - List<NamedFactory<Signature>> clientAlgorithms = new ArrayList<>( - session.getSignatureFactories()); - if (log.isDebugEnabled()) { - log.debug( - "handleServerSignatureAlgorithms({}): PubkeyAcceptedAlgorithms before: {}", //$NON-NLS-1$ - session, clientAlgorithms); - } - List<NamedFactory<Signature>> unknown = new ArrayList<>(); - Set<String> known = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); - known.addAll(serverAlgorithms); - for (Iterator<NamedFactory<Signature>> iter = clientAlgorithms - .iterator(); iter.hasNext();) { - NamedFactory<Signature> algo = iter.next(); - if (!known.contains(algo.getName())) { - unknown.add(algo); - iter.remove(); - } - } - // Re-add the unknown ones at the end. Per RFC 8308, some - // servers may not announce _all_ their supported algorithms, - // and a client may use unknown algorithms. - clientAlgorithms.addAll(unknown); - if (log.isDebugEnabled()) { - log.debug( - "handleServerSignatureAlgorithms({}): PubkeyAcceptedAlgorithms after: {}", //$NON-NLS-1$ - session, clientAlgorithms); - } - session.setAttribute(SERVER_ALGORITHMS, known); - session.setSignatureFactories(clientAlgorithms); - } - } -} diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyAuthentication.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyAuthentication.java index 6755094420..08da18f5aa 100644 --- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyAuthentication.java +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyAuthentication.java @@ -9,216 +9,56 @@ */ package org.eclipse.jgit.internal.transport.sshd; -import java.io.IOException; -import java.security.PublicKey; -import java.security.spec.InvalidKeySpecException; -import java.text.MessageFormat; -import java.util.Deque; -import java.util.HashSet; -import java.util.LinkedList; +import static java.text.MessageFormat.format; +import static org.eclipse.jgit.transport.SshConstants.PUBKEY_ACCEPTED_ALGORITHMS; + import java.util.List; -import java.util.Set; import org.apache.sshd.client.auth.pubkey.UserAuthPublicKey; +import org.apache.sshd.client.config.hosts.HostConfigEntry; import org.apache.sshd.client.session.ClientSession; import org.apache.sshd.common.NamedFactory; -import org.apache.sshd.common.NamedResource; -import org.apache.sshd.common.RuntimeSshException; -import org.apache.sshd.common.SshConstants; -import org.apache.sshd.common.config.keys.KeyUtils; import org.apache.sshd.common.signature.Signature; -import org.apache.sshd.common.signature.SignatureFactoriesHolder; -import org.apache.sshd.common.util.buffer.Buffer; +import org.eclipse.jgit.util.StringUtils; /** - * Custom {@link UserAuthPublicKey} implementation fixing SSHD-1105: if there - * are several signature algorithms applicable for a public key type, we must - * try them all, in the correct order. - * - * @see <a href="https://issues.apache.org/jira/browse/SSHD-1105">SSHD-1105</a> - * @see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=572056">Bug - * 572056</a> + * Custom {@link UserAuthPublicKey} implementation for handling SSH config + * PubkeyAcceptedAlgorithms. */ public class JGitPublicKeyAuthentication extends UserAuthPublicKey { - private final Deque<String> currentAlgorithms = new LinkedList<>(); - - private String chosenAlgorithm; - JGitPublicKeyAuthentication(List<NamedFactory<Signature>> factories) { super(factories); } @Override - protected boolean sendAuthDataRequest(ClientSession session, String service) + public void init(ClientSession rawSession, String service) throws Exception { - if (current == null) { - currentAlgorithms.clear(); - chosenAlgorithm = null; - } - String currentAlgorithm = null; - if (current != null && !currentAlgorithms.isEmpty()) { - currentAlgorithm = currentAlgorithms.poll(); - if (chosenAlgorithm != null) { - Set<String> knownServerAlgorithms = session.getAttribute( - JGitKexExtensionHandler.SERVER_ALGORITHMS); - if (knownServerAlgorithms != null - && knownServerAlgorithms.contains(chosenAlgorithm)) { - // We've tried key 'current' with 'chosenAlgorithm', but it - // failed. However, the server had told us it supported - // 'chosenAlgorithm'. Thus it makes no sense to continue - // with this key and other signature algorithms. Skip to the - // next key, if any. - currentAlgorithm = null; - } - } + if (!(rawSession instanceof JGitClientSession)) { + throw new IllegalStateException("Wrong session type: " //$NON-NLS-1$ + + rawSession.getClass().getCanonicalName()); } - if (currentAlgorithm == null) { - try { - if (keys == null || !keys.hasNext()) { - if (log.isDebugEnabled()) { - log.debug( - "sendAuthDataRequest({})[{}] no more keys to send", //$NON-NLS-1$ - session, service); - } - current = null; - return false; - } - current = keys.next(); - currentAlgorithms.clear(); - chosenAlgorithm = null; - } catch (Error e) { // Copied from superclass - throw new RuntimeSshException(e); - } - } - PublicKey key; - try { - key = current.getPublicKey(); - } catch (Error e) { // Copied from superclass - throw new RuntimeSshException(e); - } - if (currentAlgorithm == null) { - String keyType = KeyUtils.getKeyType(key); - Set<String> aliases = new HashSet<>( - KeyUtils.getAllEquivalentKeyTypes(keyType)); - aliases.add(keyType); - List<NamedFactory<Signature>> existingFactories; - if (current instanceof SignatureFactoriesHolder) { - existingFactories = ((SignatureFactoriesHolder) current) - .getSignatureFactories(); - } else { - existingFactories = getSignatureFactories(); - } - if (existingFactories != null) { + JGitClientSession session = ((JGitClientSession) rawSession); + HostConfigEntry hostConfig = session.getHostConfigEntry(); + // Set signature algorithms for public key authentication + String pubkeyAlgos = hostConfig.getProperty(PUBKEY_ACCEPTED_ALGORITHMS); + if (!StringUtils.isEmptyOrNull(pubkeyAlgos)) { + List<String> signatures = session.getSignatureFactoriesNames(); + signatures = session.modifyAlgorithmList(signatures, + session.getAllAvailableSignatureAlgorithms(), pubkeyAlgos, + PUBKEY_ACCEPTED_ALGORITHMS); + if (!signatures.isEmpty()) { if (log.isDebugEnabled()) { - log.debug( - "sendAuthDataRequest({})[{}] selecting from PubKeyAcceptedAlgorithms {}", //$NON-NLS-1$ - session, service, - NamedResource.getNames(existingFactories)); + log.debug(PUBKEY_ACCEPTED_ALGORITHMS + ' ' + signatures); } - // Select the factories by name and in order - existingFactories.forEach(f -> { - if (aliases.contains(f.getName())) { - currentAlgorithms.add(f.getName()); - } - }); + setSignatureFactoriesNames(signatures); + } else { + log.warn(format(SshdText.get().configNoKnownAlgorithms, + PUBKEY_ACCEPTED_ALGORITHMS, pubkeyAlgos)); } - currentAlgorithm = currentAlgorithms.isEmpty() ? keyType - : currentAlgorithms.poll(); } - String name = getName(); - if (log.isDebugEnabled()) { - log.debug( - "sendAuthDataRequest({})[{}] send SSH_MSG_USERAUTH_REQUEST request {} type={} - fingerprint={}", //$NON-NLS-1$ - session, service, name, currentAlgorithm, - KeyUtils.getFingerPrint(key)); - } - - chosenAlgorithm = currentAlgorithm; - Buffer buffer = session - .createBuffer(SshConstants.SSH_MSG_USERAUTH_REQUEST); - buffer.putString(session.getUsername()); - buffer.putString(service); - buffer.putString(name); - buffer.putBoolean(false); - buffer.putString(currentAlgorithm); - buffer.putPublicKey(key); - session.writePacket(buffer); - return true; - } - - @Override - protected boolean processAuthDataRequest(ClientSession session, - String service, Buffer buffer) throws Exception { - String name = getName(); - int cmd = buffer.getUByte(); - if (cmd != SshConstants.SSH_MSG_USERAUTH_PK_OK) { - throw new IllegalStateException(MessageFormat.format( - SshdText.get().pubkeyAuthWrongCommand, - SshConstants.getCommandMessageName(cmd), - session.getConnectAddress(), session.getServerVersion())); - } - PublicKey key; - try { - key = current.getPublicKey(); - } catch (Error e) { // Copied from superclass - throw new RuntimeSshException(e); - } - String rspKeyAlgorithm = buffer.getString(); - PublicKey rspKey = buffer.getPublicKey(); - if (log.isDebugEnabled()) { - log.debug( - "processAuthDataRequest({})[{}][{}] SSH_MSG_USERAUTH_PK_OK type={}, fingerprint={}", //$NON-NLS-1$ - session, service, name, rspKeyAlgorithm, - KeyUtils.getFingerPrint(rspKey)); - } - if (!KeyUtils.compareKeys(rspKey, key)) { - throw new InvalidKeySpecException(MessageFormat.format( - SshdText.get().pubkeyAuthWrongKey, - KeyUtils.getFingerPrint(key), - KeyUtils.getFingerPrint(rspKey), - session.getConnectAddress(), session.getServerVersion())); - } - if (!chosenAlgorithm.equalsIgnoreCase(rspKeyAlgorithm)) { - // 'algo' SHOULD be the same as 'chosenAlgorithm', which is the one - // we sent above. See https://tools.ietf.org/html/rfc4252#page-9 . - // - // However, at least Github (SSH-2.0-babeld-383743ad) servers seem - // to return the key type, not the algorithm name. - // - // So we don't check but just log the inconsistency. We sign using - // 'chosenAlgorithm' in any case, so we don't really care what the - // server says here. - log.warn(MessageFormat.format( - SshdText.get().pubkeyAuthWrongSignatureAlgorithm, - chosenAlgorithm, rspKeyAlgorithm, session.getConnectAddress(), - session.getServerVersion())); - } - String username = session.getUsername(); - Buffer out = session - .createBuffer(SshConstants.SSH_MSG_USERAUTH_REQUEST); - out.putString(username); - out.putString(service); - out.putString(name); - out.putBoolean(true); - out.putString(chosenAlgorithm); - out.putPublicKey(key); - if (log.isDebugEnabled()) { - log.debug( - "processAuthDataRequest({})[{}][{}]: signing with algorithm {}", //$NON-NLS-1$ - session, service, name, chosenAlgorithm); - } - appendSignature(session, service, name, username, chosenAlgorithm, key, - out); - session.writePacket(out); - return true; - } - - @Override - protected void releaseKeys() throws IOException { - currentAlgorithms.clear(); - current = null; - chosenAlgorithm = null; - super.releaseKeys(); + // If we don't set signature factories here, the default ones from the + // session will be used. + super.init(session, service); } } diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitSshClient.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitSshClient.java index 071e1979d3..ae12c2028d 100644 --- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitSshClient.java +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitSshClient.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018, 2020 Thomas Wolf <thomas.wolf@paranor.ch> and others + * Copyright (C) 2018, 2021 Thomas Wolf <thomas.wolf@paranor.ch> 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 @@ -267,24 +267,6 @@ public class JGitSshClient extends SshClient { session.setUsername(username); session.setConnectAddress(address); session.setHostConfigEntry(hostConfig); - // Set signature algorithms for public key authentication - String pubkeyAlgos = hostConfig - .getProperty(SshConstants.PUBKEY_ACCEPTED_ALGORITHMS); - if (!StringUtils.isEmptyOrNull(pubkeyAlgos)) { - List<String> signatures = getSignatureFactoriesNames(); - signatures = session.modifyAlgorithmList(signatures, pubkeyAlgos, - SshConstants.PUBKEY_ACCEPTED_ALGORITHMS); - if (!signatures.isEmpty()) { - if (log.isDebugEnabled()) { - log.debug(SshConstants.PUBKEY_ACCEPTED_ALGORITHMS + ' ' - + signatures); - } - session.setSignatureFactoriesNames(signatures); - } else { - log.warn(format(SshdText.get().configNoKnownAlgorithms, - SshConstants.PUBKEY_ACCEPTED_ALGORITHMS, pubkeyAlgos)); - } - } if (session.getCredentialsProvider() == null) { session.setCredentialsProvider(getCredentialsProvider()); } diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyDatabase.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyDatabase.java index 1a530b7743..85e406f422 100644 --- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyDatabase.java +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyDatabase.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018, 2019 Thomas Wolf <thomas.wolf@paranor.ch> and others + * Copyright (C) 2018, 2021 Thomas Wolf <thomas.wolf@paranor.ch> 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 @@ -182,10 +182,13 @@ public class OpenSshServerKeyDatabase for (HostKeyFile file : filesToUse) { for (HostEntryPair current : file.get()) { KnownHostEntry entry = current.getHostEntry(); - for (SshdSocketAddress host : candidates) { - if (entry.isHostMatch(host.getHostName(), host.getPort())) { - result.add(current.getServerKey()); - break; + if (!isRevoked(entry)) { + for (SshdSocketAddress host : candidates) { + if (entry.isHostMatch(host.getHostName(), + host.getPort())) { + result.add(current.getServerKey()); + break; + } } } } @@ -266,6 +269,10 @@ public class OpenSshServerKeyDatabase private static final long serialVersionUID = 1L; } + private boolean isRevoked(KnownHostEntry entry) { + return MARKER_REVOKED.equals(entry.getMarker()); + } + private boolean find(Collection<SshdSocketAddress> candidates, PublicKey serverKey, List<HostEntryPair> entries, HostEntryPair[] modified) throws RevokedKeyException { @@ -273,22 +280,22 @@ public class OpenSshServerKeyDatabase KnownHostEntry entry = current.getHostEntry(); for (SshdSocketAddress host : candidates) { if (entry.isHostMatch(host.getHostName(), host.getPort())) { - boolean isRevoked = MARKER_REVOKED - .equals(entry.getMarker()); + boolean revoked = isRevoked(entry); if (KeyUtils.compareKeys(serverKey, current.getServerKey())) { // Exact match - if (isRevoked) { + if (revoked) { throw new RevokedKeyException(); } modified[0] = null; return true; - } else if (!isRevoked) { + } else if (!revoked) { // Server sent a different key modified[0] = current; // Keep going -- maybe there's another entry for this // host } + break; } } } diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/SshdText.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/SshdText.java index 73c2288ccc..c0f5719629 100644 --- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/SshdText.java +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/SshdText.java @@ -28,6 +28,7 @@ public final class SshdText extends TranslationBundle { /***/ public String configNoKnownAlgorithms; /***/ public String configProxyJumpNotSsh; /***/ public String configProxyJumpWithPath; + /***/ public String configUnknownAlgorithm; /***/ public String ftpCloseFailed; /***/ public String gssapiFailure; /***/ public String gssapiInitFailure; diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/ServerKeyDatabase.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/ServerKeyDatabase.java index b8e6cfd14d..b1b3c1808a 100644 --- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/ServerKeyDatabase.java +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/ServerKeyDatabase.java @@ -30,7 +30,7 @@ import org.eclipse.jgit.transport.CredentialsProvider; public interface ServerKeyDatabase { /** - * Retrieves all known host keys for the given addresses. + * Retrieves all known and not revoked host keys for the given addresses. * * @param connectAddress * IP address the session tried to connect to @@ -39,7 +39,7 @@ public interface ServerKeyDatabase { * @param config * giving access to potentially interesting configuration * settings - * @return the list of known keys for the given addresses + * @return the list of known and not revoked keys for the given addresses */ @NonNull List<PublicKey> lookup(@NonNull String connectAddress, diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSessionFactory.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSessionFactory.java index 2d7e0c7c77..cad959c904 100644 --- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSessionFactory.java +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSessionFactory.java @@ -47,7 +47,6 @@ import org.eclipse.jgit.internal.transport.ssh.OpenSshConfigFile; import org.eclipse.jgit.internal.transport.sshd.AuthenticationCanceledException; import org.eclipse.jgit.internal.transport.sshd.CachingKeyPairProvider; import org.eclipse.jgit.internal.transport.sshd.GssApiWithMicAuthFactory; -import org.eclipse.jgit.internal.transport.sshd.JGitKexExtensionHandler; import org.eclipse.jgit.internal.transport.sshd.JGitPasswordAuthFactory; import org.eclipse.jgit.internal.transport.sshd.JGitPublicKeyAuthFactory; import org.eclipse.jgit.internal.transport.sshd.JGitServerKeyVerifier; @@ -217,7 +216,6 @@ public class SshdSessionFactory extends SshSessionFactory implements Closeable { new JGitUserInteraction(credentialsProvider)); client.setUserAuthFactories(getUserAuthFactories()); client.setKeyIdentityProvider(defaultKeysProvider); - client.setKexExtensionHandler(JGitKexExtensionHandler.INSTANCE); // JGit-specific things: JGitSshClient jgitClient = (JGitSshClient) client; jgitClient.setKeyCache(getKeyCache()); |