summaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit.junit.ssh
diff options
context:
space:
mode:
authorMatthias Sohn <matthias.sohn@sap.com>2020-06-10 10:14:28 +0200
committerMatthias Sohn <matthias.sohn@sap.com>2020-06-10 10:33:50 +0200
commit4887894ffd637030a311ca8d60b78515b1a5cf35 (patch)
treea890edb80b54f5c5078a10b938b37f04ee12edca /org.eclipse.jgit.junit.ssh
parent629fa260c03a54cac35836010df34b565d13fe85 (diff)
parent0ec6e4b3d5becf0025dcf83e8b843c9c34043ba0 (diff)
downloadjgit-4887894ffd637030a311ca8d60b78515b1a5cf35.tar.gz
jgit-4887894ffd637030a311ca8d60b78515b1a5cf35.zip
Merge branch 'master' into next
* master: SimpleMergeTest: Clean up code style Prepare 5.8.1-SNAPSHOT builds Handle Fragment-Host declaration when updating version JGit v5.8.0.202006091008-r Prepare 5.9.0-SNAPSHOT builds Handle Fragment-Host declaration when updating version Add benchmark for strategies how to move a file Add getter for unpackErrorHandler in ReceivePack Upgrade maven-project-info-reports-plugin to 3.1.0 Upgrade maven-shade-plugin to 3.2.4 ObjectDirectoryInserter: Open FileOutputStream in try-with-resource ObjectDirectoryInserter: Remove redundant 'throws' declarations ObjectDirectory: Further clean up insertUnpackedObject Add Git#shutdown for releasing resources held by JGit process ApplyCommand: use context lines to determine hunk location GPG: don't prompt for a passphrase for unprotected keys Fix typo in org.eclipse.jgit.ssh.jsch.test MANIFEST Fix ProtectedMembersInFinalClass warning flagged by error prone Use version range to define fragment host bundle version ObjectDirectory: Explicitly handle NoSuchFileException ObjectDirectory: Fail immediately when atomic move is not supported Fix jgit packaging Fix InvalidInlineTag error flagged by error prone Fix BadComparable error flagged by error prone Add tests for RawTextComparator.WS_IGNORE_CHANGE.hash() Update Orbit to R20200529191137 for final Eclipse release 2020-06 Organize manifest of org.eclipse.jgit.pgm Do not include log4j implementation in jgit Decouple JSch from JGit Core Decouple BouncyCastle from JGit Core Verify that the user home directory is valid WindowCache: conditional JMX setup RawTextComparator.WS_IGNORE_CHANGE must not compare whitespace Revert "PackBitmapIndex: Not buffer inflated bitmap in BasePackBitmapIndex" Update jetty to 9.4.28.v20200408 Add 4.16 staging target platform In-memory SSH keys for the "no files" sshd tests Builder API to configure SshdSessionFactories TransportHttp: abort on time-out or on SocketException Ignore core.eol if core.autocrlf=input Attributes: fix handling of text=auto in combination with eol Bazel: Remove superfluous dependencies flagged by unused_deps Log stack trace if CachingKeyPairProvider hits unexpected exception Update Orbit to S20200519202422 and ant to 1.10.8 Include full IssuerFingerprint in GPG signature Bazel: Fix src_sha1 of bcpg-jdk15on Suppress API error for new method BitmapIndex.Bitmap#retrieveCompressed Fix wrong @since tags added in dcb0265 PackBitmapIndex: Set distance threshold PackBitmapIndex: Not buffer inflated bitmap in BasePackBitmapIndex PackBitmapIndex: Remove convertedBitmaps in the Remapper PackBitmapIndex: Reduce memory usage in GC PackBitmapIndex: Add AddToBitmapWithCacheFilter class PackBitmapIndex: Add util methods and builder to BitmapCommit PackBitmapIndex: Move BitmapCommit to a top-level class Refactor: Make retriveCompressed an method of the Bitmap class Fix downloading LFS Object fails behind proxy Allow for using custom s3 host with lfs server ReceivePack: adding IterativeConnectivityChecker Moving transport/internal -> internal/transport Fix error occurring during checkout Change-Id: Ic11286e16ed6a72c6372297b310336dd040689d1
Diffstat (limited to 'org.eclipse.jgit.junit.ssh')
-rw-r--r--org.eclipse.jgit.junit.ssh/.classpath1
-rw-r--r--org.eclipse.jgit.junit.ssh/BUILD7
-rw-r--r--org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF11
-rw-r--r--org.eclipse.jgit.junit.ssh/build.properties3
-rw-r--r--org.eclipse.jgit.junit.ssh/pom.xml19
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_dsa12
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_dsa.pub1
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_dsa_testpass15
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_dsa_testpass.pub1
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_2565
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_256.pub1
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_256_testpass8
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_256_testpass.pub1
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_3846
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_384.pub1
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_384_testpass9
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_384_testpass.pub1
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_5217
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_521.pub1
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_521_testpass10
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_521_testpass.pub1
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ed255197
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ed25519.pub1
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ed25519_expensive_testpass8
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ed25519_expensive_testpass.pub1
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ed25519_testpass8
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ed25519_testpass.pub1
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_102415
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_1024.pub1
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_1024_testpass18
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_1024_testpass.pub1
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_204827
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_2048.pub1
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_2048_testpass30
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_2048_testpass.pub1
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_307239
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_3072.pub1
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_3072_testpass42
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_3072_testpass.pub1
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_409651
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_4096.pub1
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_4096_testpass54
-rw-r--r--org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_4096_testpass.pub1
-rw-r--r--org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshTestBase.java813
-rw-r--r--org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshTestGitServer.java37
-rw-r--r--org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshTestHarness.java418
46 files changed, 1691 insertions, 8 deletions
diff --git a/org.eclipse.jgit.junit.ssh/.classpath b/org.eclipse.jgit.junit.ssh/.classpath
index eca7bdba8f..110168ffa1 100644
--- a/org.eclipse.jgit.junit.ssh/.classpath
+++ b/org.eclipse.jgit.junit.ssh/.classpath
@@ -3,5 +3,6 @@
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="resources"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/org.eclipse.jgit.junit.ssh/BUILD b/org.eclipse.jgit.junit.ssh/BUILD
index 906053e39a..61b5ce78cb 100644
--- a/org.eclipse.jgit.junit.ssh/BUILD
+++ b/org.eclipse.jgit.junit.ssh/BUILD
@@ -8,10 +8,17 @@ java_library(
srcs = glob(["src/**/*.java"]),
resource_strip_prefix = "org.eclipse.jgit.junit.ssh/resources",
resources = glob(["resources/**"]),
+ visibility = [
+ "//org.eclipse.jgit.ssh.apache.test:__pkg__",
+ "//org.eclipse.jgit.ssh.jsch.test:__pkg__",
+ ],
deps = [
+ "//lib:jsch",
+ "//lib:junit",
"//lib:sshd-osgi",
"//lib:sshd-sftp",
# We want these deps to be provided_deps
"//org.eclipse.jgit:jgit",
+ "//org.eclipse.jgit.junit:junit",
],
)
diff --git a/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF
index 28f3513b8d..2b06d48047 100644
--- a/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF
@@ -8,7 +8,8 @@ Bundle-Localization: plugin
Bundle-Vendor: %Bundle-Vendor
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
-Import-Package: org.apache.sshd.common;version="[2.4.0,2.5.0)",
+Import-Package: com.jcraft.jsch;version="0.1.55",
+ org.apache.sshd.common;version="[2.4.0,2.5.0)",
org.apache.sshd.common.config.keys;version="[2.4.0,2.5.0)",
org.apache.sshd.common.file.virtualfs;version="[2.4.0,2.5.0)",
org.apache.sshd.common.helpers;version="[2.4.0,2.5.0)",
@@ -31,7 +32,15 @@ Import-Package: org.apache.sshd.common;version="[2.4.0,2.5.0)",
org.apache.sshd.server.subsystem;version="[2.4.0,2.5.0)",
org.apache.sshd.server.subsystem.sftp;version="[2.4.0,2.5.0)",
org.eclipse.jgit.annotations;version="[6.0.0,6.1.0)",
+ org.eclipse.jgit.api;version="[6.0.0,6.1.0)",
+ org.eclipse.jgit.api.errors;version="[6.0.0,6.1.0)",
+ org.eclipse.jgit.errors;version="[6.0.0,6.1.0)",
+ org.eclipse.jgit.junit;version="[6.0.0,6.1.0)",
org.eclipse.jgit.lib;version="[6.0.0,6.1.0)",
+ org.eclipse.jgit.revwalk;version="[6.0.0,6.1.0)",
org.eclipse.jgit.transport;version="[6.0.0,6.1.0)",
+ org.eclipse.jgit.util;version="[6.0.0,6.1.0)",
+ org.junit;version="[4.13,5.0.0)",
+ org.junit.experimental.theories;version="[4.13,5.0.0)",
org.slf4j;version="[1.7.0,2.0.0)"
Export-Package: org.eclipse.jgit.junit.ssh;version="6.0.0"
diff --git a/org.eclipse.jgit.junit.ssh/build.properties b/org.eclipse.jgit.junit.ssh/build.properties
index aa1a008269..84f1c95cfa 100644
--- a/org.eclipse.jgit.junit.ssh/build.properties
+++ b/org.eclipse.jgit.junit.ssh/build.properties
@@ -1,4 +1,5 @@
-source.. = src/
+source.. = src/,\
+ resources/
output.. = bin/
bin.includes = META-INF/,\
.,\
diff --git a/org.eclipse.jgit.junit.ssh/pom.xml b/org.eclipse.jgit.junit.ssh/pom.xml
index 5f53ee799d..cd4626037f 100644
--- a/org.eclipse.jgit.junit.ssh/pom.xml
+++ b/org.eclipse.jgit.junit.ssh/pom.xml
@@ -40,6 +40,12 @@
</dependency>
<dependency>
+ <groupId>org.eclipse.jgit</groupId>
+ <artifactId>org.eclipse.jgit.junit</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-osgi</artifactId>
<version>${apache-sshd-version}</version>
@@ -52,6 +58,16 @@
</dependency>
<dependency>
+ <groupId>com.jcraft</groupId>
+ <artifactId>jsch</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.jcraft</groupId>
+ <artifactId>jzlib</artifactId>
+ </dependency>
+
+ <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>provided</scope>
@@ -68,6 +84,9 @@
<include>plugin.properties</include>
</includes>
</resource>
+ <resource>
+ <directory>resources/</directory>
+ </resource>
</resources>
<plugins>
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_dsa b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_dsa
new file mode 100644
index 0000000000..f097516df2
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_dsa
@@ -0,0 +1,12 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBuwIBAAKBgQC+mJEX/XBloWhNM+BEuoh5z+EAuZfVyJ8cHNKlQmC1sWrENKGh
+P8ZhzWeHW0A7JnvTQgMqW6yD4mDzCpbR1wEz5KeXAphEjCGPnRik7Q4RjpZTd6Nq
+nNF/CYYGYuwR7ZGUPITTpKJWgX6NkEk+a4tvTWP7xfxOq5iKIspFEhEOlQIVAIBi
+TdAR8M2twrXZdspBjdJprjDXAoGAOrRYdXRHhpsOewIi9GQah0lde7AVrmZawK9Z
+BwhDUagL58gS8PvcsNNVhS2dKEX45pqZmgayt2UEE/5bke3+CdZtStDsezBYMu8P
+I/0qjOULhl7xLJT5ayCIN2ZuvcH8vtqH89fXgZkIz0c68AzY1ZFjJPc+TdE0puI9
+3mMVRaoCgYEAslyMZiOwYA3oiFMQTJEphKdgejWsjqQ9LoKppfZ3d4Jj1V3tgI1s
+/wHfoneUUrUwM+sMHZKXbBDLWWQUOSIxDYcXKDkbZ1FlmhvJR+45D2LyLKjEnjVD
+lQCwYly4P26zXqciZS7k3H/DjiHtAPUeoHm9IYb1A03K8Bd/xW0guMcCFFeUfQeX
+3mFPCfKJ5uXMjkPUqIo/
+-----END DSA PRIVATE KEY-----
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_dsa.pub b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_dsa.pub
new file mode 100644
index 0000000000..676685332e
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_dsa.pub
@@ -0,0 +1 @@
+ssh-dss AAAAB3NzaC1kc3MAAACBAL6YkRf9cGWhaE0z4ES6iHnP4QC5l9XInxwc0qVCYLWxasQ0oaE/xmHNZ4dbQDsme9NCAypbrIPiYPMKltHXATPkp5cCmESMIY+dGKTtDhGOllN3o2qc0X8JhgZi7BHtkZQ8hNOkolaBfo2QST5ri29NY/vF/E6rmIoiykUSEQ6VAAAAFQCAYk3QEfDNrcK12XbKQY3Saa4w1wAAAIA6tFh1dEeGmw57AiL0ZBqHSV17sBWuZlrAr1kHCENRqAvnyBLw+9yw01WFLZ0oRfjmmpmaBrK3ZQQT/luR7f4J1m1K0Ox7MFgy7w8j/SqM5QuGXvEslPlrIIg3Zm69wfy+2ofz19eBmQjPRzrwDNjVkWMk9z5N0TSm4j3eYxVFqgAAAIEAslyMZiOwYA3oiFMQTJEphKdgejWsjqQ9LoKppfZ3d4Jj1V3tgI1s/wHfoneUUrUwM+sMHZKXbBDLWWQUOSIxDYcXKDkbZ1FlmhvJR+45D2LyLKjEnjVDlQCwYly4P26zXqciZS7k3H/DjiHtAPUeoHm9IYb1A03K8Bd/xW0guMc= testuser
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_dsa_testpass b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_dsa_testpass
new file mode 100644
index 0000000000..375d38fe43
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_dsa_testpass
@@ -0,0 +1,15 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,EBB6ACAA4F1FC558865344E3C2B91A5F
+
+CWMAq20YBO8ueHnmQ7IaKa7ISEvNbwbzqoBIxor6TZYSU3JvlIf5AL2UvGpMJDk1
+fyROdCjdVAeWKQC0peU54D3YnD3am4gZlrclPMjMRnjBmqO+vnU7bTudIt/8y6vg
+gmHZki0/aceQ6QvGwGrxBezBPaK4Bc926lePujHHE/PbtuQgkBw7rhIBGKVuy0qN
+sFbC4AGnYl5tudy5RLvCcpQvpDCjnYAfGQVimRYSOsaOwTEBvsnQFUH1pqQAYLC4
+Capo1yj6Q0smzwsGoyFSvmPkyzLbMTT42m+M48gc5nuaOkbU5absqOb8cQgRVmWB
+W1HnpufqGtyF6vBK+qlzg157bhQDYMwZuubX+IrTRL67djBiSIpiRDZduJavT3zq
+iSrRGSnjnkhp4NxtJJjprDQe4VAZEccN5GWPjClbogjpsG+fmTJiNDMI88L11DrV
+Vjeaxsql31iur/xGwvmBYd+/V+Nu4v7kA4XViO/3ZIpqi8qvQ3si5hbALSX0OPnm
+9q0eMp9qfmzPvbmysq2BEenBaZDwEWYTYpcF23pjwc1EvmfP8EAYT+xH95ZhxVmc
+Sujq0VyGeIhy7+gRHZo2Fg==
+-----END DSA PRIVATE KEY-----
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_dsa_testpass.pub b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_dsa_testpass.pub
new file mode 100644
index 0000000000..676685332e
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_dsa_testpass.pub
@@ -0,0 +1 @@
+ssh-dss AAAAB3NzaC1kc3MAAACBAL6YkRf9cGWhaE0z4ES6iHnP4QC5l9XInxwc0qVCYLWxasQ0oaE/xmHNZ4dbQDsme9NCAypbrIPiYPMKltHXATPkp5cCmESMIY+dGKTtDhGOllN3o2qc0X8JhgZi7BHtkZQ8hNOkolaBfo2QST5ri29NY/vF/E6rmIoiykUSEQ6VAAAAFQCAYk3QEfDNrcK12XbKQY3Saa4w1wAAAIA6tFh1dEeGmw57AiL0ZBqHSV17sBWuZlrAr1kHCENRqAvnyBLw+9yw01WFLZ0oRfjmmpmaBrK3ZQQT/luR7f4J1m1K0Ox7MFgy7w8j/SqM5QuGXvEslPlrIIg3Zm69wfy+2ofz19eBmQjPRzrwDNjVkWMk9z5N0TSm4j3eYxVFqgAAAIEAslyMZiOwYA3oiFMQTJEphKdgejWsjqQ9LoKppfZ3d4Jj1V3tgI1s/wHfoneUUrUwM+sMHZKXbBDLWWQUOSIxDYcXKDkbZ1FlmhvJR+45D2LyLKjEnjVDlQCwYly4P26zXqciZS7k3H/DjiHtAPUeoHm9IYb1A03K8Bd/xW0guMc= testuser
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_256 b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_256
new file mode 100644
index 0000000000..8a4c864afa
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_256
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIAqXVKoLNr7/wNluxmGZnZmJCD/5h06ptAICRk+8FIjfoAoGCCqGSM49
+AwEHoUQDQgAEoQHTUWwu3nJnCHeSv3YE59UxfuGNjAXLzK0MjDwoXt6/qePjjKAQ
+ehHdAIYQHr9zYJu5SA5b86HL5glqjcy+Pg==
+-----END EC PRIVATE KEY-----
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_256.pub b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_256.pub
new file mode 100644
index 0000000000..43540ec0ec
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_256.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKEB01FsLt5yZwh3kr92BOfVMX7hjYwFy8ytDIw8KF7ev6nj44ygEHoR3QCGEB6/c2CbuUgOW/Ohy+YJao3Mvj4= testuser
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_256_testpass b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_256_testpass
new file mode 100644
index 0000000000..b767c8e99a
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_256_testpass
@@ -0,0 +1,8 @@
+-----BEGIN EC PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,86940587F5C93441B585F469FF31AC06
+
+LaIyzOCeBPJA6OkFOFnFfVorYO+Rm1g5QpvqEcFZ+FCuEvhMZN00NMZ5hHKvwQLt
+XSK5Se8MUD+e6qFH/ZcoYTixUqYjYJlOkxJzKaXg5nM82wQHa1LqQqcL4IDrJmzv
+qJbCLtl6XOfkQQUA6gezqhtiNYWLDZIPfZ0dsaIB/fU=
+-----END EC PRIVATE KEY-----
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_256_testpass.pub b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_256_testpass.pub
new file mode 100644
index 0000000000..43540ec0ec
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_256_testpass.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKEB01FsLt5yZwh3kr92BOfVMX7hjYwFy8ytDIw8KF7ev6nj44ygEHoR3QCGEB6/c2CbuUgOW/Ohy+YJao3Mvj4= testuser
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_384 b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_384
new file mode 100644
index 0000000000..dc2ac86508
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_384
@@ -0,0 +1,6 @@
+-----BEGIN EC PRIVATE KEY-----
+MIGkAgEBBDAgAgPcgkPaitxOrphrrLe+am0eUhYi346UUTnb5WZL3164MEjFByd9
+Egv6KwB4hCqgBwYFK4EEACKhZANiAAQhJrJ+vJLbkbd9C1he+4XuxaOyZ1IqYJqz
+PZCXcKkIlgy+0I07RAxRUd75GHKc4ViyUnLq5odV25H6FNzHJHO7ifE4H6jrEpA/
+UL6LkfZReYZ4sNmeQI7MBXm2IXQsIZ4=
+-----END EC PRIVATE KEY-----
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_384.pub b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_384.pub
new file mode 100644
index 0000000000..3e813a5e48
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_384.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBCEmsn68ktuRt30LWF77he7Fo7JnUipgmrM9kJdwqQiWDL7QjTtEDFFR3vkYcpzhWLJScurmh1XbkfoU3Mckc7uJ8TgfqOsSkD9QvouR9lF5hniw2Z5AjswFebYhdCwhng== testuser
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_384_testpass b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_384_testpass
new file mode 100644
index 0000000000..06032d049f
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_384_testpass
@@ -0,0 +1,9 @@
+-----BEGIN EC PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,80B1C4D6D9B45690A07B9886050C63A7
+
+WxS7EGs77p1aPZuxXW0G/yTFKAh4M30AaeGQBPjDR/HTAmPJe3irDH56fdmGhY4+
+zBT+6X1VppB+UqB0nJ/qHq7FeA37eJPXJnuskPh2BzLlBaVhmEnzZylEW33gzAuH
+XzC/Z2OjdWRjn+rBXM5fwo9IIC0WzTNpBokdeMo8tpnPzGTlsTFeyVgMZJ3wOlCO
+4ItX9ddY5P+MrLzWP672IyZZqAQGfLec4YoJ286wpHY=
+-----END EC PRIVATE KEY-----
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_384_testpass.pub b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_384_testpass.pub
new file mode 100644
index 0000000000..3e813a5e48
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_384_testpass.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBCEmsn68ktuRt30LWF77he7Fo7JnUipgmrM9kJdwqQiWDL7QjTtEDFFR3vkYcpzhWLJScurmh1XbkfoU3Mckc7uJ8TgfqOsSkD9QvouR9lF5hniw2Z5AjswFebYhdCwhng== testuser
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_521 b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_521
new file mode 100644
index 0000000000..c28151e5ab
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_521
@@ -0,0 +1,7 @@
+-----BEGIN EC PRIVATE KEY-----
+MIHcAgEBBEIB4zI/MCFSfJ0wfyLwZPxG1vP2o3fF7fEuOTpK+fxbDHKYz6r4bNv3
+HkPQEVTIAqDl7r5Ebcx0BMeYr9oe69tPZIigBwYFK4EEACOhgYkDgYYABAChltEM
+zT8dXwIhQD2iuy7QbaBkhWMhpFaxztvzSQqoTZvBgBsOmSr9frFA93lSQoHD1Bge
+wuwBkNGm9lRcw0tEgABqifONkj07Qj2847MKS1iiVu1sHh7Ys3YimyfJc+nZRNi+
+W03nkcdvWd6PP8y/VENoV7+BtIO9txj8Dt5LYOtFgw==
+-----END EC PRIVATE KEY-----
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_521.pub b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_521.pub
new file mode 100644
index 0000000000..9bac1e80f0
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_521.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAChltEMzT8dXwIhQD2iuy7QbaBkhWMhpFaxztvzSQqoTZvBgBsOmSr9frFA93lSQoHD1BgewuwBkNGm9lRcw0tEgABqifONkj07Qj2847MKS1iiVu1sHh7Ys3YimyfJc+nZRNi+W03nkcdvWd6PP8y/VENoV7+BtIO9txj8Dt5LYOtFgw== testuser
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_521_testpass b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_521_testpass
new file mode 100644
index 0000000000..c1c1bbaced
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_521_testpass
@@ -0,0 +1,10 @@
+-----BEGIN EC PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,7070032284B3C310353B8C352AB2D8CE
+
+UBgXTwobcLX1VFtQaLNiwwVzdN1+TlmhSRCnU+kv2EpunXxfvyOVS1mZTam9NyhE
+O0Mc7REi5hDHp8UYM7MP+wrwK+QM3D2Vm2/Rh0+acd4Gu2XGACJHWXGIyKwNsU0R
+ZddusHIi+979sHw3vSUFCvuDwc9YZBoujpzls7NYEWXiAVv6wd1RCtAynkBk/uvc
+1F7iHLuRttejBPvrb/a2AxY0pFpCuCVmGjuiS5bfVWBj7xLEplqdU6/95rd9pRwx
+e2uRlU0AFiQGNPStfhjgfCWnmf+aX3vAgVqkLMYKYQE=
+-----END EC PRIVATE KEY-----
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_521_testpass.pub b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_521_testpass.pub
new file mode 100644
index 0000000000..9bac1e80f0
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ecdsa_521_testpass.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAChltEMzT8dXwIhQD2iuy7QbaBkhWMhpFaxztvzSQqoTZvBgBsOmSr9frFA93lSQoHD1BgewuwBkNGm9lRcw0tEgABqifONkj07Qj2847MKS1iiVu1sHh7Ys3YimyfJc+nZRNi+W03nkcdvWd6PP8y/VENoV7+BtIO9txj8Dt5LYOtFgw== testuser
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ed25519 b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ed25519
new file mode 100644
index 0000000000..02afa54788
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ed25519
@@ -0,0 +1,7 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
+QyNTUxOQAAACBIJlrW8XB46iAVY0XqbjYKG8wJ95iILxOb5ONQhFBvPQAAAJC8jORLvIzk
+SwAAAAtzc2gtZWQyNTUxOQAAACBIJlrW8XB46iAVY0XqbjYKG8wJ95iILxOb5ONQhFBvPQ
+AAAECjklggj+glO2K60Ptg+aXYGBdvXtk9TQnKINhrEIxW9UgmWtbxcHjqIBVjRepuNgob
+zAn3mIgvE5vk41CEUG89AAAACHRlc3R1c2VyAQIDBAU=
+-----END OPENSSH PRIVATE KEY-----
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ed25519.pub b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ed25519.pub
new file mode 100644
index 0000000000..7857db5602
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ed25519.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEgmWtbxcHjqIBVjRepuNgobzAn3mIgvE5vk41CEUG89 testuser
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ed25519_expensive_testpass b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ed25519_expensive_testpass
new file mode 100644
index 0000000000..904cf302c2
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ed25519_expensive_testpass
@@ -0,0 +1,8 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABAsFN8vig
+Nw4/Ow6xbb7MAZAAABAAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIEZXZRjuttLufaP8
+wFD/i4lYPnKk01z46Jwv/9U4mPioAAAAkHLErPaXeC179rzXMaSwClstzsKvJ/Gqh2cY8d
+cWzymXtKZcivWMKesRHbC+1qRx53ofx15IzT5Fmg6NuNk4sm2s+lH8x8HN3CPWBfjGIelP
+iQUR6M6Y91mPigpRC2HUJmJIaFNdrRqFF84a5+qyK//tdy1fv4gNMLi5yPdXiL/Ttw05FS
+LkFikjfvSGZSO/MA==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ed25519_expensive_testpass.pub b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ed25519_expensive_testpass.pub
new file mode 100644
index 0000000000..65038b5f4c
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ed25519_expensive_testpass.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEZXZRjuttLufaP8wFD/i4lYPnKk01z46Jwv/9U4mPio test
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ed25519_testpass b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ed25519_testpass
new file mode 100644
index 0000000000..7ad4a77056
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ed25519_testpass
@@ -0,0 +1,8 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABA4hLhtuV
+MNBBC+j45F4KFcAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIEgmWtbxcHjqIBVj
+RepuNgobzAn3mIgvE5vk41CEUG89AAAAkPH343T+NbHb05J/6CHnF9h7C11LJDHe2x9+HC
+dNB50fP9M+KJ/cC5cqIeHm8y0fg+wX2WLlJPjNVoSd5MciWCfUWO0k32ciVpoyrGCz5Gh6
+axKVVY42QjdgO0S2QxWClnAuMdkVdl2ke/PcGp4yqTTIruAAB0m3d0jZdKNT1Vziww0rQB
++DOo7xQ9Tx99U+rA==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ed25519_testpass.pub b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ed25519_testpass.pub
new file mode 100644
index 0000000000..7857db5602
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_ed25519_testpass.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEgmWtbxcHjqIBVjRepuNgobzAn3mIgvE5vk41CEUG89 testuser
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_1024 b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_1024
new file mode 100644
index 0000000000..0b403674fa
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_1024
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQDGfj0Jmqj+CUb+WdFrlkRV49TJtNzvvMb/nX20zqgGm50cOIYr
+MzfFpSQN630pXeAidIgiV/PWAsipntQfSWPRG+RpB/wMKHVUNPJCJkjjRFEa56Yx
+gAhgNwF511K13x4p2tEN0r6wsfw1nos9VoO8XDBAu3lellAgBdufyCt8vwIDAQAB
+AoGBAKU+bNP1BGDQGmEfJv+5DlSuofP19MREVSpx0zfVnv45SFc5G0EVl4Wb0GMi
+O4VXmIM2nipxLBZrJOBI0HDnaQcx1zQR6tpvBO7BbAU0sflOvUDldUStTnz3TTQW
+2ECm2y8bsArNqkeLndqis3ICmYL1budhDdUYYcqv10IlbjPJAkEA6yE0zduCE2wM
+Ob7lcqiQCOiXeZ0KijHTmSZV4Fn4HRbp+XuxUpjSWFaoDTO0bncGNE+JYjywe64V
+XvEORb1hTQJBANgcjEoCrUFY7VYWx3f1tpN0Q6jwwcj67Sd+ysaZNgghTPU32GTa
+auGQFv+tifUQMyyVrhAfZ6s8myKOH5SWUDsCQGVvqOkaRq58UXXkDfZ+E81UEm0L
+u81Mm52ZdTjZd3mNNhlELIaWmUA0+kDfynpRbOLKYVl5FyX0PxH7ao3Zmo0CQFpL
++1YFLk0KkggRdoCp+wI7ZvXUurN2HNcOxD0c0RWujFA9aD4jgNsEcIeeA/GQNkGf
+vN3hsVg793oFti5Ia/cCQAubCMvRqFTyXUBervPVC0kibO3OwYt2xN/7lQXAVSfm
+nRwV/46trioV3rMF84hpOk/46Qe5hqbWyQnL+dZljpY=
+-----END RSA PRIVATE KEY-----
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_1024.pub b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_1024.pub
new file mode 100644
index 0000000000..4aded97ab6
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_1024.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDGfj0Jmqj+CUb+WdFrlkRV49TJtNzvvMb/nX20zqgGm50cOIYrMzfFpSQN630pXeAidIgiV/PWAsipntQfSWPRG+RpB/wMKHVUNPJCJkjjRFEa56YxgAhgNwF511K13x4p2tEN0r6wsfw1nos9VoO8XDBAu3lellAgBdufyCt8vw== testuser
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_1024_testpass b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_1024_testpass
new file mode 100644
index 0000000000..0b66dc0aa9
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_1024_testpass
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,4B8025AB7456E0A2B48408407C6E3FF4
+
+B9gztX+5QQPqMR/79eJHxjNdo9baoKjfWY+Ye7t1h7ucOPMCEXRSP8FwPwBfbzQh
+6W1AHOfiDCHTzArDRG9SXrFfRlU+8o5ffs/TStTNqde/AXJeNuM3pwbmqKV1m9oY
+oWelabmGtNUvGMAHMFm/2uk4BgS9Kjv71KnJg0cQQfIiPKTPBncJe/R5mf6O12rB
+ByOrrlDmjtgveZZsgggEZbU9Y9DYiHZp6yT0JepxIWNImQ/A9EeUPTQheVB2ECT6
+DLUOwRfyFhdvsfD2eXLK+u7T47keFny3rIfm1e8HC1y3X+T/nFxKGoShecx1NmEL
+HMgOKyFSwGSZh5jxE66dSQoc+rRZhCWSyPJEb9cjwp8JLON8oH3Yg+PIXYJhMFK+
+nghAIVXp3/H+cYXMN27j21cRGC7ePuF3YX242Gr+LSj42Wf4qCMTyvWur8WrSe6U
+iyrWJ8+w2J7O7rRHGM8v+GYGaiX1qIXFheM/774vsDmjuueOhkjiqs254gaap8xk
+LcJUuqJU2AL21+eW+R+EG3Rl/AbMIaQ4GFDpHfgEmmvVVoOvJunNQkDIP9JzKczO
+g7cN/EYLUC2TcdmNaiunB8RhXMiaTqw4kYJEzy4lsxk/xjubC7vlQKTvtnWCpob+
+WpHX/2FBdPPULt38AIk4HQq7vKvKw9TmvGeOvQmCUun7eCFFhxKrwNKO5YCXAHvs
+fv7JNGfrST4jwbqCvamuk+XTf0GkgJN83G7DT04EIzee6wwai/NRDybgYptJsj9G
+6wBpKH15BtkktuUzM1MCt5+T6Ccsg+d6xE6eStimwDxkXCjvgz/KlS+sPKe7uS4h
+-----END RSA PRIVATE KEY-----
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_1024_testpass.pub b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_1024_testpass.pub
new file mode 100644
index 0000000000..4aded97ab6
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_1024_testpass.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDGfj0Jmqj+CUb+WdFrlkRV49TJtNzvvMb/nX20zqgGm50cOIYrMzfFpSQN630pXeAidIgiV/PWAsipntQfSWPRG+RpB/wMKHVUNPJCJkjjRFEa56YxgAhgNwF511K13x4p2tEN0r6wsfw1nos9VoO8XDBAu3lellAgBdufyCt8vw== testuser
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_2048 b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_2048
new file mode 100644
index 0000000000..a2d7d62310
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_2048
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEA1sFEWiIp8SVO8/sDhKJ67O7tQdtDwsqWi9Fm238tAuy26OH+
+ylireX/qVcndU8Yr0qYShcwloEUaeNe77VgffZa2ZIUee75u8u+WGCYjea4RQ1bZ
+tDcioWkxl+xYfVuuKaA8CQn47XUdyoA/5P3DpDhaJl8KevaYupJNHOo9Lt2E5dVT
+93OksZBOQ6E3nNlsefP/hnFByiczlde2GIXP2sWLoxsiVsbI+CLeGtxQxPubX9yu
+vWrl/nv/yERR5ZBOEVY5N2+1BdT7DvOIMg2q60FpJv6zZpQi7Ov1iONMVafytIRW
+Ma2rPkpS83Ebxh5c92T3rgLUf5DcZjKvBgxtpwIDAQABAoIBAHeDZv6iNKU3FhFB
+iFuv8Kka7n7P/43QIKf/CTbuN6aBBenkm18QqZ0cStUjWkDc8FZyhaxgSDBBRNIr
+fTJA8IV78lVOoABNooEgRG98ChIVhRXsp4tbg7JAUJEzvqtE8k/IFKETI61CmCmx
+5d0SPGaP1du02KhFxAlQkgmdch85st+tRFv5GZXqiKbR6QlNaJgIXIoOlykVvnz6
+rnl6Q1SDutBOKGC8xFrDzFI8KxLFe3RFQxtHtsLRPcrrpukNSHICTMO4jtGXSZ12
+9Zh29ZtkouCDk+b176dGrJKfIBbxXtBGVXtkuo7rj8EWVWrJiiYbL2hcWD+Pw1VL
+0GWkaEECgYEA+RrE4nVkfdJ0Zgx+sACQqs4uKi/JuFHU69JnO7RB2lDwzQbIPKl7
+nn0ExJ4V9m035/3mqKReBIyMIjIhwXgLFiakNO/+GAWa4ycRMB3pV8WaVFCnWZEF
+oLRg1ukoLs01TfOszcux831n8zmPlz/NLTTkC26O3WXsVmnCSlPXd1MCgYEA3LMW
+B8ONEDFYACB8xKA5zn3jrKq/yVFfiQzEO87zSkgG1mQbsb5T8jggWiIHVyZKQUSk
+8ZkrwBKW+LwyRik1lVwawALmcvvN3VyCW5BukniErAUu8jb3+R2aFdrjzpiNqzMF
+M18BPDElirTXMjJusC7z/0I7+gyAu9ttYJY1id0CgYBqjIiqVIwnRV2ESNPndFZs
+uMQGR2qA7H+mXtjJMND6EKTvDXeYeuXlZJQlhXjfbtf64x9GAwgz6eoGtmq51h7n
+2p9iBUUqATu+7Xbsnd6xLFRWvCjYpq9BjeXeBtypKB0kupWvcPEstPdBkd1ZVHDu
+ZTElsqRpDq+IRrRUFoiTAQKBgQCxTGmRWSa08H8asv6o03M9EONbrlyedXHDXu8y
+gQHwFcbwasHY2+cCetZ6skWlXIxgvK2prXx5NDX2ovHcbXSvhauzv2C01NdAUvYi
+avh5ULp8mzlouoIhrgdAMXW7XdDJzRYLe/I5Ed5v/PG4UM2dWksIMISQT4UH5bKL
+2oAuPQKBgCQaJ2oc5qE/f6MiL0XfGSdY26gOZcVrm9L1XKXtyHkfj4xWYQ58DSYa
+vNZH3fGyfR+q7g1WgUmLib5etOjUjbVYRjIEov8xLA41UZZLNGRLc4VzgeCT73CW
+YvbxeN93fL0tgvKeyNVzIsWRazHMo+aQodlXvpPckHXYxYHS93W+
+-----END RSA PRIVATE KEY-----
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_2048.pub b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_2048.pub
new file mode 100644
index 0000000000..b787e36483
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_2048.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDWwURaIinxJU7z+wOEonrs7u1B20PCypaL0Wbbfy0C7Lbo4f7KWKt5f+pVyd1TxivSphKFzCWgRRp417vtWB99lrZkhR57vm7y75YYJiN5rhFDVtm0NyKhaTGX7Fh9W64poDwJCfjtdR3KgD/k/cOkOFomXwp69pi6kk0c6j0u3YTl1VP3c6SxkE5DoTec2Wx58/+GcUHKJzOV17YYhc/axYujGyJWxsj4It4a3FDE+5tf3K69auX+e//IRFHlkE4RVjk3b7UF1PsO84gyDarrQWkm/rNmlCLs6/WI40xVp/K0hFYxras+SlLzcRvGHlz3ZPeuAtR/kNxmMq8GDG2n testuser
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_2048_testpass b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_2048_testpass
new file mode 100644
index 0000000000..7b3a3f4e58
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_2048_testpass
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,DED10D02EF74A02F24F46AB44A84F4B3
+
+DL0M2dNu7cXNLE6KGPqEt3pSKiQw6ajlxYaaXyyAwvpZB0Pv44HUjXfhMONs5FH5
+rDjz1RSYDRdMF/h6FtltdEEareXwMtRTvP2wb0gsQKiYS5M9WeebM3TY55JmwS1U
+hhrPrEaP6hs6WEy9xp9DVxJN2y1MA5iss7M+fQ4/C6QeSp9On6bgCEvNPwdMTS4A
+3sLp+yzRvrefQmSi2SWbJoYlChitOMdc84iDJXDo951QQLX75GqMm41fFLHHrcTO
+7v/k/D7p/KLlNf43Ru+2yPNE7qyEK0pDSjvPnjPykIa6SWq3Qx2DnVdtZ7bWF8LA
+B349QmuE1r/YYHNvWnp0/5SztivJk3NMeTT29PIiZoHioo53Vtru6RcXYMOvHbh1
+maioVkgRl5gkhLC86o4V+3hiJQNrVCWMuT+lxLY2Tt6bFXulbf3WH69AEAFW4S4a
+e7zH4fwvkSwz+bFxg9B+Yynv42ke1a+tvDI+aDvsMmv9JUCy6G4Te+isXYxLdtT0
+nyqJ+wwP53AWS8gOvoUXzxxsEchTDtQnBQMWuSHEdFrk3OLGykNN6vZaxUROxpJf
+vcPl7JniWGhzDzUdHh0AQbLxXoZlv4YU1uO/+1OnrvIkuO5DCDg8v2sTFRW6sgiU
+JXm3QPJiU/bu3/FJ4XCU75cTcunZMXsL7TY9mURq7Y5FxcByuvSL2nlA7KfROTVq
+I6w+Ej+r99C1u0G63sk5b99Pm4cb2+V/sr7pslqlU9Yw1Z5hw55ibih04CiWZAhJ
+Az7s8ho4dY9E1n/XJSe26p14RPYU+w7WZuN6Xb04t3+BhF4Ubbsdn6F3lAVOrrWH
+6xNoncmIEYdfdcI089UPpV4/bIpdakXRIbaLmpshyU6aIRUXqYkzwduXcHUrxgq3
+1QCZHNvq1+9i5Wqj8JP8cZrq9YVldOeXdIIsm1SSepbDQ7820d5T4Dk6cj85BXYC
+6t12UNZ5mhzTvIAqbR3Who53jQ8cY0MSVXR6Jd6vPih2OhAnccnuJmRCNNJkL4mg
+pVcsSgYjoUx+w6Ou1muCIkkGpdEhLLwEnKFc0HUmPBToRqgiB1Aec+7oMv62XhXe
+yA26/dpT6N6SWYKN7MyDWUe2ilkmjXI+JrPCH+/w4FXh+GKafOn8XlcBnRWHVBEX
+ZQfYLckd1j9B6p7By7ed2H+8FxZLz3gthcSxRG89IP/EQImY/e9A3aoLrFX6C/W0
+Gd6JrIvzC2bZCvrq+VTYs3101j1xe6ZDJnq68HokjpG8P9DlFYDOpRetCjR7TuqN
+I5s606KAsGkt/jfbSNUMIEtuM0AC75m3TTJeWdfYh/PVYevUC+pUoreJ0ZsttQ2i
+D550sAAzU7PCzZQsDF1i2jv/YZ0wXz7+C7YFiGNmb3HmXH0Lb2HISJR5UL+x+hHY
+RArXtVubqjFz179pawzI0n03Z1OXiHolwer7C+Twmarv7SPe8rMU3HcHP25JeTAW
+mo0PxNGG3yQPlRZWpPz8LEWGo+fDqfA4kbqy4+Pvo7B8YFIQyE9QG+oBv+/7uqMU
+UOs1ZqsmvEUmvWMeQnWsjETmHKucbmTBm8ktsesb3sCKfY/pf8hAHbO6+9J3ebYf
+-----END RSA PRIVATE KEY-----
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_2048_testpass.pub b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_2048_testpass.pub
new file mode 100644
index 0000000000..b787e36483
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_2048_testpass.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDWwURaIinxJU7z+wOEonrs7u1B20PCypaL0Wbbfy0C7Lbo4f7KWKt5f+pVyd1TxivSphKFzCWgRRp417vtWB99lrZkhR57vm7y75YYJiN5rhFDVtm0NyKhaTGX7Fh9W64poDwJCfjtdR3KgD/k/cOkOFomXwp69pi6kk0c6j0u3YTl1VP3c6SxkE5DoTec2Wx58/+GcUHKJzOV17YYhc/axYujGyJWxsj4It4a3FDE+5tf3K69auX+e//IRFHlkE4RVjk3b7UF1PsO84gyDarrQWkm/rNmlCLs6/WI40xVp/K0hFYxras+SlLzcRvGHlz3ZPeuAtR/kNxmMq8GDG2n testuser
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_3072 b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_3072
new file mode 100644
index 0000000000..10d622c905
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_3072
@@ -0,0 +1,39 @@
+-----BEGIN RSA PRIVATE KEY-----
+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
+-----END RSA PRIVATE KEY-----
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_3072.pub b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_3072.pub
new file mode 100644
index 0000000000..686d3b06b1
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_3072.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDUzzht4+crpxH0SL8fRLfpCF19SXSpQhlesc29L2L+elNl03WYLNbF40ebRglBamf0Co9kYb908a3cJAQvnZMpdrBj/SSz7inQkn3brSipUEUmtcTmVq1VAJ0hnUZHaIkveRktcddKRRHKAQv1oF84RRKYLhKQ1jQs4a7AxnZPJeIVYctj2V7UNTZQxt+Trn7ouDNT4UrM7iyD/NkPegH0D6f6jNJm/9gQy4+9QBugxQmu7+5zoPlTGHAnoZIo2RK3fElQqeyiGQJtECr9qey9UmoSyBlz6gpUWJ0s8/P2suOgSXfD5xSUzRNttdqq0VcKgTxLoIAkb8blGR+vDttRSSMZtitWqNHVbfZ2De3HNkxWiMjOiUHkta2xtljrbRv6EeTtWH4XdXDbKKcY2s8NWdUzAH6lEKw+RZK+Uu+lHgLvGqqIS5wHV4WrBZJWF8ODOS+1OJownszti6cnmkVaM13TItk2AhrlIRLOufnrjDCNzAFsxWJ+KYynem8UFus= testuser
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_3072_testpass b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_3072_testpass
new file mode 100644
index 0000000000..353a24c206
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_3072_testpass
@@ -0,0 +1,42 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,040847DD0487D72145EB88CB09486EB0
+
+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
+-----END RSA PRIVATE KEY-----
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_3072_testpass.pub b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_3072_testpass.pub
new file mode 100644
index 0000000000..686d3b06b1
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_3072_testpass.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDUzzht4+crpxH0SL8fRLfpCF19SXSpQhlesc29L2L+elNl03WYLNbF40ebRglBamf0Co9kYb908a3cJAQvnZMpdrBj/SSz7inQkn3brSipUEUmtcTmVq1VAJ0hnUZHaIkveRktcddKRRHKAQv1oF84RRKYLhKQ1jQs4a7AxnZPJeIVYctj2V7UNTZQxt+Trn7ouDNT4UrM7iyD/NkPegH0D6f6jNJm/9gQy4+9QBugxQmu7+5zoPlTGHAnoZIo2RK3fElQqeyiGQJtECr9qey9UmoSyBlz6gpUWJ0s8/P2suOgSXfD5xSUzRNttdqq0VcKgTxLoIAkb8blGR+vDttRSSMZtitWqNHVbfZ2De3HNkxWiMjOiUHkta2xtljrbRv6EeTtWH4XdXDbKKcY2s8NWdUzAH6lEKw+RZK+Uu+lHgLvGqqIS5wHV4WrBZJWF8ODOS+1OJownszti6cnmkVaM13TItk2AhrlIRLOufnrjDCNzAFsxWJ+KYynem8UFus= testuser
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_4096 b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_4096
new file mode 100644
index 0000000000..1a10b388e6
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_4096
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+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
+-----END RSA PRIVATE KEY-----
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_4096.pub b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_4096.pub
new file mode 100644
index 0000000000..3c3c16feeb
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_4096.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDDNtJeBHx0z8RTfpPaUApShGWiMqyk+EpV8O3s3emsYBzYvoA/TLcbUcsuAo8rb1LQLJ1yrKXr3hJP6672pjMMtCUVAdvEgbvo86YdeP3ZsXjuUlRE3GLvyGgQOdla0MbSuxQIEPUjjP61eNZXzWm/cGpWDmKVHq6o2C/dHNePaMvpD7fPBfF4zDuMndO66SF/nSGXFuUfhsEg4u5nJvi3xHgTJeasA+6kdpRlKLBvFoOtX6yB27/sbx2fIHR1UvcBQ1QSntauHY97CeOBRw1BCbIm4H3zAQ/f4atOyS2LGMgSYJ17+B8OyXknEHPNtQW2VDwlU6ef0kJDZTftxGCCxbfKiMXEYJT5slpfPTNKA+Z9H+tPuheAMpHvolnZVJMa4AWs9x1HISs+Dg8LoW1bSY3GfZLpErbyzrGlMPLAQO7wROGUohcac31cNfbqBjDnpmWYBolDopA/8XQCR/ydEBHOQ8m0hrbWIGtQdFcsXtgqcHAvIJSBMDdZIOA10/0Zrv7okLmAY9bkoYgqgrtJlj0vE2hXrqKCWnScYQzbtlTWtrCWXBwkDORtJpWIP+++siK7PTizj7kr6sCF7wJThRMFZQmBS+1NJXt39IF8UuxAkj9bXWf35IIhsELH2c437GQyQxBXKsw9agP6hhHH/BcYg7aqSQ956AbJvygpiw== testuser
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_4096_testpass b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_4096_testpass
new file mode 100644
index 0000000000..96e29fc15c
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_4096_testpass
@@ -0,0 +1,54 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,1EFAFB79DD5E78C98C5A2204D6747AF8
+
+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
+-----END RSA PRIVATE KEY-----
diff --git a/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_4096_testpass.pub b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_4096_testpass.pub
new file mode 100644
index 0000000000..3c3c16feeb
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/resources/org/eclipse/jgit/junit/ssh/id_rsa_4096_testpass.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDDNtJeBHx0z8RTfpPaUApShGWiMqyk+EpV8O3s3emsYBzYvoA/TLcbUcsuAo8rb1LQLJ1yrKXr3hJP6672pjMMtCUVAdvEgbvo86YdeP3ZsXjuUlRE3GLvyGgQOdla0MbSuxQIEPUjjP61eNZXzWm/cGpWDmKVHq6o2C/dHNePaMvpD7fPBfF4zDuMndO66SF/nSGXFuUfhsEg4u5nJvi3xHgTJeasA+6kdpRlKLBvFoOtX6yB27/sbx2fIHR1UvcBQ1QSntauHY97CeOBRw1BCbIm4H3zAQ/f4atOyS2LGMgSYJ17+B8OyXknEHPNtQW2VDwlU6ef0kJDZTftxGCCxbfKiMXEYJT5slpfPTNKA+Z9H+tPuheAMpHvolnZVJMa4AWs9x1HISs+Dg8LoW1bSY3GfZLpErbyzrGlMPLAQO7wROGUohcac31cNfbqBjDnpmWYBolDopA/8XQCR/ydEBHOQ8m0hrbWIGtQdFcsXtgqcHAvIJSBMDdZIOA10/0Zrv7okLmAY9bkoYgqgrtJlj0vE2hXrqKCWnScYQzbtlTWtrCWXBwkDORtJpWIP+++siK7PTizj7kr6sCF7wJThRMFZQmBS+1NJXt39IF8UuxAkj9bXWf35IIhsELH2c437GQyQxBXKsw9agP6hhHH/BcYg7aqSQ956AbJvygpiw== testuser
diff --git a/org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshTestBase.java b/org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshTestBase.java
new file mode 100644
index 0000000000..2d284cf1d5
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshTestBase.java
@@ -0,0 +1,813 @@
+/*
+ * Copyright (C) 2018, 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.junit.ssh;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.List;
+import java.util.Locale;
+
+import org.eclipse.jgit.api.errors.TransportException;
+import org.eclipse.jgit.transport.CredentialItem;
+import org.junit.Test;
+import org.junit.experimental.theories.DataPoints;
+import org.junit.experimental.theories.Theory;
+
+/**
+ * The ssh tests. Concrete subclasses can re-use these tests by implementing the
+ * abstract operations from {@link SshTestHarness}. This gives a way to test
+ * different ssh clients against a unified test suite.
+ */
+public abstract class SshTestBase extends SshTestHarness {
+
+ @DataPoints
+ public static String[] KEY_RESOURCES = { //
+ "id_dsa", //
+ "id_rsa_1024", //
+ "id_rsa_2048", //
+ "id_rsa_3072", //
+ "id_rsa_4096", //
+ "id_ecdsa_256", //
+ "id_ecdsa_384", //
+ "id_ecdsa_521", //
+ "id_ed25519", //
+ // And now encrypted. Passphrase is "testpass".
+ "id_dsa_testpass", //
+ "id_rsa_1024_testpass", //
+ "id_rsa_2048_testpass", //
+ "id_rsa_3072_testpass", //
+ "id_rsa_4096_testpass", //
+ "id_ecdsa_256_testpass", //
+ "id_ecdsa_384_testpass", //
+ "id_ecdsa_521_testpass", //
+ "id_ed25519_testpass", //
+ "id_ed25519_expensive_testpass" };
+
+ protected File defaultCloneDir;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ defaultCloneDir = new File(getTemporaryDirectory(), "cloned");
+ }
+
+ @Test(expected = TransportException.class)
+ public void testSshWithoutConfig() throws Exception {
+ cloneWith("ssh://" + TEST_USER + "@localhost:" + testPort
+ + "/doesntmatter", defaultCloneDir, null);
+ }
+
+ @Test
+ public void testSshWithGlobalIdentity() throws Exception {
+ cloneWith(
+ "ssh://" + TEST_USER + "@localhost:" + testPort
+ + "/doesntmatter",
+ defaultCloneDir, null,
+ "IdentityFile " + privateKey1.getAbsolutePath());
+ }
+
+ @Test
+ public void testSshWithDefaultIdentity() throws Exception {
+ File idRsa = new File(privateKey1.getParentFile(), "id_rsa");
+ Files.copy(privateKey1.toPath(), idRsa.toPath());
+ // We expect the session factory to pick up these keys...
+ cloneWith("ssh://" + TEST_USER + "@localhost:" + testPort
+ + "/doesntmatter", defaultCloneDir, null);
+ }
+
+ @Test
+ public void testSshWithConfig() throws Exception {
+ cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, null, //
+ "Host localhost", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + privateKey1.getAbsolutePath());
+ }
+
+ @Test
+ public void testSshWithConfigEncryptedUnusedKey() throws Exception {
+ // Copy the encrypted test key from the bundle.
+ File encryptedKey = new File(sshDir, "id_dsa");
+ copyTestResource("id_dsa_testpass", encryptedKey);
+ TestCredentialsProvider provider = new TestCredentialsProvider(
+ "testpass");
+ cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, provider, //
+ "Host localhost", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + privateKey1.getAbsolutePath());
+ assertEquals("CredentialsProvider should not have been called", 0,
+ provider.getLog().size());
+ }
+
+ @Test
+ public void testSshWithConfigEncryptedUnusedKeyInConfigLast()
+ throws Exception {
+ // Copy the encrypted test key from the bundle.
+ File encryptedKey = new File(sshDir, "id_dsa_test_key");
+ copyTestResource("id_dsa_testpass", encryptedKey);
+ TestCredentialsProvider provider = new TestCredentialsProvider(
+ "testpass");
+ cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, provider, //
+ "Host localhost", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + privateKey1.getAbsolutePath(),
+ "IdentityFile " + encryptedKey.getAbsolutePath());
+ // This test passes with JSch per chance because JSch completely ignores
+ // the second IdentityFile
+ assertEquals("CredentialsProvider should not have been called", 0,
+ provider.getLog().size());
+ }
+
+ private boolean isJsch() {
+ return getSessionFactory().getType().equals("jsch");
+ }
+
+ @Test
+ public void testSshWithConfigEncryptedUnusedKeyInConfigFirst()
+ throws Exception {
+ // Test cannot pass with JSch; it handles only one IdentityFile.
+ // assumeTrue(!(getSessionFactory() instanceof
+ // JschConfigSessionFactory)); gives in bazel a failure with "Never
+ // found parameters that satisfied method assumptions."
+ // In maven it's fine!?
+ if (isJsch()) {
+ return;
+ }
+ // Copy the encrypted test key from the bundle.
+ File encryptedKey = new File(sshDir, "id_dsa_test_key");
+ copyTestResource("id_dsa_testpass", encryptedKey);
+ TestCredentialsProvider provider = new TestCredentialsProvider(
+ "testpass");
+ cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, provider, //
+ "Host localhost", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + encryptedKey.getAbsolutePath(),
+ "IdentityFile " + privateKey1.getAbsolutePath());
+ assertEquals("CredentialsProvider should have been called once", 1,
+ provider.getLog().size());
+ }
+
+ @Test
+ public void testSshEncryptedUsedKeyCached() throws Exception {
+ // Make sure we are asked for the password only once if we do several
+ // operations with an encrypted key.
+ File encryptedKey = new File(sshDir, "id_dsa_test_key");
+ copyTestResource("id_dsa_testpass", encryptedKey);
+ File encryptedPublicKey = new File(sshDir, "id_dsa_test_key.pub");
+ copyTestResource("id_dsa_testpass.pub", encryptedPublicKey);
+ server.setTestUserPublicKey(encryptedPublicKey.toPath());
+ TestCredentialsProvider provider = new TestCredentialsProvider(
+ "testpass");
+ pushTo(provider,
+ cloneWith("ssh://localhost/doesntmatter", //
+ defaultCloneDir, provider, //
+ "Host localhost", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + encryptedKey.getAbsolutePath()));
+ assertEquals("CredentialsProvider should have been called once", 1,
+ provider.getLog().size());
+ }
+
+ @Test(expected = TransportException.class)
+ public void testSshEncryptedUsedKeyWrongPassword() throws Exception {
+ File encryptedKey = new File(sshDir, "id_dsa_test_key");
+ copyTestResource("id_dsa_testpass", encryptedKey);
+ File encryptedPublicKey = new File(sshDir, "id_dsa_test_key.pub");
+ copyTestResource("id_dsa_testpass.pub", encryptedPublicKey);
+ server.setTestUserPublicKey(encryptedPublicKey.toPath());
+ TestCredentialsProvider provider = new TestCredentialsProvider(
+ "wrongpass");
+ cloneWith("ssh://localhost/doesntmatter", //
+ defaultCloneDir, provider, //
+ "Host localhost", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "NumberOfPasswordPrompts 1", //
+ "IdentityFile " + encryptedKey.getAbsolutePath());
+ }
+
+ @Test
+ public void testSshEncryptedUsedKeySeveralPassword() throws Exception {
+ File encryptedKey = new File(sshDir, "id_dsa_test_key");
+ copyTestResource("id_dsa_testpass", encryptedKey);
+ File encryptedPublicKey = new File(sshDir, "id_dsa_test_key.pub");
+ copyTestResource("id_dsa_testpass.pub", encryptedPublicKey);
+ server.setTestUserPublicKey(encryptedPublicKey.toPath());
+ TestCredentialsProvider provider = new TestCredentialsProvider(
+ "wrongpass", "wrongpass2", "testpass");
+ cloneWith("ssh://localhost/doesntmatter", //
+ defaultCloneDir, provider, //
+ "Host localhost", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + encryptedKey.getAbsolutePath());
+ assertEquals("CredentialsProvider should have been called 3 times", 3,
+ provider.getLog().size());
+ }
+
+ @Test(expected = TransportException.class)
+ public void testSshWithoutKnownHosts() throws Exception {
+ assertTrue("Could not delete known_hosts", knownHosts.delete());
+ cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, null, //
+ "Host localhost", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + privateKey1.getAbsolutePath());
+ }
+
+ @Test
+ public void testSshWithoutKnownHostsWithProviderAsk()
+ throws Exception {
+ File copiedHosts = new File(knownHosts.getParentFile(),
+ "copiedKnownHosts");
+ assertTrue("Failed to rename known_hosts",
+ knownHosts.renameTo(copiedHosts));
+ // The provider will answer "yes" to all questions, so we should be able
+ // to connect and end up with a new known_hosts file with the host key.
+ TestCredentialsProvider provider = new TestCredentialsProvider();
+ cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, provider, //
+ "Host localhost", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + privateKey1.getAbsolutePath());
+ List<LogEntry> messages = provider.getLog();
+ assertFalse("Expected user interaction", messages.isEmpty());
+ if (isJsch()) {
+ // JSch doesn't create a non-existing file.
+ assertEquals("Expected to be asked about the key", 1,
+ messages.size());
+ return;
+ }
+ assertEquals(
+ "Expected to be asked about the key, and the file creation",
+ 2, messages.size());
+ assertTrue("~/.ssh/known_hosts should exist now", knownHosts.exists());
+ // Instead of checking the file contents, let's just clone again
+ // without provider. If it works, the server host key was written
+ // correctly.
+ File clonedAgain = new File(getTemporaryDirectory(), "cloned2");
+ cloneWith("ssh://localhost/doesntmatter", clonedAgain, null, //
+ "Host localhost", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + privateKey1.getAbsolutePath());
+ }
+
+ @Test
+ public void testSshWithoutKnownHostsWithProviderAcceptNew()
+ throws Exception {
+ File copiedHosts = new File(knownHosts.getParentFile(),
+ "copiedKnownHosts");
+ assertTrue("Failed to rename known_hosts",
+ knownHosts.renameTo(copiedHosts));
+ TestCredentialsProvider provider = new TestCredentialsProvider();
+ cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, provider, //
+ "Host localhost", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "StrictHostKeyChecking accept-new", //
+ "IdentityFile " + privateKey1.getAbsolutePath());
+ if (isJsch()) {
+ // JSch doesn't create new files.
+ assertTrue("CredentialsProvider not called",
+ provider.getLog().isEmpty());
+ return;
+ }
+ assertEquals("Expected to be asked about the file creation", 1,
+ provider.getLog().size());
+ assertTrue("~/.ssh/known_hosts should exist now", knownHosts.exists());
+ // Instead of checking the file contents, let's just clone again
+ // without provider. If it works, the server host key was written
+ // correctly.
+ File clonedAgain = new File(getTemporaryDirectory(), "cloned2");
+ cloneWith("ssh://localhost/doesntmatter", clonedAgain, null, //
+ "Host localhost", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + privateKey1.getAbsolutePath());
+ }
+
+ @Test(expected = TransportException.class)
+ public void testSshWithoutKnownHostsDeny() throws Exception {
+ File copiedHosts = new File(knownHosts.getParentFile(),
+ "copiedKnownHosts");
+ assertTrue("Failed to rename known_hosts",
+ knownHosts.renameTo(copiedHosts));
+ cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, null, //
+ "Host localhost", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "StrictHostKeyChecking yes", //
+ "IdentityFile " + privateKey1.getAbsolutePath());
+ }
+
+ @Test(expected = TransportException.class)
+ public void testSshModifiedHostKeyDeny()
+ throws Exception {
+ File copiedHosts = new File(knownHosts.getParentFile(),
+ "copiedKnownHosts");
+ assertTrue("Failed to rename known_hosts",
+ knownHosts.renameTo(copiedHosts));
+ // Now produce a new known_hosts file containing some other key.
+ createKnownHostsFile(knownHosts, "localhost", testPort, publicKey1);
+ cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, null, //
+ "Host localhost", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "StrictHostKeyChecking yes", //
+ "IdentityFile " + privateKey1.getAbsolutePath());
+ }
+
+ @Test(expected = TransportException.class)
+ public void testSshModifiedHostKeyWithProviderDeny() throws Exception {
+ File copiedHosts = new File(knownHosts.getParentFile(),
+ "copiedKnownHosts");
+ assertTrue("Failed to rename known_hosts",
+ knownHosts.renameTo(copiedHosts));
+ // Now produce a new known_hosts file containing some other key.
+ createKnownHostsFile(knownHosts, "localhost", testPort, publicKey1);
+ TestCredentialsProvider provider = new TestCredentialsProvider();
+ try {
+ cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, provider, //
+ "Host localhost", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "StrictHostKeyChecking yes", //
+ "IdentityFile " + privateKey1.getAbsolutePath());
+ } catch (Exception e) {
+ assertEquals("Expected to be told about the modified key", 1,
+ provider.getLog().size());
+ assertTrue("Only messages expected", provider.getLog().stream()
+ .flatMap(l -> l.getItems().stream()).allMatch(
+ c -> c instanceof CredentialItem.InformationalMessage));
+ throw e;
+ }
+ }
+
+ private void checkKnownHostsModifiedHostKey(File backup, File newFile,
+ String wrongKey) throws IOException {
+ List<String> oldLines = Files.readAllLines(backup.toPath(), UTF_8);
+ // Find the original entry. We should have that again in known_hosts.
+ String oldKeyPart = null;
+ for (String oldLine : oldLines) {
+ if (oldLine.contains("[localhost]:")) {
+ String[] parts = oldLine.split("\\s+");
+ if (parts.length > 2) {
+ oldKeyPart = parts[parts.length - 2] + ' '
+ + parts[parts.length - 1];
+ break;
+ }
+ }
+ }
+ assertNotNull("Old key not found", oldKeyPart);
+ List<String> newLines = Files.readAllLines(newFile.toPath(), UTF_8);
+ assertFalse("Old host key still found in known_hosts file" + newFile,
+ hasHostKey("localhost", testPort, wrongKey, newLines));
+ assertTrue("New host key not found in known_hosts file" + newFile,
+ hasHostKey("localhost", testPort, oldKeyPart, newLines));
+
+ }
+
+ @Test
+ public void testSshModifiedHostKeyAllow() throws Exception {
+ assertTrue("Failed to delete known_hosts", knownHosts.delete());
+ createKnownHostsFile(knownHosts, "localhost", testPort, publicKey1);
+ File backup = new File(getTemporaryDirectory(), "backupKnownHosts");
+ Files.copy(knownHosts.toPath(), backup.toPath());
+ cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, null, //
+ "Host localhost", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "StrictHostKeyChecking no", //
+ "IdentityFile " + privateKey1.getAbsolutePath());
+ // File should not have been updated!
+ String[] oldLines = Files
+ .readAllLines(backup.toPath(), UTF_8)
+ .toArray(new String[0]);
+ String[] newLines = Files
+ .readAllLines(knownHosts.toPath(), UTF_8)
+ .toArray(new String[0]);
+ assertArrayEquals("Known hosts file should not be modified", oldLines,
+ newLines);
+ }
+
+ @Test
+ public void testSshModifiedHostKeyAsk() throws Exception {
+ File copiedHosts = new File(knownHosts.getParentFile(),
+ "copiedKnownHosts");
+ assertTrue("Failed to rename known_hosts",
+ knownHosts.renameTo(copiedHosts));
+ String wrongKeyPart = createKnownHostsFile(knownHosts, "localhost",
+ testPort, publicKey1);
+ TestCredentialsProvider provider = new TestCredentialsProvider();
+ cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, provider, //
+ "Host localhost", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + privateKey1.getAbsolutePath());
+ checkKnownHostsModifiedHostKey(copiedHosts, knownHosts, wrongKeyPart);
+ assertEquals("Expected to be asked about the modified key", 1,
+ provider.getLog().size());
+ }
+
+ @Test
+ public void testSshCloneWithConfigAndPush() throws Exception {
+ pushTo(cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, null, //
+ "Host localhost", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + privateKey1.getAbsolutePath()));
+ }
+
+ @Test
+ public void testSftpWithConfig() throws Exception {
+ cloneWith("sftp://localhost/.git", defaultCloneDir, null, //
+ "Host localhost", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + privateKey1.getAbsolutePath());
+ }
+
+ @Test
+ public void testSftpCloneWithConfigAndPush() throws Exception {
+ pushTo(cloneWith("sftp://localhost/.git", defaultCloneDir, null, //
+ "Host localhost", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + privateKey1.getAbsolutePath()));
+ }
+
+ @Test(expected = TransportException.class)
+ public void testSshWithConfigWrongKey() throws Exception {
+ cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, null, //
+ "Host localhost", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + privateKey2.getAbsolutePath());
+ }
+
+ @Test
+ public void testSshWithWrongUserNameInConfig() throws Exception {
+ // Bug 526778
+ cloneWith(
+ "ssh://" + TEST_USER + "@localhost:" + testPort
+ + "/doesntmatter",
+ defaultCloneDir, null, //
+ "Host localhost", //
+ "HostName localhost", //
+ "User sombody_else", //
+ "IdentityFile " + privateKey1.getAbsolutePath());
+ }
+
+ @Test
+ public void testSshWithWrongPortInConfig() throws Exception {
+ // Bug 526778
+ cloneWith(
+ "ssh://" + TEST_USER + "@localhost:" + testPort
+ + "/doesntmatter",
+ defaultCloneDir, null, //
+ "Host localhost", //
+ "HostName localhost", //
+ "Port 22", //
+ "User " + TEST_USER, //
+ "IdentityFile " + privateKey1.getAbsolutePath());
+ }
+
+ @Test
+ public void testSshWithAliasInConfig() throws Exception {
+ // Bug 531118
+ cloneWith("ssh://git/doesntmatter", defaultCloneDir, null, //
+ "Host git", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + privateKey1.getAbsolutePath(), "", //
+ "Host localhost", //
+ "HostName localhost", //
+ "Port 22", //
+ "User someone_else", //
+ "IdentityFile " + privateKey2.getAbsolutePath());
+ }
+
+ @Test
+ public void testSshWithUnknownCiphersInConfig() throws Exception {
+ // Bug 535672
+ cloneWith("ssh://git/doesntmatter", defaultCloneDir, null, //
+ "Host git", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + privateKey1.getAbsolutePath(), //
+ "Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr");
+ }
+
+ @Test
+ public void testSshWithUnknownHostKeyAlgorithmsInConfig()
+ throws Exception {
+ // Bug 535672
+ cloneWith("ssh://git/doesntmatter", defaultCloneDir, null, //
+ "Host git", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + privateKey1.getAbsolutePath(), //
+ "HostKeyAlgorithms foobar,ssh-rsa,ssh-dss");
+ }
+
+ @Test
+ public void testSshWithUnknownKexAlgorithmsInConfig()
+ throws Exception {
+ // Bug 535672
+ cloneWith("ssh://git/doesntmatter", defaultCloneDir, null, //
+ "Host git", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + privateKey1.getAbsolutePath(), //
+ "KexAlgorithms foobar,diffie-hellman-group14-sha1,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521");
+ }
+
+ @Test
+ public void testSshWithMinimalHostKeyAlgorithmsInConfig()
+ throws Exception {
+ // Bug 537790
+ cloneWith("ssh://git/doesntmatter", defaultCloneDir, null, //
+ "Host git", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + privateKey1.getAbsolutePath(), //
+ "HostKeyAlgorithms ssh-rsa,ssh-dss");
+ }
+
+ @Test
+ public void testSshWithUnknownAuthInConfig() throws Exception {
+ cloneWith("ssh://git/doesntmatter", defaultCloneDir, null, //
+ "Host git", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + privateKey1.getAbsolutePath(), //
+ "PreferredAuthentications gssapi-with-mic,hostbased,publickey,keyboard-interactive,password");
+ }
+
+ @Test(expected = TransportException.class)
+ public void testSshWithNoMatchingAuthInConfig() throws Exception {
+ // Server doesn't do password, and anyway we set no password.
+ cloneWith("ssh://git/doesntmatter", defaultCloneDir, null, //
+ "Host git", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + privateKey1.getAbsolutePath(), //
+ "PreferredAuthentications password");
+ }
+
+ @Test
+ public void testRsaHostKeySecond() throws Exception {
+ // See https://git.eclipse.org/r/#/c/130402/ : server has EcDSA
+ // (preferred), RSA, we have RSA in known_hosts: client and server
+ // should agree on RSA.
+ File newHostKey = new File(getTemporaryDirectory(), "newhostkey");
+ copyTestResource("id_ecdsa_256", newHostKey);
+ server.addHostKey(newHostKey.toPath(), true);
+ cloneWith("ssh://git/doesntmatter", defaultCloneDir, null, //
+ "Host git", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + privateKey1.getAbsolutePath());
+ }
+
+ @Test
+ public void testEcDsaHostKey() throws Exception {
+ // See https://git.eclipse.org/r/#/c/130402/ : server has RSA
+ // (preferred), EcDSA, we have EcDSA in known_hosts: client and server
+ // should agree on EcDSA.
+ File newHostKey = new File(getTemporaryDirectory(), "newhostkey");
+ copyTestResource("id_ecdsa_256", newHostKey);
+ server.addHostKey(newHostKey.toPath(), false);
+ File newHostKeyPub = new File(getTemporaryDirectory(),
+ "newhostkey.pub");
+ copyTestResource("id_ecdsa_256.pub", newHostKeyPub);
+ createKnownHostsFile(knownHosts, "localhost", testPort, newHostKeyPub);
+ cloneWith("ssh://git/doesntmatter", defaultCloneDir, null, //
+ "Host git", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + privateKey1.getAbsolutePath());
+ }
+
+ @Test
+ public void testPasswordAuth() throws Exception {
+ server.enablePasswordAuthentication();
+ TestCredentialsProvider provider = new TestCredentialsProvider(
+ TEST_USER.toUpperCase(Locale.ROOT));
+ cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
+ "Host git", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "PreferredAuthentications password");
+ }
+
+ @Test
+ public void testPasswordAuthSeveralTimes() throws Exception {
+ server.enablePasswordAuthentication();
+ TestCredentialsProvider provider = new TestCredentialsProvider(
+ "wrongpass", "wrongpass", TEST_USER.toUpperCase(Locale.ROOT));
+ cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
+ "Host git", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "PreferredAuthentications password");
+ }
+
+ @Test(expected = TransportException.class)
+ public void testPasswordAuthWrongPassword() throws Exception {
+ server.enablePasswordAuthentication();
+ TestCredentialsProvider provider = new TestCredentialsProvider(
+ "wrongpass");
+ cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
+ "Host git", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "PreferredAuthentications password");
+ }
+
+ @Test(expected = TransportException.class)
+ public void testPasswordAuthNoPassword() throws Exception {
+ server.enablePasswordAuthentication();
+ TestCredentialsProvider provider = new TestCredentialsProvider();
+ cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
+ "Host git", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "PreferredAuthentications password");
+ }
+
+ @Test(expected = TransportException.class)
+ public void testPasswordAuthCorrectPasswordTooLate() throws Exception {
+ server.enablePasswordAuthentication();
+ TestCredentialsProvider provider = new TestCredentialsProvider(
+ "wrongpass", "wrongpass", "wrongpass",
+ TEST_USER.toUpperCase(Locale.ROOT));
+ cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
+ "Host git", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "PreferredAuthentications password");
+ }
+
+ @Test
+ public void testKeyboardInteractiveAuth() throws Exception {
+ server.enableKeyboardInteractiveAuthentication();
+ TestCredentialsProvider provider = new TestCredentialsProvider(
+ TEST_USER.toUpperCase(Locale.ROOT));
+ cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
+ "Host git", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "PreferredAuthentications keyboard-interactive");
+ }
+
+ @Test
+ public void testKeyboardInteractiveAuthSeveralTimes() throws Exception {
+ server.enableKeyboardInteractiveAuthentication();
+ TestCredentialsProvider provider = new TestCredentialsProvider(
+ "wrongpass", "wrongpass", TEST_USER.toUpperCase(Locale.ROOT));
+ cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
+ "Host git", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "PreferredAuthentications keyboard-interactive");
+ }
+
+ @Test(expected = TransportException.class)
+ public void testKeyboardInteractiveAuthWrongPassword() throws Exception {
+ server.enableKeyboardInteractiveAuthentication();
+ TestCredentialsProvider provider = new TestCredentialsProvider(
+ "wrongpass");
+ cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
+ "Host git", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "PreferredAuthentications keyboard-interactive");
+ }
+
+ @Test(expected = TransportException.class)
+ public void testKeyboardInteractiveAuthNoPassword() throws Exception {
+ server.enableKeyboardInteractiveAuthentication();
+ TestCredentialsProvider provider = new TestCredentialsProvider();
+ cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
+ "Host git", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "PreferredAuthentications keyboard-interactive");
+ }
+
+ @Test(expected = TransportException.class)
+ public void testKeyboardInteractiveAuthCorrectPasswordTooLate()
+ throws Exception {
+ server.enableKeyboardInteractiveAuthentication();
+ TestCredentialsProvider provider = new TestCredentialsProvider(
+ "wrongpass", "wrongpass", "wrongpass",
+ TEST_USER.toUpperCase(Locale.ROOT));
+ cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
+ "Host git", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "PreferredAuthentications keyboard-interactive");
+ }
+
+ @Theory
+ public void testSshKeys(String keyName) throws Exception {
+ // JSch fails on ECDSA 384/521 keys. Compare
+ // https://sourceforge.net/p/jsch/patches/10/
+ assumeTrue(!(isJsch() && (keyName.contains("ed25519")
+ || keyName.startsWith("id_ecdsa_384")
+ || keyName.startsWith("id_ecdsa_521"))));
+ File cloned = new File(getTemporaryDirectory(), "cloned");
+ String keyFileName = keyName + "_key";
+ File privateKey = new File(sshDir, keyFileName);
+ copyTestResource(keyName, privateKey);
+ File publicKey = new File(sshDir, keyFileName + ".pub");
+ copyTestResource(keyName + ".pub", publicKey);
+ server.setTestUserPublicKey(publicKey.toPath());
+ TestCredentialsProvider provider = new TestCredentialsProvider(
+ "testpass");
+ pushTo(provider,
+ cloneWith("ssh://localhost/doesntmatter", //
+ cloned, provider, //
+ "Host localhost", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + privateKey.getAbsolutePath()));
+ int expectedCalls = keyName.endsWith("testpass") ? 1 : 0;
+ assertEquals("Unexpected calls to CredentialsProvider", expectedCalls,
+ provider.getLog().size());
+ // Should now also work without credentials provider, even if the key
+ // was encrypted.
+ cloned = new File(getTemporaryDirectory(), "cloned2");
+ pushTo(null,
+ cloneWith("ssh://localhost/doesntmatter", //
+ cloned, null, //
+ "Host localhost", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + privateKey.getAbsolutePath()));
+ }
+}
diff --git a/org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshTestGitServer.java b/org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshTestGitServer.java
index 883ff0b8b5..03e2855829 100644
--- a/org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshTestGitServer.java
+++ b/org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshTestGitServer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> and others
+ * Copyright (C) 2018, 2020 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
@@ -252,11 +252,24 @@ public class SshTestGitServer {
.loadKeyPairIdentities(null,
NamedResource.ofName(key.toString()), in, null)
.iterator().next();
- if (inFront) {
- hostKeys.add(0, pair);
- } else {
- hostKeys.add(pair);
- }
+ addHostKey(pair, inFront);
+ }
+ }
+
+ /**
+ * Adds an additional host key to the server.
+ *
+ * @param key
+ * {@link KeyPair} to add
+ * @param inFront
+ * whether to add the new key before other existing keys
+ * @since 5.8
+ */
+ public void addHostKey(@NonNull KeyPair key, boolean inFront) {
+ if (inFront) {
+ hostKeys.add(0, key);
+ } else {
+ hostKeys.add(key);
}
}
@@ -323,6 +336,18 @@ public class SshTestGitServer {
}
/**
+ * Sets the test user's public key on the server.
+ *
+ * @param key
+ * to set
+ *
+ * @since 5.8
+ */
+ public void setTestUserPublicKey(@NonNull PublicKey key) {
+ this.testKey = key;
+ }
+
+ /**
* Sets the lines the server sends before its server identification in the
* initial protocol version exchange.
*
diff --git a/org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshTestHarness.java b/org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshTestHarness.java
new file mode 100644
index 0000000000..43f9dc4b24
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshTestHarness.java
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2018, 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.junit.ssh;
+
+import static java.nio.charset.StandardCharsets.US_ASCII;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jgit.api.CloneCommand;
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.PushCommand;
+import org.eclipse.jgit.api.ResetCommand.ResetType;
+import org.eclipse.jgit.errors.UnsupportedCredentialItem;
+import org.eclipse.jgit.junit.RepositoryTestCase;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.transport.CredentialItem;
+import org.eclipse.jgit.transport.CredentialsProvider;
+import org.eclipse.jgit.transport.PushResult;
+import org.eclipse.jgit.transport.RemoteRefUpdate;
+import org.eclipse.jgit.transport.SshSessionFactory;
+import org.eclipse.jgit.transport.URIish;
+import org.eclipse.jgit.util.FS;
+import org.junit.After;
+
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.KeyPair;
+
+/**
+ * Root class for ssh tests. Sets up the ssh test server. A set of pre-computed
+ * keys for testing is provided in the bundle and can be used in test cases via
+ * {@link #copyTestResource(String, File)}. These test key files names have four
+ * components, separated by a single underscore: "id", the algorithm, the bits
+ * (if variable), and the password if the private key is encrypted. For instance
+ * "{@code id_ecdsa_384_testpass}" is an encrypted ECDSA-384 key. The passphrase
+ * to decrypt is "testpass". The key "{@code id_ecdsa_384}" is the same but
+ * unencrypted. All keys were generated and encrypted via ssh-keygen. Note that
+ * DSA and ec25519 have no "bits" component. Available keys are listed in
+ * {@link SshTestBase#KEY_RESOURCES}.
+ */
+public abstract class SshTestHarness extends RepositoryTestCase {
+
+ protected static final String TEST_USER = "testuser";
+
+ protected File sshDir;
+
+ protected File privateKey1;
+
+ protected File privateKey2;
+
+ protected File publicKey1;
+
+ protected SshTestGitServer server;
+
+ private SshSessionFactory factory;
+
+ protected int testPort;
+
+ protected File knownHosts;
+
+ private File homeDir;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ writeTrashFile("file.txt", "something");
+ try (Git git = new Git(db)) {
+ git.add().addFilepattern("file.txt").call();
+ git.commit().setMessage("Initial commit").call();
+ }
+ mockSystemReader.setProperty("user.home",
+ getTemporaryDirectory().getAbsolutePath());
+ mockSystemReader.setProperty("HOME",
+ getTemporaryDirectory().getAbsolutePath());
+ homeDir = FS.DETECTED.userHome();
+ FS.DETECTED.setUserHome(getTemporaryDirectory().getAbsoluteFile());
+ sshDir = new File(getTemporaryDirectory(), ".ssh");
+ assertTrue(sshDir.mkdir());
+ File serverDir = new File(getTemporaryDirectory(), "srv");
+ assertTrue(serverDir.mkdir());
+ // Create two key pairs. Let's not call them "id_rsa".
+ privateKey1 = new File(sshDir, "first_key");
+ privateKey2 = new File(sshDir, "second_key");
+ publicKey1 = createKeyPair(privateKey1);
+ createKeyPair(privateKey2);
+ ByteArrayOutputStream publicHostKey = new ByteArrayOutputStream();
+ // Start a server with our test user and the first key.
+ server = new SshTestGitServer(TEST_USER, publicKey1.toPath(), db,
+ createHostKey(publicHostKey));
+ testPort = server.start();
+ assertTrue(testPort > 0);
+ knownHosts = new File(sshDir, "known_hosts");
+ Files.write(knownHosts.toPath(), Collections.singleton("[localhost]:"
+ + testPort + ' '
+ + publicHostKey.toString(US_ASCII.name())));
+ factory = createSessionFactory();
+ SshSessionFactory.setInstance(factory);
+ }
+
+ private static File createKeyPair(File privateKeyFile) throws Exception {
+ // Found no way to do this with MINA sshd except rolling it all
+ // ourselves...
+ JSch jsch = new JSch();
+ KeyPair pair = KeyPair.genKeyPair(jsch, KeyPair.RSA, 2048);
+ try (OutputStream out = new FileOutputStream(privateKeyFile)) {
+ pair.writePrivateKey(out);
+ }
+ File publicKeyFile = new File(privateKeyFile.getParentFile(),
+ privateKeyFile.getName() + ".pub");
+ try (OutputStream out = new FileOutputStream(publicKeyFile)) {
+ pair.writePublicKey(out, TEST_USER);
+ }
+ return publicKeyFile;
+ }
+
+ private static byte[] createHostKey(OutputStream publicKey)
+ throws Exception {
+ JSch jsch = new JSch();
+ KeyPair pair = KeyPair.genKeyPair(jsch, KeyPair.RSA, 2048);
+ pair.writePublicKey(publicKey, "");
+ try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
+ pair.writePrivateKey(out);
+ out.flush();
+ return out.toByteArray();
+ }
+ }
+
+ /**
+ * Creates a new known_hosts file with one entry for the given host and port
+ * taken from the given public key file.
+ *
+ * @param file
+ * to write the known_hosts file to
+ * @param host
+ * for the entry
+ * @param port
+ * for the entry
+ * @param publicKey
+ * to use
+ * @return the public-key part of the line
+ * @throws IOException
+ */
+ protected static String createKnownHostsFile(File file, String host,
+ int port, File publicKey) throws IOException {
+ List<String> lines = Files.readAllLines(publicKey.toPath(), UTF_8);
+ assertEquals("Public key has too many lines", 1, lines.size());
+ String pubKey = lines.get(0);
+ // Strip off the comment.
+ String[] parts = pubKey.split("\\s+");
+ assertTrue("Unexpected key content",
+ parts.length == 2 || parts.length == 3);
+ String keyPart = parts[0] + ' ' + parts[1];
+ String line = '[' + host + "]:" + port + ' ' + keyPart;
+ Files.write(file.toPath(), Collections.singletonList(line));
+ return keyPart;
+ }
+
+ /**
+ * Checks whether there is a line for the given host and port that also
+ * matches the given key part in the list of lines.
+ *
+ * @param host
+ * to look for
+ * @param port
+ * to look for
+ * @param keyPart
+ * to look for
+ * @param lines
+ * to look in
+ * @return {@code true} if found, {@code false} otherwise
+ */
+ protected boolean hasHostKey(String host, int port, String keyPart,
+ List<String> lines) {
+ String h = '[' + host + "]:" + port;
+ return lines.stream()
+ .anyMatch(l -> l.contains(h) && l.contains(keyPart));
+ }
+
+ @After
+ public void shutdownServer() throws Exception {
+ if (server != null) {
+ server.stop();
+ server = null;
+ }
+ FS.DETECTED.setUserHome(homeDir);
+ SshSessionFactory.setInstance(null);
+ factory = null;
+ }
+
+ protected abstract SshSessionFactory createSessionFactory();
+
+ protected SshSessionFactory getSessionFactory() {
+ return factory;
+ }
+
+ protected abstract void installConfig(String... config);
+
+ /**
+ * Copies a test data file contained in the test bundle to the given file.
+ * Equivalent to {@link #copyTestResource(Class, String, File)} with
+ * {@code SshTestHarness.class} as first parameter.
+ *
+ * @param resourceName
+ * of the test resource to copy
+ * @param to
+ * file to copy the resource to
+ * @throws IOException
+ * if the resource cannot be copied
+ */
+ protected void copyTestResource(String resourceName, File to)
+ throws IOException {
+ copyTestResource(SshTestHarness.class, resourceName, to);
+ }
+
+ /**
+ * Copies a test data file contained in the test bundle to the given file,
+ * using {@link Class#getResourceAsStream(String)} to get the test resource.
+ *
+ * @param loader
+ * {@link Class} to use to load the resource
+ * @param resourceName
+ * of the test resource to copy
+ * @param to
+ * file to copy the resource to
+ * @throws IOException
+ * if the resource cannot be copied
+ */
+ protected void copyTestResource(Class<?> loader, String resourceName,
+ File to) throws IOException {
+ try (InputStream in = loader.getResourceAsStream(resourceName)) {
+ Files.copy(in, to.toPath());
+ }
+ }
+
+ protected File cloneWith(String uri, File to, CredentialsProvider provider,
+ String... config) throws Exception {
+ installConfig(config);
+ CloneCommand clone = Git.cloneRepository().setCloneAllBranches(true)
+ .setDirectory(to).setURI(uri);
+ if (provider != null) {
+ clone.setCredentialsProvider(provider);
+ }
+ try (Git git = clone.call()) {
+ Repository repo = git.getRepository();
+ assertNotNull(repo.resolve("master"));
+ assertNotEquals(db.getWorkTree(),
+ git.getRepository().getWorkTree());
+ assertTrue(new File(git.getRepository().getWorkTree(), "file.txt")
+ .exists());
+ return repo.getWorkTree();
+ }
+ }
+
+ protected void pushTo(File localClone) throws Exception {
+ pushTo(null, localClone);
+ }
+
+ protected void pushTo(CredentialsProvider provider, File localClone)
+ throws Exception {
+ RevCommit commit;
+ File newFile = null;
+ try (Git git = Git.open(localClone)) {
+ // Write a new file and modify a file.
+ Repository local = git.getRepository();
+ newFile = File.createTempFile("new", "sshtest",
+ local.getWorkTree());
+ write(newFile, "something new");
+ File existingFile = new File(local.getWorkTree(), "file.txt");
+ write(existingFile, "something else");
+ git.add().addFilepattern("file.txt")
+ .addFilepattern(newFile.getName())
+ .call();
+ commit = git.commit().setMessage("Local commit").call();
+ // Push
+ PushCommand push = git.push().setPushAll();
+ if (provider != null) {
+ push.setCredentialsProvider(provider);
+ }
+ Iterable<PushResult> results = push.call();
+ for (PushResult result : results) {
+ for (RemoteRefUpdate u : result.getRemoteUpdates()) {
+ assertEquals(
+ "Could not update " + u.getRemoteName() + ' '
+ + u.getMessage(),
+ RemoteRefUpdate.Status.OK, u.getStatus());
+ }
+ }
+ }
+ // Now check "master" in the remote repo directly:
+ assertEquals("Unexpected remote commit", commit, db.resolve("master"));
+ assertEquals("Unexpected remote commit", commit,
+ db.resolve(Constants.HEAD));
+ File remoteFile = new File(db.getWorkTree(), newFile.getName());
+ assertFalse("File should not exist on remote", remoteFile.exists());
+ try (Git git = new Git(db)) {
+ git.reset().setMode(ResetType.HARD).setRef(Constants.HEAD).call();
+ }
+ assertTrue("File does not exist on remote", remoteFile.exists());
+ checkFile(remoteFile, "something new");
+ }
+
+ protected static class TestCredentialsProvider extends CredentialsProvider {
+
+ private final List<String> stringStore;
+
+ private final Iterator<String> strings;
+
+ public TestCredentialsProvider(String... strings) {
+ if (strings == null || strings.length == 0) {
+ stringStore = Collections.emptyList();
+ } else {
+ stringStore = Arrays.asList(strings);
+ }
+ this.strings = stringStore.iterator();
+ }
+
+ @Override
+ public boolean isInteractive() {
+ return true;
+ }
+
+ @Override
+ public boolean supports(CredentialItem... items) {
+ return true;
+ }
+
+ @Override
+ public boolean get(URIish uri, CredentialItem... items)
+ throws UnsupportedCredentialItem {
+ System.out.println("URI: " + uri);
+ for (CredentialItem item : items) {
+ System.out.println(item.getClass().getSimpleName() + ' '
+ + item.getPromptText());
+ }
+ logItems(uri, items);
+ for (CredentialItem item : items) {
+ if (item instanceof CredentialItem.InformationalMessage) {
+ continue;
+ }
+ if (item instanceof CredentialItem.YesNoType) {
+ ((CredentialItem.YesNoType) item).setValue(true);
+ } else if (item instanceof CredentialItem.CharArrayType) {
+ if (strings.hasNext()) {
+ ((CredentialItem.CharArrayType) item)
+ .setValue(strings.next().toCharArray());
+ } else {
+ return false;
+ }
+ } else if (item instanceof CredentialItem.StringType) {
+ if (strings.hasNext()) {
+ ((CredentialItem.StringType) item)
+ .setValue(strings.next());
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private List<LogEntry> log = new ArrayList<>();
+
+ private void logItems(URIish uri, CredentialItem... items) {
+ log.add(new LogEntry(uri, Arrays.asList(items)));
+ }
+
+ public List<LogEntry> getLog() {
+ return log;
+ }
+ }
+
+ protected static class LogEntry {
+
+ private URIish uri;
+
+ private List<CredentialItem> items;
+
+ public LogEntry(URIish uri, List<CredentialItem> items) {
+ this.uri = uri;
+ this.items = items;
+ }
+
+ public URIish getURIish() {
+ return uri;
+ }
+
+ public List<CredentialItem> getItems() {
+ return items;
+ }
+ }
+}