diff --git a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/ssh/SshTestGitServer.java b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/ssh/SshTestGitServer.java index 675a11589..8d3207c43 100644 --- a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/ssh/SshTestGitServer.java +++ b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/ssh/SshTestGitServer.java @@ -53,8 +53,9 @@ import java.util.Collections; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import org.apache.sshd.common.config.keys.IdentityUtils; +import org.apache.sshd.common.config.keys.AuthorizedKeyEntry; import org.apache.sshd.common.config.keys.KeyUtils; +import org.apache.sshd.common.config.keys.PublicKeyEntryResolver; import org.apache.sshd.common.file.virtualfs.VirtualFileSystemFactory; import org.apache.sshd.common.keyprovider.KeyPairProvider; import org.apache.sshd.common.session.Session; @@ -65,13 +66,15 @@ import org.apache.sshd.server.shell.UnknownCommand; import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory; import org.eclipse.jgit.annotations.NonNull; import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.transport.ReceivePack; +import org.eclipse.jgit.transport.RemoteConfig; import org.eclipse.jgit.transport.UploadPack; /** * A simple ssh/sftp git test server based on Apache MINA sshd. *

* Supports only a single repository. Authenticates only the given test user - * against his given test public key. ssh is limited to fetching (upload-pack). + * against his given test public key. Supports fetch and push. *

* * @since 5.2 @@ -112,9 +115,7 @@ public class SshTestGitServer { @NonNull Repository repository, @NonNull byte[] hostKey) throws IOException, GeneralSecurityException { this.testUser = testUser; - this.testKey = IdentityUtils - .loadIdentities(Collections.singletonMap("A", testKey), null) - .get("A").getPublic(); + setTestUserPublicKey(testKey); this.repository = repository; server = SshServer.setUpDefaultServer(); // Set host key @@ -156,9 +157,10 @@ public class SshTestGitServer { .compareKeys(SshTestGitServer.this.testKey, publicKey); }); server.setCommandFactory(command -> { - if (command.startsWith("git-upload-pack") - || command.startsWith("git upload-pack")) { + if (command.startsWith(RemoteConfig.DEFAULT_UPLOAD_PACK)) { return new GitUploadPackCommand(command, executorService); + } else if (command.startsWith(RemoteConfig.DEFAULT_RECEIVE_PACK)) { + return new GitReceivePackCommand(command, executorService); } return new UnknownCommand(command); }); @@ -186,6 +188,12 @@ public class SshTestGitServer { server.stop(true); } + public void setTestUserPublicKey(Path key) + throws IOException, GeneralSecurityException { + this.testKey = AuthorizedKeyEntry.readAuthorizedKeys(key).get(0) + .resolvePublicKey(PublicKeyEntryResolver.IGNORING); + } + private class GitUploadPackCommand extends AbstractCommandSupport { protected GitUploadPackCommand(String command, @@ -214,4 +222,27 @@ public class SshTestGitServer { } } + + private class GitReceivePackCommand extends AbstractCommandSupport { + + protected GitReceivePackCommand(String command, + ExecutorService executorService) { + super(command, executorService, false); + } + + @Override + public void run() { + try { + new ReceivePack(repository).receive(getInputStream(), + getOutputStream(), getErrorStream()); + onExit(0); + } catch (IOException e) { + log.warn( + MessageFormat.format("Could not run {0}", getCommand()), + e); + onExit(-1, e.toString()); + } + } + + } } diff --git a/org.eclipse.jgit.test/BUILD b/org.eclipse.jgit.test/BUILD index 0b862c00d..2082e7eac 100644 --- a/org.eclipse.jgit.test/BUILD +++ b/org.eclipse.jgit.test/BUILD @@ -20,7 +20,8 @@ HELPERS = glob(["src/**/*.java"]) + [PKG + c for c in [ "revwalk/RevWalkTestCase.java", "transport/ObjectIdMatcher.java", "transport/SpiTransport.java", - "transport/SshTestBase.java", + "transport/ssh/SshTestBase.java", + "transport/ssh/SshTestHarness.java", "treewalk/FileTreeIteratorWithTimeControl.java", "treewalk/filter/AlwaysCloneTreeFilter.java", "test/resources/SampleDataRepositoryTestCase.java", diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/id_dsa_test b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/id_dsa_test deleted file mode 100644 index cc39e8b87..000000000 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/id_dsa_test +++ /dev/null @@ -1,15 +0,0 @@ ------BEGIN DSA PRIVATE KEY----- -Proc-Type: 4,ENCRYPTED -DEK-Info: AES-128-CBC,D7B8FC3F4E304A2A22754B068767081F - -IewkLt6JyqtPccAsnfeLv7IMlLvgm7tqQSYK1/CLhmDE0aZXViD8sqxLA6dVjmkp -BVyk7EBpp43PnVQYsDcMPnyM8H83vNRDtIQ6fxM1PJafiP7Rbn1k1fDh7DwA48PU -FnT6zZ9aYEKYMto0WIdQ86j/uY+LtYygQDDoZ2ohn2NlpykeyrSp0bDRIoW6sdc5 -+LlfDtq2usv3fcxMAJpO/SSN78LvBlyOK4n/JAVSkPawsW1WsIrXA52mk0iUhjYc -aYOCuL+wA7OmHAOpfS5HUXZ4i/7qONnLBkEqeIOcgTmShh1c4oWw9TjWK1AzdSDU -G2nkRJ/8zK/jdm5wcmrjrzuREM1VbCiXHlVoHYI0W1Z9etOgz1cj4KLz/bB8Nf+8 -shCez1Aw5ec33BzwysfwymfAKeXjYaxdKcur3j+UdXAlYRD28BRnWmTL5Jx82eUu -NIh0U9pHkn+PjdzmjSPEUP7wzDjQQacaQTkBRf5gPyOYfv/+Mnq6YyflKaPYmkEr -eztO22VZlpyp/hj2LzBav9wi0++teInNQGU+GxHedsWm4+YpffMhz1bz5ZUQ670A -0WJJH3k/KnxbCY3usj4eJr+CsX+LNZhm+rKyjRDmRwA= ------END DSA PRIVATE KEY----- diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/id_dsa_test.pub b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/id_dsa_test.pub deleted file mode 100644 index 0528a928c..000000000 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/id_dsa_test.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-dss AAAAB3NzaC1kc3MAAACBAIsXi0EUiI6GmhHqrwwjvO2wdujW46+uXM/SG2GVI3KxCSf95B2XgXBsgiKH0sy3guyqjDcP4Ph5Mctg1IxqmqugN6xf9YB6lf09bRdIbumVGU6nXW7bZDHdk9nmvWy56vurofwvhoRnQBUJ3L4n7dxxvXhIyRPOxptayOS2ZcnRAAAAFQDsgGxVxcBBM9y0Rm3kNz/R64CYEQAAAIEAgCbyCJNZb66KQBMO7B+NPxx0caSKjZ+3TpWL6pLJGTAu1pztd1wpElECNCEBhTX9p1HEypTIjOUFU2gjgaBLUcWE0JK+/4vJjjvaENvrQardH0EeRfrazhpRY+X6ytUTk0YPDuQn+ZqBhXxAoD8BA+TJMvk7oMpMUTyr6LGBuj4AAACAeXCfOrKY6wHuMkHHpa9Ix95T+7h5ZrSosrV1WO5g9X04LNiPFRXvGyMWYF17VaGqVWID5NbbGP4PqwSw0rjmw7c/xxV2DYNfJ5NFWsDHxhI6RP9AaGTKcdIEykWEkGgJDiVF/DJgjvapGCW4Lo5UB1JJRXEM4YmTiEbyUyahKqw= thomas@Arcturus diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_dsa b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_dsa new file mode 100644 index 000000000..f097516df --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/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.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_dsa.pub b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_dsa.pub new file mode 100644 index 000000000..676685332 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/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.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_dsa_testpass b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_dsa_testpass new file mode 100644 index 000000000..375d38fe4 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/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.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_dsa_testpass.pub b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_dsa_testpass.pub new file mode 100644 index 000000000..676685332 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/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.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_256 b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_256 new file mode 100644 index 000000000..8a4c864af --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/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.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_256.pub b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_256.pub new file mode 100644 index 000000000..43540ec0e --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_256.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKEB01FsLt5yZwh3kr92BOfVMX7hjYwFy8ytDIw8KF7ev6nj44ygEHoR3QCGEB6/c2CbuUgOW/Ohy+YJao3Mvj4= testuser diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_256_testpass b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_256_testpass new file mode 100644 index 000000000..b767c8e99 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/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.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_256_testpass.pub b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_256_testpass.pub new file mode 100644 index 000000000..43540ec0e --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_256_testpass.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKEB01FsLt5yZwh3kr92BOfVMX7hjYwFy8ytDIw8KF7ev6nj44ygEHoR3QCGEB6/c2CbuUgOW/Ohy+YJao3Mvj4= testuser diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_384 b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_384 new file mode 100644 index 000000000..dc2ac8650 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/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.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_384.pub b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_384.pub new file mode 100644 index 000000000..3e813a5e4 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_384.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBCEmsn68ktuRt30LWF77he7Fo7JnUipgmrM9kJdwqQiWDL7QjTtEDFFR3vkYcpzhWLJScurmh1XbkfoU3Mckc7uJ8TgfqOsSkD9QvouR9lF5hniw2Z5AjswFebYhdCwhng== testuser diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_384_testpass b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_384_testpass new file mode 100644 index 000000000..06032d049 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/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.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_384_testpass.pub b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_384_testpass.pub new file mode 100644 index 000000000..3e813a5e4 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_384_testpass.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBCEmsn68ktuRt30LWF77he7Fo7JnUipgmrM9kJdwqQiWDL7QjTtEDFFR3vkYcpzhWLJScurmh1XbkfoU3Mckc7uJ8TgfqOsSkD9QvouR9lF5hniw2Z5AjswFebYhdCwhng== testuser diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_521 b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_521 new file mode 100644 index 000000000..c28151e5a --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/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.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_521.pub b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_521.pub new file mode 100644 index 000000000..9bac1e80f --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_521.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAChltEMzT8dXwIhQD2iuy7QbaBkhWMhpFaxztvzSQqoTZvBgBsOmSr9frFA93lSQoHD1BgewuwBkNGm9lRcw0tEgABqifONkj07Qj2847MKS1iiVu1sHh7Ys3YimyfJc+nZRNi+W03nkcdvWd6PP8y/VENoV7+BtIO9txj8Dt5LYOtFgw== testuser diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_521_testpass b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_521_testpass new file mode 100644 index 000000000..c1c1bbace --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/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.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_521_testpass.pub b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_521_testpass.pub new file mode 100644 index 000000000..9bac1e80f --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_521_testpass.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAChltEMzT8dXwIhQD2iuy7QbaBkhWMhpFaxztvzSQqoTZvBgBsOmSr9frFA93lSQoHD1BgewuwBkNGm9lRcw0tEgABqifONkj07Qj2847MKS1iiVu1sHh7Ys3YimyfJc+nZRNi+W03nkcdvWd6PP8y/VENoV7+BtIO9txj8Dt5LYOtFgw== testuser diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ed25519 b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ed25519 new file mode 100644 index 000000000..02afa5478 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/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.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ed25519.pub b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ed25519.pub new file mode 100644 index 000000000..7857db560 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ed25519.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEgmWtbxcHjqIBVjRepuNgobzAn3mIgvE5vk41CEUG89 testuser diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ed25519_testpass b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ed25519_testpass new file mode 100644 index 000000000..7ad4a7705 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/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.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ed25519_testpass.pub b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ed25519_testpass.pub new file mode 100644 index 000000000..7857db560 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ed25519_testpass.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEgmWtbxcHjqIBVjRepuNgobzAn3mIgvE5vk41CEUG89 testuser diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_1024 b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_1024 new file mode 100644 index 000000000..0b403674f --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/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.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_1024.pub b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_1024.pub new file mode 100644 index 000000000..4aded97ab --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_1024.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDGfj0Jmqj+CUb+WdFrlkRV49TJtNzvvMb/nX20zqgGm50cOIYrMzfFpSQN630pXeAidIgiV/PWAsipntQfSWPRG+RpB/wMKHVUNPJCJkjjRFEa56YxgAhgNwF511K13x4p2tEN0r6wsfw1nos9VoO8XDBAu3lellAgBdufyCt8vw== testuser diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_1024_testpass b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_1024_testpass new file mode 100644 index 000000000..0b66dc0aa --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/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.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_1024_testpass.pub b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_1024_testpass.pub new file mode 100644 index 000000000..4aded97ab --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/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.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_2048 b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_2048 new file mode 100644 index 000000000..a2d7d6231 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/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.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_2048.pub b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_2048.pub new file mode 100644 index 000000000..b787e3648 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/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.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_2048_testpass b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_2048_testpass new file mode 100644 index 000000000..7b3a3f4e5 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/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.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_2048_testpass.pub b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_2048_testpass.pub new file mode 100644 index 000000000..b787e3648 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/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.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_3072 b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_3072 new file mode 100644 index 000000000..10d622c90 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/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.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_3072.pub b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_3072.pub new file mode 100644 index 000000000..686d3b06b --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/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.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_3072_testpass b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_3072_testpass new file mode 100644 index 000000000..353a24c20 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/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.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_3072_testpass.pub b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_3072_testpass.pub new file mode 100644 index 000000000..686d3b06b --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/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.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_4096 b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_4096 new file mode 100644 index 000000000..1a10b388e --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/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.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_4096.pub b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_4096.pub new file mode 100644 index 000000000..3c3c16fee --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/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.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_4096_testpass b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_4096_testpass new file mode 100644 index 000000000..96e29fc15 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/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.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_4096_testpass.pub b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_4096_testpass.pub new file mode 100644 index 000000000..3c3c16fee --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/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.test/tst/org/eclipse/jgit/transport/JSchSshTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/JSchSshTest.java index 7b0344070..8ff70c4e9 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/JSchSshTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/JSchSshTest.java @@ -53,12 +53,16 @@ import java.util.Arrays; import org.eclipse.jgit.errors.TransportException; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.transport.OpenSshConfig.Host; +import org.eclipse.jgit.transport.ssh.SshTestBase; import org.eclipse.jgit.util.FS; +import org.junit.experimental.theories.Theories; +import org.junit.runner.RunWith; import com.jcraft.jsch.JSch; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session; +@RunWith(Theories.class) public class JSchSshTest extends SshTestBase { private class TestSshSessionFactory extends JschConfigSessionFactory { diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ssh/SshTestBase.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ssh/SshTestBase.java new file mode 100644 index 000000000..4afe6e242 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ssh/SshTestBase.java @@ -0,0 +1,608 @@ +/* + * Copyright (C) 2018, Thomas Wolf + * 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.transport.ssh; + +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.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.List; +import java.util.Map; + +import org.eclipse.jgit.api.errors.TransportException; +import org.eclipse.jgit.transport.CredentialItem; +import org.eclipse.jgit.transport.JschConfigSessionFactory; +import org.eclipse.jgit.transport.URIish; +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", // + // 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" }; + + protected File defaultCloneDir; + + @Override + public void setUp() throws Exception { + super.setUp(); + defaultCloneDir = new File(getTemporaryDirectory(), "cloned"); + } + + @Test(expected = TransportException.class) + public void testSshWithoutConfig() throws Exception { + cloneWith("ssh://" + TEST_USER + "@localhost:" + testPort + + "/doesntmatter", defaultCloneDir, null); + } + + @Test + public void testSshWithGlobalIdentity() throws Exception { + cloneWith( + "ssh://" + TEST_USER + "@localhost:" + testPort + + "/doesntmatter", + defaultCloneDir, null, + "IdentityFile " + privateKey1.getAbsolutePath()); + } + + @Test + public void testSshWithDefaultIdentity() throws Exception { + File idRsa = new File(privateKey1.getParentFile(), "id_rsa"); + Files.copy(privateKey1.toPath(), idRsa.toPath()); + // We expect the session factory to pick up these keys... + cloneWith("ssh://" + TEST_USER + "@localhost:" + testPort + + "/doesntmatter", defaultCloneDir, null); + } + + @Test + public void testSshWithConfig() throws Exception { + cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, null, // + "Host localhost", // + "HostName localhost", // + "Port " + testPort, // + "User " + TEST_USER, // + "IdentityFile " + privateKey1.getAbsolutePath()); + } + + @Test + public void testSshWithConfigEncryptedUnusedKey() throws Exception { + // Copy the encrypted test key from the bundle. + File encryptedKey = new File(sshDir, "id_dsa"); + copyTestResource("id_dsa_testpass", encryptedKey); + TestCredentialsProvider provider = new TestCredentialsProvider( + "testpass"); + cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, provider, // + "Host localhost", // + "HostName localhost", // + "Port " + testPort, // + "User " + TEST_USER, // + "IdentityFile " + privateKey1.getAbsolutePath()); + assertEquals("CredentialsProvider should not have been called", 0, + provider.getLog().size()); + } + + @Test + public void testSshWithConfigEncryptedUnusedKeyInConfigLast() + throws Exception { + // Copy the encrypted test key from the bundle. + File encryptedKey = new File(sshDir, "id_dsa_test_key"); + copyTestResource("id_dsa_testpass", encryptedKey); + TestCredentialsProvider provider = new TestCredentialsProvider( + "testpass"); + cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, provider, // + "Host localhost", // + "HostName localhost", // + "Port " + testPort, // + "User " + TEST_USER, // + "IdentityFile " + privateKey1.getAbsolutePath(), + "IdentityFile " + encryptedKey.getAbsolutePath()); + // This test passes with JSch per chance because JSch completely ignores + // the second IdentityFile + assertEquals("CredentialsProvider should not have been called", 0, + provider.getLog().size()); + } + + @Test + public void testSshWithConfigEncryptedUnusedKeyInConfigFirst() + throws Exception { + // Test cannot pass with JSch; it handles only one IdentityFile + assumeTrue(!(getSessionFactory() instanceof JschConfigSessionFactory)); + // 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 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()); + Map> messages = provider.getLog(); + assertFalse("Expected user interaction", messages.isEmpty()); + if (getSessionFactory() instanceof JschConfigSessionFactory) { + // JSch doesn't create a non-existing file. + assertEquals("Expected to be asked about the key", 1, + messages.size()); + return; + } + assertEquals( + "Expected to be asked about the key, and the file creation", + 2, messages.size()); + assertTrue("~/.ssh/known_hosts should exist now", knownHosts.exists()); + // Instead of checking the file contents, let's just clone again + // without provider. If it works, the server host key was written + // correctly. + File clonedAgain = new File(getTemporaryDirectory(), "cloned2"); + cloneWith("ssh://localhost/doesntmatter", clonedAgain, provider, // + "Host localhost", // + "HostName localhost", // + "Port " + testPort, // + "User " + TEST_USER, // + "IdentityFile " + privateKey1.getAbsolutePath()); + } + + @Test + public void testSshWithoutKnownHostsWithProviderAcceptNew() + throws Exception { + File copiedHosts = new File(knownHosts.getParentFile(), + "copiedKnownHosts"); + assertTrue("Failed to rename known_hosts", + knownHosts.renameTo(copiedHosts)); + TestCredentialsProvider provider = new TestCredentialsProvider(); + cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, provider, // + "Host localhost", // + "HostName localhost", // + "Port " + testPort, // + "User " + TEST_USER, // + "StrictHostKeyChecking accept-new", // + "IdentityFile " + privateKey1.getAbsolutePath()); + if (getSessionFactory() instanceof JschConfigSessionFactory) { + // JSch doesn't create new files. + assertTrue("CredentialsProvider not called", + provider.getLog().isEmpty()); + return; + } + assertEquals("Expected to be asked about the file creation", 1, + provider.getLog().size()); + assertTrue("~/.ssh/known_hosts should exist now", knownHosts.exists()); + // Instead of checking the file contents, let's just clone again + // without provider. If it works, the server host key was written + // correctly. + File clonedAgain = new File(getTemporaryDirectory(), "cloned2"); + cloneWith("ssh://localhost/doesntmatter", clonedAgain, null, // + "Host localhost", // + "HostName localhost", // + "Port " + testPort, // + "User " + TEST_USER, // + "IdentityFile " + privateKey1.getAbsolutePath()); + } + + @Test(expected = TransportException.class) + public void testSshWithoutKnownHostsDeny() throws Exception { + File copiedHosts = new File(knownHosts.getParentFile(), + "copiedKnownHosts"); + assertTrue("Failed to rename known_hosts", + knownHosts.renameTo(copiedHosts)); + cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, null, // + "Host localhost", // + "HostName localhost", // + "Port " + testPort, // + "User " + TEST_USER, // + "StrictHostKeyChecking yes", // + "IdentityFile " + privateKey1.getAbsolutePath()); + } + + @Test(expected = TransportException.class) + public void testSshModifiedHostKeyDeny() + throws Exception { + File copiedHosts = new File(knownHosts.getParentFile(), + "copiedKnownHosts"); + assertTrue("Failed to rename known_hosts", + knownHosts.renameTo(copiedHosts)); + // Now produce a new known_hosts file containing some other key. + createKnownHostsFile(knownHosts, "localhost", testPort, publicKey1); + cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, null, // + "Host localhost", // + "HostName localhost", // + "Port " + testPort, // + "User " + TEST_USER, // + "StrictHostKeyChecking yes", // + "IdentityFile " + privateKey1.getAbsolutePath()); + } + + @Test(expected = TransportException.class) + public void testSshModifiedHostKeyWithProviderDeny() throws Exception { + File copiedHosts = new File(knownHosts.getParentFile(), + "copiedKnownHosts"); + assertTrue("Failed to rename known_hosts", + knownHosts.renameTo(copiedHosts)); + // Now produce a new known_hosts file containing some other key. + createKnownHostsFile(knownHosts, "localhost", testPort, publicKey1); + TestCredentialsProvider provider = new TestCredentialsProvider(); + try { + cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, provider, // + "Host localhost", // + "HostName localhost", // + "Port " + testPort, // + "User " + TEST_USER, // + "StrictHostKeyChecking yes", // + "IdentityFile " + privateKey1.getAbsolutePath()); + } catch (Exception e) { + assertEquals("Expected to be told about the modified key", 1, + provider.getLog().size()); + assertTrue("Only messages expected", provider.getLog().values() + .stream().flatMap(List::stream).allMatch( + c -> c instanceof CredentialItem.InformationalMessage)); + throw e; + } + } + + private void checkKnownHostsModifiedHostKey(File backup, File newFile, + String wrongKey) throws IOException { + List oldLines = Files.readAllLines(backup.toPath(), + StandardCharsets.UTF_8); + // Find the original entry. We should have that again in known_hosts. + String oldKeyPart = null; + for (String oldLine : oldLines) { + if (oldLine.contains("[localhost]:")) { + String[] parts = oldLine.split("\\s+"); + if (parts.length > 2) { + oldKeyPart = parts[parts.length - 2] + ' ' + + parts[parts.length - 1]; + break; + } + } + } + assertNotNull("Old key not found", oldKeyPart); + List newLines = Files.readAllLines(newFile.toPath(), + StandardCharsets.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(), StandardCharsets.UTF_8) + .toArray(new String[0]); + String[] newLines = Files + .readAllLines(knownHosts.toPath(), StandardCharsets.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"); + } + + @Theory + public void testSshKeys(String keyName) throws Exception { + // JSch fails on ECDSA 384/521 keys. Compare + // https://sourceforge.net/p/jsch/patches/10/ + assumeTrue(!(getSessionFactory() instanceof JschConfigSessionFactory + && (keyName.startsWith("id_ecdsa_384") + || keyName.startsWith("id_ecdsa_521")))); + File cloned = new File(getTemporaryDirectory(), "cloned"); + String keyFileName = keyName + "_key"; + File privateKey = new File(sshDir, keyFileName); + copyTestResource(keyName, privateKey); + File publicKey = new File(sshDir, keyFileName + ".pub"); + copyTestResource(keyName + ".pub", publicKey); + server.setTestUserPublicKey(publicKey.toPath()); + TestCredentialsProvider provider = new TestCredentialsProvider( + "testpass"); + pushTo(provider, + cloneWith("ssh://localhost/doesntmatter", // + cloned, provider, // + "Host localhost", // + "HostName localhost", // + "Port " + testPort, // + "User " + TEST_USER, // + "IdentityFile " + privateKey.getAbsolutePath())); + int expectedCalls = keyName.endsWith("testpass") ? 1 : 0; + assertEquals("Unexpected calls to CredentialsProvider", expectedCalls, + provider.getLog().size()); + // Should now also work without credentials provider, even if the key + // was encrypted. + cloned = new File(getTemporaryDirectory(), "cloned2"); + pushTo(null, + cloneWith("ssh://localhost/doesntmatter", // + cloned, null, // + "Host localhost", // + "HostName localhost", // + "Port " + testPort, // + "User " + TEST_USER, // + "IdentityFile " + privateKey.getAbsolutePath())); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/SshTestBase.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ssh/SshTestHarness.java similarity index 53% rename from org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/SshTestBase.java rename to org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ssh/SshTestHarness.java index 28ba1f89f..347c72b3d 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/SshTestBase.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ssh/SshTestHarness.java @@ -40,7 +40,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.eclipse.jgit.transport; +package org.eclipse.jgit.transport.ssh; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -51,6 +51,7 @@ 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.charset.StandardCharsets; @@ -64,18 +65,39 @@ import java.util.Map; import org.eclipse.jgit.api.CloneCommand; import org.eclipse.jgit.api.Git; -import org.eclipse.jgit.api.errors.TransportException; +import org.eclipse.jgit.api.PushCommand; +import org.eclipse.jgit.api.ResetCommand.ResetType; import org.eclipse.jgit.errors.UnsupportedCredentialItem; import org.eclipse.jgit.junit.RepositoryTestCase; import org.eclipse.jgit.junit.ssh.SshTestGitServer; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.transport.CredentialItem; +import org.eclipse.jgit.transport.CredentialsProvider; +import org.eclipse.jgit.transport.PushResult; +import org.eclipse.jgit.transport.RemoteRefUpdate; +import org.eclipse.jgit.transport.SshSessionFactory; +import org.eclipse.jgit.transport.URIish; import org.eclipse.jgit.util.FS; import org.junit.After; -import org.junit.Test; import com.jcraft.jsch.JSch; import com.jcraft.jsch.KeyPair; -public abstract class SshTestBase extends RepositoryTestCase { +/** + * 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"; @@ -85,7 +107,9 @@ public abstract class SshTestBase extends RepositoryTestCase { protected File privateKey2; - private SshTestGitServer server; + protected File publicKey1; + + protected SshTestGitServer server; private SshSessionFactory factory; @@ -116,11 +140,11 @@ public abstract class SshTestBase extends RepositoryTestCase { // Create two key pairs. Let's not call them "id_rsa". privateKey1 = new File(sshDir, "first_key"); privateKey2 = new File(sshDir, "second_key"); - createKeyPair(privateKey1); + 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, privateKey1.toPath(), db, + server = new SshTestGitServer(TEST_USER, publicKey1.toPath(), db, createHostKey(publicHostKey)); testPort = server.start(); assertTrue(testPort > 0); @@ -132,7 +156,7 @@ public abstract class SshTestBase extends RepositoryTestCase { SshSessionFactory.setInstance(factory); } - private static void createKeyPair(File privateKeyFile) throws Exception { + 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(); @@ -145,6 +169,7 @@ public abstract class SshTestBase extends RepositoryTestCase { try (OutputStream out = new FileOutputStream(publicKeyFile)) { pair.writePublicKey(out, TEST_USER); } + return publicKeyFile; } private static byte[] createHostKey(OutputStream publicKey) @@ -159,6 +184,58 @@ public abstract class SshTestBase extends RepositoryTestCase { } } + /** + * Creates a new known_hosts file with one entry for the given host and port + * taken from the given public key file. + * + * @param file + * to write the known_hosts file to + * @param host + * for the entry + * @param port + * for the entry + * @param publicKey + * to use + * @return the public-key part of the line + * @throws IOException + */ + protected static String createKnownHostsFile(File file, String host, + int port, File publicKey) throws IOException { + List lines = Files.readAllLines(publicKey.toPath(), + StandardCharsets.UTF_8); + assertEquals("Public key has too many lines", 1, lines.size()); + String pubKey = lines.get(0); + // Strip off the comment. + String[] parts = pubKey.split("\\s+"); + assertTrue("Unexpected key content", + parts.length == 2 || parts.length == 3); + String keyPart = parts[0] + ' ' + parts[1]; + String line = '[' + host + "]:" + port + ' ' + keyPart; + Files.write(file.toPath(), Collections.singletonList(line)); + return keyPart; + } + + /** + * Checks whether there is a line for the given host and port that also + * matches the given key part in the list of lines. + * + * @param host + * to look for + * @param port + * to look for + * @param keyPart + * to look for + * @param lines + * to look in + * @return {@code true} if found, {@code false} otherwise + */ + protected boolean hasHostKey(String host, int port, String keyPart, + List lines) { + String h = '[' + host + "]:" + port; + return lines.stream() + .anyMatch(l -> l.contains(h) && l.contains(keyPart)); + } + @After public void shutdownServer() throws Exception { if (server != null) { @@ -178,221 +255,111 @@ public abstract class SshTestBase extends RepositoryTestCase { protected abstract void installConfig(String... config); - @Test(expected = TransportException.class) - public void testSshCloneWithoutConfig() throws Exception { - cloneWith("ssh://" + TEST_USER + "@localhost:" + testPort - + "/doesntmatter", null); + /** + * 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); } - @Test - public void testSshCloneWithGlobalIdentity() throws Exception { - cloneWith( - "ssh://" + TEST_USER + "@localhost:" + testPort - + "/doesntmatter", - null, - "IdentityFile " + privateKey1.getAbsolutePath()); - } - - @Test - public void testSshCloneWithDefaultIdentity() 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", null); - } - - @Test - public void testSshCloneWithConfig() throws Exception { - cloneWith("ssh://localhost/doesntmatter", null, // - "Host localhost", // - "HostName localhost", // - "Port " + testPort, // - "User " + TEST_USER, // - "IdentityFile " + privateKey1.getAbsolutePath()); - } - - @Test - public void testSshCloneWithConfigEncryptedUnusedKey() throws Exception { - // Copy the encrypted test key from the bundle. - File encryptedKey = new File(sshDir, "id_dsa"); - try (InputStream in = SshTestBase.class - .getResourceAsStream("id_dsa_test")) { - Files.copy(in, encryptedKey.toPath()); + /** + * 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()); } - TestCredentialsProvider provider = new TestCredentialsProvider( - "testpass"); - cloneWith("ssh://localhost/doesntmatter", 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(expected = TransportException.class) - public void testSshCloneWithoutKnownHosts() throws Exception { - assertTrue("Could not delete known_hosts", knownHosts.delete()); - cloneWith("ssh://localhost/doesntmatter", null, // - "Host localhost", // - "HostName localhost", // - "Port " + testPort, // - "User " + TEST_USER, // - "IdentityFile " + privateKey1.getAbsolutePath()); - } - - @Test - public void testSshCloneWithoutKnownHostsWithProvider() 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", provider, // - "Host localhost", // - "HostName localhost", // - "Port " + testPort, // - "User " + TEST_USER, // - "IdentityFile " + privateKey1.getAbsolutePath()); - Map> messages = provider.getLog(); - assertFalse("Expected user iteraction", messages.isEmpty()); - } - - @Test - public void testSftpCloneWithConfig() throws Exception { - cloneWith("sftp://localhost/.git", null, // - "Host localhost", // - "HostName localhost", // - "Port " + testPort, // - "User " + TEST_USER, // - "IdentityFile " + privateKey1.getAbsolutePath()); - } - - @Test(expected = TransportException.class) - public void testSshCloneWithConfigWrongKey() throws Exception { - cloneWith("ssh://localhost/doesntmatter", null, // - "Host localhost", // - "HostName localhost", // - "Port " + testPort, // - "User " + TEST_USER, // - "IdentityFile " + privateKey2.getAbsolutePath()); - } - - @Test - public void testSshCloneWithWrongUserNameInConfig() throws Exception { - // Bug 526778 - cloneWith( - "ssh://" + TEST_USER + "@localhost:" + testPort - + "/doesntmatter", - null, // - "Host localhost", // - "HostName localhost", // - "User sombody_else", // - "IdentityFile " + privateKey1.getAbsolutePath()); - } - - @Test - public void testSshCloneWithWrongPortInConfig() throws Exception { - // Bug 526778 - cloneWith( - "ssh://" + TEST_USER + "@localhost:" + testPort - + "/doesntmatter", - null, // - "Host localhost", // - "HostName localhost", // - "Port 22", // - "User " + TEST_USER, // - "IdentityFile " + privateKey1.getAbsolutePath()); - } - - @Test - public void testSshCloneWithAliasInConfig() throws Exception { - // Bug 531118 - cloneWith("ssh://git/doesntmatter", 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 testSshCloneWithUnknownCiphersInConfig() throws Exception { - // Bug 535672 - cloneWith("ssh://git/doesntmatter", 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 testSshCloneWithUnknownHostKeyAlgorithmsInConfig() - throws Exception { - // Bug 535672 - cloneWith("ssh://git/doesntmatter", null, // - "Host git", // - "HostName localhost", // - "Port " + testPort, // - "User " + TEST_USER, // - "IdentityFile " + privateKey1.getAbsolutePath(), // - "HostKeyAlgorithms foobar,ssh-rsa,ssh-dss"); - } - - @Test - public void testSshCloneWithUnknownKexAlgorithmsInConfig() - throws Exception { - // Bug 535672 - cloneWith("ssh://git/doesntmatter", 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 testSshCloneWithMinimalHostKeyAlgorithmsInConfig() - throws Exception { - // Bug 537790 - cloneWith("ssh://git/doesntmatter", null, // - "Host git", // - "HostName localhost", // - "Port " + testPort, // - "User " + TEST_USER, // - "IdentityFile " + privateKey1.getAbsolutePath(), // - "HostKeyAlgorithms ssh-rsa,ssh-dss"); - } - - private void cloneWith(String uri, CredentialsProvider provider, + protected File cloneWith(String uri, File to, CredentialsProvider provider, String... config) throws Exception { installConfig(config); - File cloned = new File(getTemporaryDirectory(), "cloned"); CloneCommand clone = Git.cloneRepository().setCloneAllBranches(true) - .setDirectory(cloned).setURI(uri); + .setDirectory(to).setURI(uri); if (provider != null) { clone.setCredentialsProvider(provider); } try (Git git = clone.call()) { - assertNotNull(git.getRepository().resolve("master")); + Repository repo = git.getRepository(); + assertNotNull(repo.resolve("master")); assertNotEquals(db.getWorkTree(), git.getRepository().getWorkTree()); - checkFile(new File(git.getRepository().getWorkTree(), "file.txt"), - "something"); + assertTrue(new File(git.getRepository().getWorkTree(), "file.txt") + .exists()); + return repo.getWorkTree(); } } - private static class TestCredentialsProvider extends CredentialsProvider { + protected void pushTo(File localClone) throws Exception { + pushTo(null, localClone); + } + + protected void pushTo(CredentialsProvider provider, File localClone) + throws Exception { + RevCommit commit; + File newFile = null; + try (Git git = Git.open(localClone)) { + // Write a new file and modify a file. + Repository local = git.getRepository(); + newFile = File.createTempFile("new", "sshtest", + local.getWorkTree()); + write(newFile, "something new"); + File existingFile = new File(local.getWorkTree(), "file.txt"); + write(existingFile, "something else"); + git.add().addFilepattern("file.txt") + .addFilepattern(newFile.getName()) + .call(); + commit = git.commit().setMessage("Local commit").call(); + // Push + PushCommand push = git.push().setPushAll(); + if (provider != null) { + push.setCredentialsProvider(provider); + } + Iterable results = push.call(); + for (PushResult result : results) { + for (RemoteRefUpdate u : result.getRemoteUpdates()) { + assertEquals( + "Could not update " + u.getRemoteName() + ' ' + + u.getMessage(), + RemoteRefUpdate.Status.OK, u.getStatus()); + } + } + } + // Now check "master" in the remote repo directly: + assertEquals("Unexpected remote commit", commit, db.resolve("master")); + assertEquals("Unexpected remote commit", commit, + db.resolve(Constants.HEAD)); + File remoteFile = new File(db.getWorkTree(), newFile.getName()); + assertFalse("File should not exist on remote", remoteFile.exists()); + try (Git git = new Git(db)) { + git.reset().setMode(ResetType.HARD).setRef(Constants.HEAD).call(); + } + assertTrue("File does not exist on remote", remoteFile.exists()); + checkFile(remoteFile, "something new"); + } + + protected static class TestCredentialsProvider extends CredentialsProvider { private final List stringStore; @@ -463,4 +430,5 @@ public abstract class SshTestBase extends RepositoryTestCase { return log; } } + } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FtpChannel.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FtpChannel.java index 162a1dcee..39e87b246 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FtpChannel.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FtpChannel.java @@ -42,6 +42,7 @@ */ package org.eclipse.jgit.transport; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -201,17 +202,44 @@ public interface FtpChannel { * @param path * to delete * @throws IOException + * if the file does not exist or could otherwise not be deleted */ void rm(String path) throws IOException; /** - * Renames a file on the remote file system. + * Deletes a file on the remote file system. If the file does not exist, no + * exception is thrown. + * + * @param path + * to delete + * @throws IOException + * if the file exist but could not be deleted + */ + default void delete(String path) throws IOException { + try { + rm(path); + } catch (FileNotFoundException e) { + // Ignore; it's OK if the file doesn't exist + } catch (FtpException f) { + if (f.getStatus() == FtpException.NO_SUCH_FILE) { + return; + } + throw f; + } + } + + /** + * Renames a file on the remote file system. If {@code to} exists, it is + * replaced by {@code from}. (POSIX rename() semantics) * * @param from * original name of the file * @param to * new name of the file * @throws IOException + * @see stdio.h: + * rename() */ void rename(String from, String to) throws IOException; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschSession.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschSession.java index a7797d98f..843b90c95 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschSession.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschSession.java @@ -369,10 +369,37 @@ public class JschSession implements RemoteSession { @Override public void rename(String from, String to) throws IOException { map(() -> { - ftp.rename(from, to); + // Plain FTP rename will fail if "to" exists. Jsch knows about + // the FTP extension "posix-rename@openssh.com", which will + // remove "to" first if it exists. + if (hasPosixRename()) { + ftp.rename(from, to); + } else if (!to.equals(from)) { + // Try to remove "to" first. With git, we typically get this + // when a lock file is moved over the file locked. Note that + // the check for to being equal to from may still fail in + // the general case, but for use with JGit's TransportSftp + // it should be good enough. + delete(to); + ftp.rename(from, to); + } return null; }); } + /** + * Determine whether the server has the posix-rename extension. + * + * @return {@code true} if it is supported, {@code false} otherwise + * @see OpenSSH + * deviations and extensions to the published SSH protocol + * @see stdio.h: + * rename() + */ + private boolean hasPosixRename() { + return "1".equals(ftp.getExtension("posix-rename@openssh.com")); //$NON-NLS-1$//$NON-NLS-2$ + } } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportSftp.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportSftp.java index 5cf986718..5c68308f9 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportSftp.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportSftp.java @@ -272,13 +272,8 @@ public class TransportSftp extends SshTransport implements WalkTransport { @Override void deleteFile(String path) throws IOException { try { - ftp.rm(path); - } catch (FileNotFoundException e) { - return; + ftp.delete(path); } catch (FtpChannel.FtpException f) { - if (f.getStatus() == FtpChannel.FtpException.NO_SUCH_FILE) { - return; - } throw new TransportException(MessageFormat.format( JGitText.get().cannotDeleteObjectsPath, objectsPath, path, f.getMessage()), f);