aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit.ssh.apache
diff options
context:
space:
mode:
authorThomas Wolf <thomas.wolf@paranor.ch>2019-01-14 17:30:03 +0100
committerMatthias Sohn <matthias.sohn@sap.com>2019-05-06 15:22:05 +0200
commit86cee68e0d9282ecc6a49792693309e8d5d9d984 (patch)
tree7a4745417f0bcbd9f5e998f21f4703db38ee19c2 /org.eclipse.jgit.ssh.apache
parent756c2c2b3c9be5f9c487c08de868acaeb43348d9 (diff)
downloadjgit-86cee68e0d9282ecc6a49792693309e8d5d9d984.tar.gz
jgit-86cee68e0d9282ecc6a49792693309e8d5d9d984.zip
Apache MINA sshd client: adapt to sshd 2.2.0
Update target platforms, maven and bazel builds to use sshd 2.2.0. Adapt internal classes to changed sshd interfaces and remove previous work-arounds for asking repeatedly for key passwords and for loading keys lazily; both are now done by sshd. CQ: 19034 CQ: 19035 Bug: 541425 Change-Id: I85e1df6ebb8a94953a912d9b2b8a7b5bdfbd608a Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch> Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
Diffstat (limited to 'org.eclipse.jgit.ssh.apache')
-rw-r--r--org.eclipse.jgit.ssh.apache/BUILD2
-rw-r--r--org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF81
-rw-r--r--org.eclipse.jgit.ssh.apache/pom.xml2
-rw-r--r--org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/CachingKeyPairProvider.java87
-rw-r--r--org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/EncryptedFileKeyPairProvider.java158
-rw-r--r--org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitClientSession.java6
-rw-r--r--org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitHostConfigEntry.java17
-rw-r--r--org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyAuthFactory.java83
-rw-r--r--org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyAuthentication.java103
-rw-r--r--org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyIterator.java275
-rw-r--r--org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitSshClient.java57
-rw-r--r--org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitSshConfig.java5
-rw-r--r--org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyVerifier.java2
-rw-r--r--org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/PasswordProviderWrapper.java20
-rw-r--r--org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/RepeatingFilePasswordProvider.java41
-rw-r--r--org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSessionFactory.java25
16 files changed, 174 insertions, 790 deletions
diff --git a/org.eclipse.jgit.ssh.apache/BUILD b/org.eclipse.jgit.ssh.apache/BUILD
index a1a6c8e24c..372cfc228f 100644
--- a/org.eclipse.jgit.ssh.apache/BUILD
+++ b/org.eclipse.jgit.ssh.apache/BUILD
@@ -12,7 +12,7 @@ java_library(
deps = [
"//lib:eddsa",
"//lib:slf4j-api",
- "//lib:sshd-core",
+ "//lib:sshd-osgi",
"//lib:sshd-sftp",
"//org.eclipse.jgit:jgit",
],
diff --git a/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF b/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF
index 96dbd8a4ad..d1f7d49826 100644
--- a/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF
@@ -32,46 +32,47 @@ Export-Package: org.eclipse.jgit.internal.transport.sshd;version="5.4.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.0.0,2.1.0)",
- org.apache.sshd.client;version="[2.0.0,2.1.0)",
- org.apache.sshd.client.auth;version="[2.0.0,2.1.0)",
- org.apache.sshd.client.auth.keyboard;version="[2.0.0,2.1.0)",
- org.apache.sshd.client.auth.password;version="[2.0.0,2.1.0)",
- org.apache.sshd.client.auth.pubkey;version="[2.0.0,2.1.0)",
- org.apache.sshd.client.channel;version="[2.0.0,2.1.0)",
- org.apache.sshd.client.config.hosts;version="[2.0.0,2.1.0)",
- org.apache.sshd.client.config.keys;version="[2.0.0,2.1.0)",
- org.apache.sshd.client.future;version="[2.0.0,2.1.0)",
- org.apache.sshd.client.keyverifier;version="[2.0.0,2.1.0)",
- org.apache.sshd.client.session;version="[2.0.0,2.1.0)",
- org.apache.sshd.client.subsystem.sftp;version="[2.0.0,2.1.0)",
- org.apache.sshd.common;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.auth;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.channel;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.compression;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.config.keys;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.config.keys.loader;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.digest;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.forward;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.future;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.helpers;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.io;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.kex;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.keyprovider;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.mac;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.random;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.session;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.session.helpers;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.signature;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.subsystem.sftp;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.util;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.util.buffer;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.util.closeable;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.util.io;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.util.logging;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.util.net;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.util.security;version="[2.0.0,2.1.0)",
- org.apache.sshd.server.auth;version="[2.0.0,2.1.0)",
+ org.apache.sshd.agent;version="[2.2.0,2.3.0)",
+ org.apache.sshd.client;version="[2.2.0,2.3.0)",
+ org.apache.sshd.client.auth;version="[2.2.0,2.3.0)",
+ org.apache.sshd.client.auth.keyboard;version="[2.2.0,2.3.0)",
+ org.apache.sshd.client.auth.password;version="[2.2.0,2.3.0)",
+ org.apache.sshd.client.auth.pubkey;version="[2.2.0,2.3.0)",
+ org.apache.sshd.client.channel;version="[2.2.0,2.3.0)",
+ org.apache.sshd.client.config.hosts;version="[2.2.0,2.3.0)",
+ org.apache.sshd.client.config.keys;version="[2.2.0,2.3.0)",
+ org.apache.sshd.client.future;version="[2.2.0,2.3.0)",
+ org.apache.sshd.client.keyverifier;version="[2.2.0,2.3.0)",
+ org.apache.sshd.client.session;version="[2.2.0,2.3.0)",
+ org.apache.sshd.client.subsystem.sftp;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.auth;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.channel;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.compression;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.config.keys;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.config.keys.loader;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.digest;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.forward;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.future;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.helpers;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.io;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.kex;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.keyprovider;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.mac;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.random;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.session;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.session.helpers;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.signature;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.subsystem.sftp;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.util;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.util.buffer;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.util.closeable;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.util.io;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.util.io.resource;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.util.logging;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.util.net;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.util.security;version="[2.2.0,2.3.0)",
+ org.apache.sshd.server.auth;version="[2.2.0,2.3.0)",
org.eclipse.jgit.annotations;version="[5.4.0,5.5.0)",
org.eclipse.jgit.errors;version="[5.4.0,5.5.0)",
org.eclipse.jgit.fnmatch;version="[5.4.0,5.5.0)",
diff --git a/org.eclipse.jgit.ssh.apache/pom.xml b/org.eclipse.jgit.ssh.apache/pom.xml
index 242957a062..31bf6d7d77 100644
--- a/org.eclipse.jgit.ssh.apache/pom.xml
+++ b/org.eclipse.jgit.ssh.apache/pom.xml
@@ -75,7 +75,7 @@
<dependency>
<groupId>org.apache.sshd</groupId>
- <artifactId>sshd-core</artifactId>
+ <artifactId>sshd-osgi</artifactId>
<version>${apache-sshd-version}</version>
</dependency>
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/CachingKeyPairProvider.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/CachingKeyPairProvider.java
index 1072f32548..a1ec31883d 100644
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/CachingKeyPairProvider.java
+++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/CachingKeyPairProvider.java
@@ -45,10 +45,13 @@ package org.eclipse.jgit.internal.transport.sshd;
import static java.text.MessageFormat.format;
import java.io.IOException;
+import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.GeneralSecurityException;
+import java.security.InvalidKeyException;
import java.security.KeyPair;
+import java.security.PrivateKey;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -57,13 +60,20 @@ import java.util.List;
import java.util.NoSuchElementException;
import java.util.concurrent.CancellationException;
+import javax.security.auth.DestroyFailedException;
+
+import org.apache.sshd.common.NamedResource;
+import org.apache.sshd.common.config.keys.FilePasswordProvider;
+import org.apache.sshd.common.keyprovider.FileKeyPairProvider;
+import org.apache.sshd.common.session.SessionContext;
+import org.apache.sshd.common.util.io.resource.IoResource;
+import org.apache.sshd.common.util.security.SecurityUtils;
import org.eclipse.jgit.transport.sshd.KeyCache;
/**
- * A {@link EncryptedFileKeyPairProvider} that uses an external
- * {@link KeyCache}.
+ * A {@link FileKeyPairProvider} that uses an external {@link KeyCache}.
*/
-public class CachingKeyPairProvider extends EncryptedFileKeyPairProvider
+public class CachingKeyPairProvider extends FileKeyPairProvider
implements Iterable<KeyPair> {
private final KeyCache cache;
@@ -71,7 +81,7 @@ public class CachingKeyPairProvider extends EncryptedFileKeyPairProvider
/**
* Creates a new {@link CachingKeyPairProvider} using the given
* {@link KeyCache}. If the cache is {@code null}, this is a simple
- * {@link EncryptedFileKeyPairProvider}.
+ * {@link FileKeyPairProvider}.
*
* @param paths
* to load keys from
@@ -85,36 +95,36 @@ public class CachingKeyPairProvider extends EncryptedFileKeyPairProvider
@Override
public Iterator<KeyPair> iterator() {
+ return iterator(null);
+ }
+
+ private Iterator<KeyPair> iterator(SessionContext session) {
Collection<? extends Path> resources = getPaths();
if (resources.isEmpty()) {
return Collections.emptyListIterator();
}
- return new CancellingKeyPairIterator(resources);
+ return new CancellingKeyPairIterator(session, resources);
}
@Override
- public Iterable<KeyPair> loadKeys() {
- return this;
+ public Iterable<KeyPair> loadKeys(SessionContext session) {
+ return () -> iterator(session);
}
- @Override
- protected KeyPair doLoadKey(Path resource)
+ private KeyPair loadKey(SessionContext session, Path path)
throws IOException, GeneralSecurityException {
- if (!Files.exists(resource)) {
- log.warn(format(SshdText.get().identityFileNotFound, resource));
+ if (!Files.exists(path)) {
+ log.warn(format(SshdText.get().identityFileNotFound, path));
return null;
}
- // By calling doLoadKey(String, Path, FilePasswordProvider) instead of
- // super.doLoadKey(Path) we can bypass the key caching in
- // AbstractResourceKeyPairProvider, over which we have no real control.
- String resourceId = resource.toString();
+ IoResource<Path> resource = getIoResource(session, path);
if (cache == null) {
- return doLoadKey(resourceId, resource, getPasswordFinder());
+ return loadKey(session, resource, path, getPasswordFinder());
}
Throwable t[] = { null };
- KeyPair key = cache.get(resource, p -> {
+ KeyPair key = cache.get(path, p -> {
try {
- return doLoadKey(resourceId, p, getPasswordFinder());
+ return loadKey(session, resource, p, getPasswordFinder());
} catch (IOException | GeneralSecurityException e) {
t[0] = e;
return null;
@@ -130,18 +140,55 @@ public class CachingKeyPairProvider extends EncryptedFileKeyPairProvider
return key;
}
+ private KeyPair loadKey(SessionContext session, NamedResource resource,
+ Path path, FilePasswordProvider passwordProvider)
+ throws IOException, GeneralSecurityException {
+ try (InputStream stream = Files.newInputStream(path)) {
+ Iterable<KeyPair> ids = SecurityUtils.loadKeyPairIdentities(session,
+ resource, stream, passwordProvider);
+ if (ids == null) {
+ throw new InvalidKeyException(
+ format(SshdText.get().identityFileNoKey, path));
+ }
+ Iterator<KeyPair> keys = ids.iterator();
+ if (!keys.hasNext()) {
+ throw new InvalidKeyException(format(
+ SshdText.get().identityFileUnsupportedFormat, path));
+ }
+ KeyPair result = keys.next();
+ if (keys.hasNext()) {
+ log.warn(format(SshdText.get().identityFileMultipleKeys, path));
+ keys.forEachRemaining(k -> {
+ PrivateKey pk = k.getPrivate();
+ if (pk != null) {
+ try {
+ pk.destroy();
+ } catch (DestroyFailedException e) {
+ // Ignore
+ }
+ }
+ });
+ }
+ return result;
+ }
+ }
+
private class CancellingKeyPairIterator implements Iterator<KeyPair> {
+ private final SessionContext context;
+
private final Iterator<Path> paths;
private KeyPair nextItem;
private boolean nextSet;
- public CancellingKeyPairIterator(Collection<? extends Path> resources) {
+ public CancellingKeyPairIterator(SessionContext session,
+ Collection<? extends Path> resources) {
List<Path> copy = new ArrayList<>(resources.size());
copy.addAll(resources);
paths = copy.iterator();
+ context = session;
}
@Override
@@ -152,7 +199,7 @@ public class CachingKeyPairProvider extends EncryptedFileKeyPairProvider
nextSet = true;
while (nextItem == null && paths.hasNext()) {
try {
- nextItem = doLoadKey(paths.next());
+ nextItem = loadKey(context, paths.next());
} catch (CancellationException cancelled) {
throw cancelled;
} catch (Exception other) {
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/EncryptedFileKeyPairProvider.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/EncryptedFileKeyPairProvider.java
deleted file mode 100644
index ef8e611811..0000000000
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/EncryptedFileKeyPairProvider.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch>
- * and other copyright owners as documented in the project's IP log.
- *
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- * names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.eclipse.jgit.internal.transport.sshd;
-
-import static java.text.MessageFormat.format;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Path;
-import java.security.GeneralSecurityException;
-import java.security.InvalidKeyException;
-import java.security.KeyPair;
-import java.security.NoSuchProviderException;
-import java.security.PrivateKey;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-
-import javax.security.auth.DestroyFailedException;
-
-import org.apache.sshd.common.config.keys.FilePasswordProvider;
-import org.apache.sshd.common.config.keys.loader.KeyPairResourceParser;
-import org.apache.sshd.common.keyprovider.FileKeyPairProvider;
-import org.apache.sshd.common.util.io.IoUtils;
-import org.apache.sshd.common.util.security.SecurityUtils;
-import org.eclipse.jgit.internal.transport.sshd.RepeatingFilePasswordProvider.ResourceDecodeResult;
-
-/**
- * A {@link FileKeyPairProvider} that asks repeatedly for a passphrase for an
- * encrypted private key if the {@link FilePasswordProvider} is a
- * {@link RepeatingFilePasswordProvider}.
- */
-public abstract class EncryptedFileKeyPairProvider extends FileKeyPairProvider {
-
- // TODO: remove this class once we're based on sshd > 2.1.0. See upstream
- // issue SSHD-850 https://issues.apache.org/jira/browse/SSHD-850 and commit
- // https://github.com/apache/mina-sshd/commit/f19bd2e34
-
- /**
- * Creates a new {@link EncryptedFileKeyPairProvider} for the given
- * {@link Path}s.
- *
- * @param paths
- * to read keys from
- */
- public EncryptedFileKeyPairProvider(List<Path> paths) {
- super(paths);
- }
-
- @Override
- protected KeyPair doLoadKey(String resourceKey, InputStream inputStream,
- FilePasswordProvider provider)
- throws IOException, GeneralSecurityException {
- if (!(provider instanceof RepeatingFilePasswordProvider)) {
- return super.doLoadKey(resourceKey, inputStream, provider);
- }
- KeyPairResourceParser parser = SecurityUtils.getKeyPairResourceParser();
- if (parser == null) {
- // This is an internal configuration error, thus no translation.
- throw new NoSuchProviderException(
- "No registered key-pair resource parser"); //$NON-NLS-1$
- }
- RepeatingFilePasswordProvider realProvider = (RepeatingFilePasswordProvider) provider;
- // Read the stream now so that we can process the content several
- // times.
- List<String> lines = IoUtils.readAllLines(inputStream);
- Collection<KeyPair> ids = null;
- while (ids == null) {
- try {
- ids = parser.loadKeyPairs(resourceKey, realProvider, lines);
- realProvider.handleDecodeAttemptResult(resourceKey, "", null); //$NON-NLS-1$
- // No exception; success. Exit the loop even if ids is still
- // null!
- break;
- } catch (IOException | GeneralSecurityException
- | RuntimeException e) {
- ResourceDecodeResult loadResult = realProvider
- .handleDecodeAttemptResult(resourceKey, "", e); //$NON-NLS-1$
- if (loadResult == null
- || loadResult == ResourceDecodeResult.TERMINATE) {
- throw e;
- } else if (loadResult == ResourceDecodeResult.RETRY) {
- continue;
- }
- // IGNORE doesn't make any sense here, but OK, let's ignore it.
- // ids == null, so we'll throw an exception below.
- break;
- }
- }
- if (ids == null) {
- // The javadoc on loadKeyPairs says it might return null if no
- // key pair found. Bad API.
- throw new InvalidKeyException(
- format(SshdText.get().identityFileNoKey, resourceKey));
- }
- Iterator<KeyPair> keys = ids.iterator();
- if (!keys.hasNext()) {
- throw new InvalidKeyException(format(
- SshdText.get().identityFileUnsupportedFormat, resourceKey));
- }
- KeyPair result = keys.next();
- if (keys.hasNext()) {
- log.warn(format(SshdText.get().identityFileMultipleKeys,
- resourceKey));
- keys.forEachRemaining(k -> {
- PrivateKey pk = k.getPrivate();
- if (pk != null) {
- try {
- pk.destroy();
- } catch (DestroyFailedException e) {
- // Ignore
- }
- }
- });
- }
- return result;
- }
-}
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 dcf330a2a4..56f8ade667 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
@@ -46,6 +46,7 @@ import static java.text.MessageFormat.format;
import java.io.IOException;
import java.net.SocketAddress;
+import java.security.GeneralSecurityException;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.Iterator;
@@ -173,7 +174,8 @@ public class JGitClientSession extends ClientSessionImpl {
}
@Override
- protected byte[] sendKexInit() throws IOException {
+ protected byte[] sendKexInit()
+ throws IOException, GeneralSecurityException {
StatefulProxyConnector proxy = proxyHandler;
if (proxy != null) {
try {
@@ -187,7 +189,7 @@ public class JGitClientSession extends ClientSessionImpl {
// This is called only from the ClientSessionImpl
// constructor, where the return value is ignored.
return null;
- } catch (IOException e) {
+ } catch (IOException | GeneralSecurityException e) {
throw e;
} catch (Exception other) {
throw new IOException(other.getLocalizedMessage(), other);
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitHostConfigEntry.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitHostConfigEntry.java
index 7b22b88ab7..21e8beaeb4 100644
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitHostConfigEntry.java
+++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitHostConfigEntry.java
@@ -53,28 +53,11 @@ import org.eclipse.jgit.annotations.NonNull;
* A {@link HostConfigEntry} that provides access to the multi-valued keys as
* lists of strings. The super class treats them as single strings containing
* comma-separated lists.
- *
*/
public class JGitHostConfigEntry extends HostConfigEntry {
private Map<String, List<String>> multiValuedOptions;
- @Override
- public String getProperty(String name, String defaultValue) {
- // Upstream bug fix (SSHD-867): if there are _no_ properties at all, the
- // super implementation returns always null even if a default value is
- // given.
- //
- // See https://issues.apache.org/jira/projects/SSHD/issues/SSHD-867
- //
- // TODO: remove this override once we're based on sshd > 2.1.0
- Map<String, String> properties = getProperties();
- if (properties == null || properties.isEmpty()) {
- return defaultValue;
- }
- return super.getProperty(name, defaultValue);
- }
-
/**
* Sets the multi-valued options.
*
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyAuthFactory.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyAuthFactory.java
deleted file mode 100644
index 0b3de4ace3..0000000000
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyAuthFactory.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch>
- * and other copyright owners as documented in the project's IP log.
- *
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- * names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.eclipse.jgit.internal.transport.sshd;
-
-import java.util.List;
-
-import org.apache.sshd.client.auth.AbstractUserAuthFactory;
-import org.apache.sshd.client.auth.UserAuth;
-import org.apache.sshd.client.auth.pubkey.UserAuthPublicKeyFactory;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.signature.Signature;
-import org.apache.sshd.common.signature.SignatureFactoriesManager;
-
-/**
- * A customized authentication factory for public key user authentication. The
- * default implementation {@link UserAuthPublicKeyFactory} ends up doing some
- * crazy stream "magic" that loads too many keys too early.
- */
-public class JGitPublicKeyAuthFactory extends AbstractUserAuthFactory
- implements SignatureFactoriesManager {
-
- /** The singleton {@link JGitPublicKeyAuthFactory}. */
- public static final JGitPublicKeyAuthFactory INSTANCE = new JGitPublicKeyAuthFactory();
-
- private JGitPublicKeyAuthFactory() {
- super(UserAuthPublicKeyFactory.NAME);
- }
-
- @Override
- public UserAuth create() {
- return new JGitPublicKeyAuthentication(getSignatureFactories());
- }
-
- @Override
- public List<NamedFactory<Signature>> getSignatureFactories() {
- return null;
- }
-
- @Override
- public void setSignatureFactories(List<NamedFactory<Signature>> factories) {
- throw new UnsupportedOperationException();
- }
-}
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
deleted file mode 100644
index 63b3990b13..0000000000
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyAuthentication.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch>
- * and other copyright owners as documented in the project's IP log.
- *
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- * names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.eclipse.jgit.internal.transport.sshd;
-
-import java.util.List;
-
-import org.apache.sshd.client.auth.pubkey.UserAuthPublicKey;
-import org.apache.sshd.client.session.ClientSession;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.signature.Signature;
-
-/**
- * A specialized public key authentication handler that uses our own
- * {@link JGitPublicKeyIterator}. The super class creates in
- * {@link #init(ClientSession, String)} a
- * {@link org.apache.sshd.client.auth.pubkey.UserAuthPublicKeyIterator}, which
- * in its constructor does some strange {@link java.util.stream.Stream} "magic"
- * that ends up loading keys prematurely.
- */
-public class JGitPublicKeyAuthentication extends UserAuthPublicKey {
-
- private ClientSession clientSession;
-
- private String serviceName;
-
- /**
- * Creates a new {@link JGitPublicKeyAuthentication}.
- *
- * @param factories
- * signature factories to use
- */
- public JGitPublicKeyAuthentication(
- List<NamedFactory<Signature>> factories) {
- super(factories);
- }
-
- @Override
- public void init(ClientSession session, String service) throws Exception {
- // Do *not* call super.init(); it'll create a UserAuthPublicKeyIterator
- // and that's where things then go wrong. Instead, do the whole
- // initialization directly here.
- clientSession = session;
- serviceName = service;
- releaseKeys();
- // Use our own iterator!
- keys = new JGitPublicKeyIterator(session, this);
- }
-
- @Override
- public ClientSession getClientSession() {
- return clientSession;
- }
-
- @Override
- public ClientSession getSession() {
- return clientSession;
- }
-
- @Override
- public String getService() {
- return serviceName;
- }
-}
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyIterator.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyIterator.java
deleted file mode 100644
index cda12623d8..0000000000
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyIterator.java
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch>
- * and other copyright owners as documented in the project's IP log.
- *
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- * names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.eclipse.jgit.internal.transport.sshd;
-
-import java.io.IOException;
-import java.nio.channels.Channel;
-import java.security.KeyPair;
-import java.security.PublicKey;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.apache.sshd.agent.SshAgent;
-import org.apache.sshd.agent.SshAgentFactory;
-import org.apache.sshd.client.auth.pubkey.AbstractKeyPairIterator;
-import org.apache.sshd.client.auth.pubkey.KeyAgentIdentity;
-import org.apache.sshd.client.auth.pubkey.KeyPairIdentity;
-import org.apache.sshd.client.auth.pubkey.PublicKeyIdentity;
-import org.apache.sshd.client.config.hosts.HostConfigEntry;
-import org.apache.sshd.client.session.ClientSession;
-import org.apache.sshd.common.FactoryManager;
-import org.apache.sshd.common.keyprovider.KeyIdentityProvider;
-import org.apache.sshd.common.signature.SignatureFactoriesManager;
-
-/**
- * A new iterator over key pairs that we use instead of the default
- * {@link org.apache.sshd.client.auth.pubkey.UserAuthPublicKeyIterator}, which
- * in its constructor does some strange {@link java.util.stream.Stream} "magic"
- * that ends up loading keys prematurely. This class uses plain
- * {@link Iterator}s instead to avoid that problem. Used in
- * {@link JGitPublicKeyAuthentication}.
- *
- * @see <a href=
- * "https://issues.apache.org/jira/projects/SSHD/issues/SSHD-860">Upstream
- * issue SSHD-860</a>
- */
-public class JGitPublicKeyIterator
- extends AbstractKeyPairIterator<PublicKeyIdentity> implements Channel {
-
- // Re: the cause for the problem mentioned above has not been determined.
- // It looks as if either the Apache code inadvertently calls
- // GenericUtils.isEmpty() on all streams (which would load the first key
- // of each stream), or the Java stream implementation does some prefetching.
- // It's not entirely clear. Using Iterators we have more control over
- // what happens when.
-
- private final AtomicBoolean open = new AtomicBoolean(true);
-
- private SshAgent agent;
-
- private final List<Iterator<PublicKeyIdentity>> keys = new ArrayList<>(3);
-
- private final Iterator<Iterator<PublicKeyIdentity>> keyIter;
-
- private Iterator<PublicKeyIdentity> current;
-
- private Boolean hasElement;
-
- /**
- * Creates a new {@link JGitPublicKeyIterator}.
- *
- * @param session
- * we're trying to authenticate
- * @param signatureFactories
- * to use
- * @throws Exception
- * if an {@link SshAgentFactory} is configured and getting
- * identities from the agent fails
- */
- public JGitPublicKeyIterator(ClientSession session,
- SignatureFactoriesManager signatureFactories) throws Exception {
- super(session);
- boolean useAgent = true;
- if (session instanceof JGitClientSession) {
- HostConfigEntry config = ((JGitClientSession) session)
- .getHostConfigEntry();
- useAgent = !config.isIdentitiesOnly();
- }
- if (useAgent) {
- FactoryManager manager = session.getFactoryManager();
- SshAgentFactory factory = manager == null ? null
- : manager.getAgentFactory();
- if (factory != null) {
- try {
- agent = factory.createClient(manager);
- keys.add(new AgentIdentityIterator(agent));
- } catch (IOException e) {
- try {
- closeAgent();
- } catch (IOException err) {
- e.addSuppressed(err);
- }
- throw e;
- }
- }
- }
- keys.add(
- new KeyPairIdentityIterator(session.getRegisteredIdentities(),
- session, signatureFactories));
- keys.add(new KeyPairIdentityIterator(session.getKeyPairProvider(),
- session, signatureFactories));
- keyIter = keys.iterator();
- }
-
- @Override
- public boolean isOpen() {
- return open.get();
- }
-
- @Override
- public void close() throws IOException {
- if (open.getAndSet(false)) {
- closeAgent();
- }
- }
-
- @Override
- public boolean hasNext() {
- if (!isOpen()) {
- return false;
- }
- if (hasElement != null) {
- return hasElement.booleanValue();
- }
- while (current == null || !current.hasNext()) {
- if (keyIter.hasNext()) {
- current = keyIter.next();
- } else {
- current = null;
- hasElement = Boolean.FALSE;
- return false;
- }
- }
- hasElement = Boolean.TRUE;
- return true;
- }
-
- @Override
- public PublicKeyIdentity next() {
- if (!isOpen() || hasElement == null && !hasNext()
- || !hasElement.booleanValue()) {
- throw new NoSuchElementException();
- }
- hasElement = null;
- PublicKeyIdentity result;
- try {
- result = current.next();
- } catch (NoSuchElementException e) {
- result = null;
- }
- return result;
- }
-
- private void closeAgent() throws IOException {
- if (agent == null) {
- return;
- }
- try {
- agent.close();
- } finally {
- agent = null;
- }
- }
-
- /**
- * An {@link Iterator} that maps the data obtained from an agent to
- * {@link PublicKeyIdentity}.
- */
- private static class AgentIdentityIterator
- implements Iterator<PublicKeyIdentity> {
-
- private final SshAgent agent;
-
- private final Iterator<? extends Map.Entry<PublicKey, String>> iter;
-
- public AgentIdentityIterator(SshAgent agent) throws IOException {
- this.agent = agent;
- iter = agent == null ? null : agent.getIdentities().iterator();
- }
-
- @Override
- public boolean hasNext() {
- return iter != null && iter.hasNext();
- }
-
- @Override
- public PublicKeyIdentity next() {
- if (iter == null) {
- throw new NoSuchElementException();
- }
- Map.Entry<PublicKey, String> entry = iter.next();
- return new KeyAgentIdentity(agent, entry.getKey(),
- entry.getValue());
- }
- }
-
- /**
- * An {@link Iterator} that maps {@link KeyPair} to
- * {@link PublicKeyIdentity}.
- */
- private static class KeyPairIdentityIterator
- implements Iterator<PublicKeyIdentity> {
-
- private final Iterator<KeyPair> keyPairs;
-
- private final ClientSession session;
-
- private final SignatureFactoriesManager signatureFactories;
-
- public KeyPairIdentityIterator(KeyIdentityProvider provider,
- ClientSession session,
- SignatureFactoriesManager signatureFactories) {
- this.session = session;
- this.signatureFactories = signatureFactories;
- keyPairs = provider == null ? null : provider.loadKeys().iterator();
- }
-
- @Override
- public boolean hasNext() {
- return keyPairs != null && keyPairs.hasNext();
- }
-
- @Override
- public PublicKeyIdentity next() {
- if (keyPairs == null) {
- throw new NoSuchElementException();
- }
- KeyPair key = keyPairs.next();
- return new KeyPairIdentity(signatureFactories, session, key);
- }
- }
-}
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 b9ff5e5208..98e71dfe4b 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
@@ -48,10 +48,12 @@ import static org.eclipse.jgit.internal.transport.ssh.OpenSshConfigFile.positive
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
+import java.net.SocketAddress;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.util.Arrays;
import java.util.Iterator;
@@ -66,12 +68,14 @@ import org.apache.sshd.client.future.ConnectFuture;
import org.apache.sshd.client.future.DefaultConnectFuture;
import org.apache.sshd.client.session.ClientSessionImpl;
import org.apache.sshd.client.session.SessionFactory;
+import org.apache.sshd.common.AttributeRepository;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.future.SshFutureListener;
import org.apache.sshd.common.io.IoConnectFuture;
import org.apache.sshd.common.io.IoSession;
import org.apache.sshd.common.keyprovider.AbstractResourceKeyPairProvider;
-import org.apache.sshd.common.keyprovider.KeyPairProvider;
+import org.apache.sshd.common.keyprovider.KeyIdentityProvider;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.session.helpers.AbstractSession;
import org.apache.sshd.common.util.ValidateUtils;
import org.eclipse.jgit.internal.transport.sshd.proxy.HttpClientConnector;
@@ -117,7 +121,8 @@ public class JGitSshClient extends SshClient {
}
@Override
- public ConnectFuture connect(HostConfigEntry hostConfig)
+ public ConnectFuture connect(HostConfigEntry hostConfig,
+ AttributeRepository context, SocketAddress localAddress)
throws IOException {
if (connector == null) {
throw new IllegalStateException("SshClient not started."); //$NON-NLS-1$
@@ -149,7 +154,7 @@ public class JGitSshClient extends SshClient {
address = configureProxy(proxy, address);
proxy.clearPassword();
}
- connector.connect(address).addListener(listener);
+ connector.connect(address, this, localAddress).addListener(listener);
return connectFuture;
}
@@ -263,16 +268,16 @@ public class JGitSshClient extends SshClient {
identities, keyCache);
ourConfiguredKeysProvider.setPasswordFinder(passwordProvider);
if (hostConfig.isIdentitiesOnly()) {
- session.setKeyPairProvider(ourConfiguredKeysProvider);
+ session.setKeyIdentityProvider(ourConfiguredKeysProvider);
} else {
- KeyPairProvider defaultKeysProvider = getKeyPairProvider();
+ KeyIdentityProvider defaultKeysProvider = getKeyIdentityProvider();
if (defaultKeysProvider instanceof AbstractResourceKeyPairProvider<?>) {
((AbstractResourceKeyPairProvider<?>) defaultKeysProvider)
.setPasswordFinder(passwordProvider);
}
- KeyPairProvider combinedProvider = new CombinedKeyPairProvider(
+ KeyIdentityProvider combinedProvider = new CombinedKeyIdentityProvider(
ourConfiguredKeysProvider, defaultKeysProvider);
- session.setKeyPairProvider(combinedProvider);
+ session.setKeyIdentityProvider(combinedProvider);
}
return session;
}
@@ -363,39 +368,30 @@ public class JGitSshClient extends SshClient {
}
/**
- * A {@link KeyPairProvider} that iterates over the {@link Iterable}s
- * returned by other {@link KeyPairProvider}s.
+ * A {@link KeyIdentityProvider} that iterates over the {@link Iterable}s
+ * returned by other {@link KeyIdentityProvider}s.
*/
- private static class CombinedKeyPairProvider implements KeyPairProvider {
+ private static class CombinedKeyIdentityProvider
+ implements KeyIdentityProvider {
- private final List<KeyPairProvider> providers;
+ private final List<KeyIdentityProvider> providers;
- public CombinedKeyPairProvider(KeyPairProvider... providers) {
+ public CombinedKeyIdentityProvider(KeyIdentityProvider... providers) {
this(Arrays.stream(providers).filter(Objects::nonNull)
.collect(Collectors.toList()));
}
- public CombinedKeyPairProvider(List<KeyPairProvider> providers) {
+ public CombinedKeyIdentityProvider(
+ List<KeyIdentityProvider> providers) {
this.providers = providers;
}
@Override
- public Iterable<String> getKeyTypes() {
- throw new UnsupportedOperationException(
- "Should not have been called in a ssh client"); //$NON-NLS-1$
- }
-
- @Override
- public KeyPair loadKey(String type) {
- throw new UnsupportedOperationException(
- "Should not have been called in a ssh client"); //$NON-NLS-1$
- }
-
- @Override
- public Iterable<KeyPair> loadKeys() {
+ public Iterable<KeyPair> loadKeys(SessionContext context) {
return () -> new Iterator<KeyPair>() {
- private Iterator<KeyPairProvider> factories = providers.iterator();
+ private Iterator<KeyIdentityProvider> factories = providers
+ .iterator();
private Iterator<KeyPair> current;
private Boolean hasElement;
@@ -407,7 +403,12 @@ public class JGitSshClient extends SshClient {
}
while (current == null || !current.hasNext()) {
if (factories.hasNext()) {
- current = factories.next().loadKeys().iterator();
+ try {
+ current = factories.next().loadKeys(context)
+ .iterator();
+ } catch (IOException | GeneralSecurityException e) {
+ throw new RuntimeException(e);
+ }
} else {
current = null;
hasElement = Boolean.FALSE;
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitSshConfig.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitSshConfig.java
index 984643961f..6468b3e276 100644
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitSshConfig.java
+++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitSshConfig.java
@@ -47,11 +47,13 @@ import static org.eclipse.jgit.internal.transport.ssh.OpenSshConfigFile.positive
import java.io.File;
import java.io.IOException;
+import java.net.SocketAddress;
import java.util.Map;
import java.util.TreeMap;
import org.apache.sshd.client.config.hosts.HostConfigEntry;
import org.apache.sshd.client.config.hosts.HostConfigEntryResolver;
+import org.apache.sshd.common.AttributeRepository;
import org.apache.sshd.common.util.net.SshdSocketAddress;
import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.internal.transport.ssh.OpenSshConfigFile;
@@ -101,7 +103,8 @@ public class JGitSshConfig implements HostConfigEntryResolver {
@Override
public HostConfigEntry resolveEffectiveHost(String host, int port,
- String username) throws IOException {
+ SocketAddress localAddress, String username,
+ AttributeRepository attributes) throws IOException {
HostEntry entry = configFile.lookup(host, port, username);
JGitHostConfigEntry config = new JGitHostConfigEntry();
// Apache MINA conflates all keys, even multi-valued ones, in one map
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyVerifier.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyVerifier.java
index 4246fbe3bc..381f7cfc22 100644
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyVerifier.java
+++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyVerifier.java
@@ -672,7 +672,7 @@ public class OpenSshServerKeyVerifier
continue;
}
try {
- PublicKey serverKey = keyPart.resolvePublicKey(
+ PublicKey serverKey = keyPart.resolvePublicKey(null,
PublicKeyEntryResolver.IGNORING);
if (serverKey == null) {
LOG.warn(format(
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/PasswordProviderWrapper.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/PasswordProviderWrapper.java
index 93bd10285a..bec65f1d3a 100644
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/PasswordProviderWrapper.java
+++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/PasswordProviderWrapper.java
@@ -50,6 +50,8 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.sshd.common.NamedResource;
+import org.apache.sshd.common.session.SessionContext;
import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.transport.URIish;
@@ -83,10 +85,12 @@ public class PasswordProviderWrapper implements RepeatingFilePasswordProvider {
}
@Override
- public String getPassword(String resourceKey) throws IOException {
+ public String getPassword(SessionContext session, NamedResource resource,
+ int attemptIndex) throws IOException {
+ String key = resource.getName();
int attempt = counts
- .computeIfAbsent(resourceKey, k -> new AtomicInteger()).get();
- char[] passphrase = delegate.getPassphrase(toUri(resourceKey), attempt);
+ .computeIfAbsent(key, k -> new AtomicInteger()).get();
+ char[] passphrase = delegate.getPassphrase(toUri(key), attempt);
if (passphrase == null) {
return null;
}
@@ -98,21 +102,23 @@ public class PasswordProviderWrapper implements RepeatingFilePasswordProvider {
}
@Override
- public ResourceDecodeResult handleDecodeAttemptResult(String resourceKey,
+ public ResourceDecodeResult handleDecodeAttemptResult(
+ SessionContext session, NamedResource resource, int retryIndex,
String password, Exception err)
throws IOException, GeneralSecurityException {
- AtomicInteger count = counts.get(resourceKey);
+ String key = resource.getName();
+ AtomicInteger count = counts.get(key);
int numberOfAttempts = count == null ? 0 : count.incrementAndGet();
ResourceDecodeResult result = null;
try {
- if (delegate.keyLoaded(toUri(resourceKey), numberOfAttempts, err)) {
+ if (delegate.keyLoaded(toUri(key), numberOfAttempts, err)) {
result = ResourceDecodeResult.RETRY;
} else {
result = ResourceDecodeResult.TERMINATE;
}
} finally {
if (result != ResourceDecodeResult.RETRY) {
- counts.remove(resourceKey);
+ counts.remove(key);
}
}
return result;
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/RepeatingFilePasswordProvider.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/RepeatingFilePasswordProvider.java
index e491cae130..977f1a22fe 100644
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/RepeatingFilePasswordProvider.java
+++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/RepeatingFilePasswordProvider.java
@@ -42,9 +42,6 @@
*/
package org.eclipse.jgit.internal.transport.sshd;
-import java.io.IOException;
-import java.security.GeneralSecurityException;
-
import org.apache.sshd.common.config.keys.FilePasswordProvider;
/**
@@ -74,42 +71,4 @@ public interface RepeatingFilePasswordProvider extends FilePasswordProvider {
return 1;
}
- // The following part of this interface is from the upstream resolution of
- // SSHD-850. See https://github.com/apache/mina-sshd/commit/f19bd2e34 .
- // TODO: remove this once we move to sshd > 2.1.0
-
- /**
- * Result value of
- * {@link RepeatingFilePasswordProvider#handleDecodeAttemptResult(String, String, Exception)}.
- */
- public enum ResourceDecodeResult {
- /** Re-throw the decoding exception. */
- TERMINATE,
- /** Retry the decoding process - including password prompt. */
- RETRY,
- /** Skip attempt and see if we can proceed without the key. */
- IGNORE;
- }
-
- /**
- * Invoked to inform the password provider about the decoding result.
- * <b>Note:</b> any exception thrown from this method (including if called
- * to inform about success) will be propagated instead of the original (if
- * any was reported)
- *
- * @param resourceKey
- * The resource key representing the <U>private</U> file
- * @param password
- * The password that was attempted
- * @param err
- * The attempt result - {@code null} for success
- * @return How to proceed in case of error - <u>ignored</u> if invoked in
- * order to report success. <b>Note:</b> {@code null} is same as
- * {@link ResourceDecodeResult#TERMINATE}.
- * @throws IOException
- * @throws GeneralSecurityException
- */
- ResourceDecodeResult handleDecodeAttemptResult(String resourceKey,
- String password, Exception err)
- throws IOException, GeneralSecurityException;
}
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 cdd47bf323..2f9691ed63 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
@@ -64,18 +64,18 @@ import org.apache.sshd.client.ClientBuilder;
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.auth.UserAuth;
import org.apache.sshd.client.auth.keyboard.UserAuthKeyboardInteractiveFactory;
+import org.apache.sshd.client.auth.pubkey.UserAuthPublicKeyFactory;
import org.apache.sshd.client.config.hosts.HostConfigEntryResolver;
import org.apache.sshd.client.keyverifier.ServerKeyVerifier;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.compression.BuiltinCompressions;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
-import org.apache.sshd.common.keyprovider.KeyPairProvider;
+import org.apache.sshd.common.keyprovider.KeyIdentityProvider;
import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.errors.TransportException;
import org.eclipse.jgit.internal.transport.sshd.CachingKeyPairProvider;
import org.eclipse.jgit.internal.transport.sshd.GssApiWithMicAuthFactory;
import org.eclipse.jgit.internal.transport.sshd.JGitPasswordAuthFactory;
-import org.eclipse.jgit.internal.transport.sshd.JGitPublicKeyAuthFactory;
import org.eclipse.jgit.internal.transport.sshd.JGitSshClient;
import org.eclipse.jgit.internal.transport.sshd.JGitSshConfig;
import org.eclipse.jgit.internal.transport.sshd.JGitUserInteraction;
@@ -211,7 +211,7 @@ public class SshdSessionFactory extends SshSessionFactory implements Closeable {
}
HostConfigEntryResolver configFile = getHostConfigEntryResolver(
home, sshDir);
- KeyPairProvider defaultKeysProvider = toKeyPairProvider(
+ KeyIdentityProvider defaultKeysProvider = toKeyIdentityProvider(
getDefaultKeys(sshDir));
KeyPasswordProvider passphrases = createKeyPasswordProvider(
credentialsProvider);
@@ -227,7 +227,7 @@ public class SshdSessionFactory extends SshSessionFactory implements Closeable {
client.setUserInteraction(
new JGitUserInteraction(credentialsProvider));
client.setUserAuthFactories(getUserAuthFactories());
- client.setKeyPairProvider(defaultKeysProvider);
+ client.setKeyIdentityProvider(defaultKeysProvider);
// JGit-specific things:
JGitSshClient jgitClient = (JGitSshClient) client;
jgitClient.setKeyCache(getKeyCache());
@@ -438,17 +438,18 @@ public class SshdSessionFactory extends SshSessionFactory implements Closeable {
/**
* Converts an {@link Iterable} of {link KeyPair}s into a
- * {@link KeyPairProvider}.
+ * {@link KeyIdentityProvider}.
*
* @param keys
- * to provide via the returned {@link KeyPairProvider}
- * @return a {@link KeyPairProvider} that provides the given {@code keys}
+ * to provide via the returned {@link KeyIdentityProvider}
+ * @return a {@link KeyIdentityProvider} that provides the given
+ * {@code keys}
*/
- private KeyPairProvider toKeyPairProvider(Iterable<KeyPair> keys) {
- if (keys instanceof KeyPairProvider) {
- return (KeyPairProvider) keys;
+ private KeyIdentityProvider toKeyIdentityProvider(Iterable<KeyPair> keys) {
+ if (keys instanceof KeyIdentityProvider) {
+ return (KeyIdentityProvider) keys;
}
- return () -> keys;
+ return (session) -> keys;
}
/**
@@ -522,7 +523,7 @@ public class SshdSessionFactory extends SshSessionFactory implements Closeable {
// Password auth doesn't have this problem.
return Collections.unmodifiableList(
Arrays.asList(GssApiWithMicAuthFactory.INSTANCE,
- JGitPublicKeyAuthFactory.INSTANCE,
+ UserAuthPublicKeyFactory.INSTANCE,
JGitPasswordAuthFactory.INSTANCE,
UserAuthKeyboardInteractiveFactory.INSTANCE));
}