aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit.junit.ssh
diff options
context:
space:
mode:
authorMatthias Sohn <matthias.sohn@sap.com>2020-11-28 21:02:09 +0100
committerMatthias Sohn <matthias.sohn@sap.com>2020-11-28 21:51:50 +0100
commit286ad23cb56ffeac77d4bfd03be575358fd5217c (patch)
treedc075c6b1d1e813f253ec465813b6251d9d07d61 /org.eclipse.jgit.junit.ssh
parent4887894ffd637030a311ca8d60b78515b1a5cf35 (diff)
parent4f2065d145c3fa3f8ad3de28af3ee5dfeb74c765 (diff)
downloadjgit-286ad23cb56ffeac77d4bfd03be575358fd5217c.tar.gz
jgit-286ad23cb56ffeac77d4bfd03be575358fd5217c.zip
Merge branch 'master' into next
* master: Remove unused imports Silence API warnings Remove erraneously merged source features Add support for reading symrefs from pack capabilities Prepare 5.3.9-SNAPSHOT builds JGit v5.3.8.202011260953-r Prepare 5.1.15-SNAPSHOT builds JGit v5.1.14.202011251942-r GC#deleteOrphans: log warning for deleted orphaned files GC#deleteOrphans: handle failure to list files in pack directory Ensure that GC#deleteOrphans respects pack lock Prepare 5.10.0-SNAPSHOT builds JGit v5.10.0.202011251205-m3 PacketLineIn: ensure that END != DELIM Update Orbit to S20201118210000 and add target for 4.18 PacketLineIn: ensure that END != DELIM PacketLineIn: ensure that END != DELIM Allow to resolve a conflict by checking out a file Update Orbit to I20201111205634 Document that setLastModified sets time of symlink target Fix bug in PerformanceLogContext Fix IOException occurring during gc Prepare 5.10.0-SNAPSHOT builds JGit v5.10.0.202011041322-m2 Revert "Client-side protocol V2 support for fetching" Close Repository to fix tests failing on Windows Client-side protocol V2 support for fetching Update slf4j to 1.7.30 Update Orbit to S20201027182932 (2020-12 M2) Fix formatting of config option values Document options in core section supported by JGit Ensure .gitmodules is loaded when accessing submodule name Export new package org.eclipse.jgit.logging and import it where used Ensure GC.deleteOrphans() can delete read-only orphaned files on Windows Add new performance logging Implement git describe --all Compute time differences with Duration Override config http.userAgent from environment GIT_HTTP_USER_AGENT Upgrade spotbugs-maven-plugin to 4.1.3 Fix OperatorPrecedence warning flagged by error prone UploadPackTest#testUploadRedundantBytes: ensure test repo is closed ObjectDirectory#selectObjectRepresentation: fix formatting Upgrade ecj to 3.23.0 Support "http.userAgent" and "http.extraHeader" from the git config sshd: better error report when user cancels authentication API filters for PackStatistics.Accumulator Add TypedConfigGetter.getPath() Make Javadoc consistent for PackStatistics fields Measure time taken for reachability checks Measure time taken for negotiation in protocol V2 IndexDiffFilter: handle path prefixes correctly sshd: support the ProxyJump ssh config Upgrade jacoco-maven-plugin to 0.8.6 ReceivePackStats: Add size and count of unnecessary pushed objects Upgrade maven-project-info-reports-plugin to 3.1.1 Prepare 5.9.1-SNAPSHOT builds JGit v5.9.0.202009080501-r [releng] Enable japicmp for the fragments added in 5.8.0 GitlinkMergeTest: fix boxing warnings Remove unused API problem filters Add missing since tag on BundleWriter#addObjectsAsIs SshdSession: close channel gracefully GPG: include signer's user ID in the signature jgit: Add DfsBundleWriter Bump Bazel version to 3.5.0 Upgrade maven-resources-plugin to 3.2.0 Upgrade plexus-compiler version to 2.8.8 [bazel] Add missing dependency to slf4j-api [errorprone] DirCacheEntry: make clear operator precedence [errorprone] PackWriter#parallelDeltaSearch: avoid suppressed exception [errorprone] Declare DirCache#version final Add jgit-4.17-staging target platform for 2020-09 Update target platform to R20200831200620 Prepare 5.10.0-SNAPSHOT builds Prepare 5.9.0-SNAPSHOT builds ResolveMerger: do not content-merge gitlinks on del/mod conflicts ResolveMerger: Adding test cases for GITLINK deletion ResolveMerger: choose OURS on gitlink when ignoreConflicts ResolveMerger: improving content merge readability ResolveMerger: extracting createGitLinksMergeResult method ResolveMerger: Adding test cases for GITLINK merge JGit v5.9.0.202008260805-m3 Fix possible NegativeArraySizeException in PackIndexV1 FS: use binary search to determine filesystem timestamp resolution Do not prematurely create directory of jgit's XDG config file FS: write to JGit config in a background thread FS: don't cache fallback if running in background Keep line endings for text files committed with CR/LF on text=auto Delay WindowCache statistics JMX MBean registration [releng] Update plexus-compiler to 2.8.7 DirCache: support index V4 Update javadoc for RemoteSession and SshSessionFactory Fix JSchProcess.waitFor() with time-out sshd: work around a race condition in Apache MINA sshd 2.4.0/2.5.x sshd: store per-session data on the sshd session object FilterSpec: Use BigInteger.ZERO instead of valueOf(0) Do not send empty blob in response to blob:none filter Add support for tree filters when fetching sshd: use PropertyResolver in test FS_POSIX: avoid prompt to install the XCode tools on OS X Remove dependency on JSch from SSH test framework Use LinkedBlockingQueue for executor determining filesystem attributes Update API warning filters Remove unused imports Bazel: Add workspace status command to stamp final artifact DiffFormatter: correctly deal with tracked files in ignored folders Prepare 5.8.2-SNAPSHOT builds JGit v5.8.1.202007141445-r Update Jetty to 9.4.30.v20200611 Fix writing GPG signatures with trailing newline Rename a test method Add a test for upstream bug SSHD-1028 Improve error message when receive.maxCommandBytes is exceeded LfsConnectionFactory#getLfsUrl: Fix unconditional break in for-loop DiffFormatterTest: Add a test to confirm the default rename detection settings Upgrade maven-site-plugin to 3.9.1 Upgrade build-helper-maven-plugin to 3.2.0 Upgrade spotbugs to 4.0.4 MergedReftable: Include the last reftable in determining minUpdateIndex Add new osgi fragments to maven-central deploy scripts PackBitmapIndex: Not buffer inflated bitmap during bitmap creation. Do not require org.assertj.core.annotations Upgrade ecj to 3.22.0 Remove workaround for signing jars using Tycho plugins Use https for URL of jgit website Fix CI information in pom.xml Use gitiles as scm url in pom.xml for browsing source code Update API baseline to 5.8.0.202006091008-r Remove trailing whitespace Change-Id: Ie6bc6954741a47cfbd32c0886bdbd7b594f08b31 Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
Diffstat (limited to 'org.eclipse.jgit.junit.ssh')
-rw-r--r--org.eclipse.jgit.junit.ssh/BUILD2
-rw-r--r--org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF3
-rw-r--r--org.eclipse.jgit.junit.ssh/pom.xml10
-rw-r--r--org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshTestBase.java49
-rw-r--r--org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshTestGitServer.java146
-rw-r--r--org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshTestHarness.java89
6 files changed, 239 insertions, 60 deletions
diff --git a/org.eclipse.jgit.junit.ssh/BUILD b/org.eclipse.jgit.junit.ssh/BUILD
index 61b5ce78cb..f7856b5273 100644
--- a/org.eclipse.jgit.junit.ssh/BUILD
+++ b/org.eclipse.jgit.junit.ssh/BUILD
@@ -13,8 +13,8 @@ java_library(
"//org.eclipse.jgit.ssh.jsch.test:__pkg__",
],
deps = [
- "//lib:jsch",
"//lib:junit",
+ "//lib:slf4j-api",
"//lib:sshd-osgi",
"//lib:sshd-sftp",
# We want these deps to be provided_deps
diff --git a/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF
index 2b06d48047..8858c09cbd 100644
--- a/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF
@@ -8,8 +8,7 @@ Bundle-Localization: plugin
Bundle-Vendor: %Bundle-Vendor
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
-Import-Package: com.jcraft.jsch;version="0.1.55",
- org.apache.sshd.common;version="[2.4.0,2.5.0)",
+Import-Package: 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)",
diff --git a/org.eclipse.jgit.junit.ssh/pom.xml b/org.eclipse.jgit.junit.ssh/pom.xml
index cd4626037f..a6f466016a 100644
--- a/org.eclipse.jgit.junit.ssh/pom.xml
+++ b/org.eclipse.jgit.junit.ssh/pom.xml
@@ -58,16 +58,6 @@
</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>
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
index 2d284cf1d5..3784741195 100644
--- 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
@@ -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
@@ -14,6 +14,7 @@ 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.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
@@ -22,9 +23,14 @@ import java.io.IOException;
import java.nio.file.Files;
import java.util.List;
import java.util.Locale;
+import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.api.errors.TransportException;
+import org.eclipse.jgit.errors.CommandFailedException;
import org.eclipse.jgit.transport.CredentialItem;
+import org.eclipse.jgit.transport.URIish;
+import org.eclipse.jgit.util.FS;
+import org.eclipse.jgit.util.SshSupport;
import org.junit.Test;
import org.junit.experimental.theories.DataPoints;
import org.junit.experimental.theories.Theory;
@@ -67,10 +73,45 @@ public abstract class SshTestBase extends SshTestHarness {
defaultCloneDir = new File(getTemporaryDirectory(), "cloned");
}
- @Test(expected = TransportException.class)
+ @Test
public void testSshWithoutConfig() throws Exception {
- cloneWith("ssh://" + TEST_USER + "@localhost:" + testPort
- + "/doesntmatter", defaultCloneDir, null);
+ assertThrows(TransportException.class,
+ () -> cloneWith("ssh://" + TEST_USER + "@localhost:" + testPort
+ + "/doesntmatter", defaultCloneDir, null));
+ }
+
+ @Test
+ public void testSingleCommand() throws Exception {
+ installConfig("IdentityFile " + privateKey1.getAbsolutePath());
+ String command = SshTestGitServer.ECHO_COMMAND + " 1 without timeout";
+ long start = System.nanoTime();
+ String reply = SshSupport.runSshCommand(
+ new URIish("ssh://" + TEST_USER + "@localhost:" + testPort),
+ null, FS.DETECTED, command, 0); // 0 == no timeout
+ long elapsed = System.nanoTime() - start;
+ assertEquals(command, reply);
+ // Now that we have an idea how long this takes on the test
+ // infrastructure, try again with a timeout.
+ command = SshTestGitServer.ECHO_COMMAND + " 1 expecting no timeout";
+ // Still use a generous timeout.
+ int timeout = 10 * ((int) TimeUnit.NANOSECONDS.toSeconds(elapsed) + 1);
+ reply = SshSupport.runSshCommand(
+ new URIish("ssh://" + TEST_USER + "@localhost:" + testPort),
+ null, FS.DETECTED, command, timeout);
+ assertEquals(command, reply);
+ }
+
+ @Test
+ public void testSingleCommandWithTimeoutExpired() throws Exception {
+ installConfig("IdentityFile " + privateKey1.getAbsolutePath());
+ String command = SshTestGitServer.ECHO_COMMAND + " 2 EXPECTING TIMEOUT";
+
+ CommandFailedException e = assertThrows(CommandFailedException.class,
+ () -> SshSupport.runSshCommand(new URIish(
+ "ssh://" + TEST_USER + "@localhost:" + testPort), null,
+ FS.DETECTED, command, 1));
+ assertTrue(e.getMessage().contains(command));
+ assertTrue(e.getMessage().contains("time"));
}
@Test
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 03e2855829..ab8e0c1ca0 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
@@ -12,6 +12,8 @@ package org.eclipse.jgit.junit.ssh;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.GeneralSecurityException;
@@ -22,8 +24,10 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
+import java.util.concurrent.TimeUnit;
import org.apache.sshd.common.NamedResource;
+import org.apache.sshd.common.PropertyResolver;
import org.apache.sshd.common.PropertyResolverUtils;
import org.apache.sshd.common.SshConstants;
import org.apache.sshd.common.config.keys.AuthorizedKeyEntry;
@@ -66,6 +70,16 @@ import org.eclipse.jgit.transport.UploadPack;
*/
public class SshTestGitServer {
+ /**
+ * Simple echo test command. Replies with the command string as passed. If
+ * of the form "echo [int] anything", takes the integer value as a delay in
+ * seconds before replying, which may be useful to test various
+ * timeout-related things.
+ *
+ * @since 5.9
+ */
+ public static final String ECHO_COMMAND = "echo";
+
@NonNull
protected final String testUser;
@@ -90,8 +104,7 @@ public class SshTestGitServer {
* @param testUser
* user name of the test user
* @param testKey
- * <em>private</em> key file of the test user; the server will
- * only user the public key from it
+ * public key file of the test user
* @param repository
* to serve
* @param hostKey
@@ -102,17 +115,54 @@ public class SshTestGitServer {
public SshTestGitServer(@NonNull String testUser, @NonNull Path testKey,
@NonNull Repository repository, @NonNull byte[] hostKey)
throws IOException, GeneralSecurityException {
+ this(testUser, readPublicKey(testKey), repository,
+ readKeyPair(hostKey));
+ }
+
+ /**
+ * Creates a ssh git <em>test</em> server. It serves one single repository,
+ * and accepts public-key authentication for exactly one test user.
+ *
+ * @param testUser
+ * user name of the test user
+ * @param testKey
+ * public key file of the test user
+ * @param repository
+ * to serve
+ * @param hostKey
+ * the unencrypted private key to use as host key
+ * @throws IOException
+ * @throws GeneralSecurityException
+ * @since 5.9
+ */
+ public SshTestGitServer(@NonNull String testUser, @NonNull Path testKey,
+ @NonNull Repository repository, @NonNull KeyPair hostKey)
+ throws IOException, GeneralSecurityException {
+ this(testUser, readPublicKey(testKey), repository, hostKey);
+ }
+
+ /**
+ * Creates a ssh git <em>test</em> server. It serves one single repository,
+ * and accepts public-key authentication for exactly one test user.
+ *
+ * @param testUser
+ * user name of the test user
+ * @param testKey
+ * the {@link PublicKey} of the test user
+ * @param repository
+ * to serve
+ * @param hostKey
+ * the {@link KeyPair} to use as host key
+ * @since 5.9
+ */
+ public SshTestGitServer(@NonNull String testUser,
+ @NonNull PublicKey testKey, @NonNull Repository repository,
+ @NonNull KeyPair hostKey) {
this.testUser = testUser;
setTestUserPublicKey(testKey);
this.repository = repository;
server = SshServer.setUpDefaultServer();
- // Set host key
- try (ByteArrayInputStream in = new ByteArrayInputStream(hostKey)) {
- SecurityUtils.loadKeyPairIdentities(null, null, in, null)
- .forEach((k) -> hostKeys.add(k));
- } catch (IOException | GeneralSecurityException e) {
- // Ignore.
- }
+ hostKeys.add(hostKey);
server.setKeyPairProvider((session) -> hostKeys);
configureAuthentication();
@@ -129,11 +179,27 @@ public class SshTestGitServer {
return new GitUploadPackCommand(command, executorService);
} else if (command.startsWith(RemoteConfig.DEFAULT_RECEIVE_PACK)) {
return new GitReceivePackCommand(command, executorService);
+ } else if (command.startsWith(ECHO_COMMAND)) {
+ return new EchoCommand(command, executorService);
}
return new UnknownCommand(command);
});
}
+ private static PublicKey readPublicKey(Path key)
+ throws IOException, GeneralSecurityException {
+ return AuthorizedKeyEntry.readAuthorizedKeys(key).get(0)
+ .resolvePublicKey(null, PublicKeyEntryResolver.IGNORING);
+ }
+
+ private static KeyPair readKeyPair(byte[] keyMaterial)
+ throws IOException, GeneralSecurityException {
+ try (ByteArrayInputStream in = new ByteArrayInputStream(keyMaterial)) {
+ return SecurityUtils.loadKeyPairIdentities(null, null, in, null)
+ .iterator().next();
+ }
+ }
+
private static class FakeUserAuthGSS extends UserAuthGSS {
@Override
protected Boolean doAuth(Buffer buffer, boolean initial)
@@ -298,6 +364,17 @@ public class SshTestGitServer {
}
/**
+ * Retrieves the server's {@link PropertyResolver}, giving access to server
+ * properties.
+ *
+ * @return the {@link PropertyResolver}
+ * @since 5.9
+ */
+ public PropertyResolver getPropertyResolver() {
+ return server;
+ }
+
+ /**
* Starts the test server, listening on a random port.
*
* @return the port the server listens on; test clients should connect to
@@ -331,8 +408,7 @@ public class SshTestGitServer {
*/
public void setTestUserPublicKey(Path key)
throws IOException, GeneralSecurityException {
- this.testKey = AuthorizedKeyEntry.readAuthorizedKeys(key).get(0)
- .resolvePublicKey(null, PublicKeyEntryResolver.IGNORING);
+ this.testKey = readPublicKey(key);
}
/**
@@ -414,4 +490,52 @@ public class SshTestGitServer {
}
}
+
+ /**
+ * Simple echo command that echoes back the command string. If the first
+ * argument is a positive integer, it's taken as a delay (in seconds) before
+ * replying. Assumes UTF-8 character encoding.
+ */
+ private static class EchoCommand extends AbstractCommandSupport {
+
+ protected EchoCommand(String command,
+ CloseableExecutorService executorService) {
+ super(command, ThreadUtils.noClose(executorService));
+ }
+
+ @Override
+ public void run() {
+ String[] parts = getCommand().split(" ");
+ int timeout = 0;
+ if (parts.length >= 2) {
+ try {
+ timeout = Integer.parseInt(parts[1]);
+ } catch (NumberFormatException e) {
+ // No timeout.
+ }
+ if (timeout > 0) {
+ try {
+ Thread.sleep(TimeUnit.SECONDS.toMillis(timeout));
+ } catch (InterruptedException e) {
+ // Ignore.
+ }
+ }
+ }
+ try {
+ doEcho(getCommand(), getOutputStream());
+ onExit(0);
+ } catch (IOException e) {
+ log.warn(
+ MessageFormat.format("Could not run {0}", getCommand()),
+ e);
+ onExit(-1, e.toString());
+ }
+ }
+
+ private void doEcho(String text, OutputStream stream)
+ throws IOException {
+ stream.write(text.getBytes(StandardCharsets.UTF_8));
+ stream.flush();
+ }
+ }
}
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
index 43f9dc4b24..90d981b772 100644
--- 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
@@ -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
@@ -9,27 +9,31 @@
*/
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.BufferedWriter;
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;
import java.nio.file.Files;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PrivateKey;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Base64;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import org.apache.sshd.common.config.keys.PublicKeyEntry;
import org.eclipse.jgit.api.CloneCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.PushCommand;
@@ -48,9 +52,6 @@ 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
@@ -75,6 +76,8 @@ public abstract class SshTestHarness extends RepositoryTestCase {
protected File publicKey1;
+ protected File publicKey2;
+
protected SshTestGitServer server;
private SshSessionFactory factory;
@@ -104,50 +107,71 @@ public abstract class SshTestHarness extends RepositoryTestCase {
File serverDir = new File(getTemporaryDirectory(), "srv");
assertTrue(serverDir.mkdir());
// Create two key pairs. Let's not call them "id_rsa".
+ KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
+ generator.initialize(2048);
privateKey1 = new File(sshDir, "first_key");
privateKey2 = new File(sshDir, "second_key");
- publicKey1 = createKeyPair(privateKey1);
- createKeyPair(privateKey2);
- ByteArrayOutputStream publicHostKey = new ByteArrayOutputStream();
+ publicKey1 = createKeyPair(generator.generateKeyPair(), privateKey1);
+ publicKey2 = createKeyPair(generator.generateKeyPair(), privateKey2);
+ // Create a host key
+ KeyPair hostKey = generator.generateKeyPair();
// Start a server with our test user and the first key.
server = new SshTestGitServer(TEST_USER, publicKey1.toPath(), db,
- createHostKey(publicHostKey));
+ hostKey);
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())));
+ StringBuilder knownHostsLine = new StringBuilder();
+ knownHostsLine.append("[localhost]:").append(testPort).append(' ');
+ PublicKeyEntry.appendPublicKeyEntry(knownHostsLine,
+ hostKey.getPublic());
+ Files.write(knownHosts.toPath(),
+ Collections.singleton(knownHostsLine.toString()));
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);
+ private static File createKeyPair(KeyPair newKey, File privateKeyFile)
+ throws Exception {
+ // Write PKCS#8 PEM unencrypted. Both JSch and sshd can read that.
+ PrivateKey privateKey = newKey.getPrivate();
+ String format = privateKey.getFormat();
+ if (!"PKCS#8".equalsIgnoreCase(format)) {
+ throw new IOException("Cannot write " + privateKey.getAlgorithm()
+ + " key in " + format + " format");
+ }
+ try (BufferedWriter writer = Files.newBufferedWriter(
+ privateKeyFile.toPath(), StandardCharsets.US_ASCII)) {
+ writer.write("-----BEGIN PRIVATE KEY-----");
+ writer.newLine();
+ write(writer, privateKey.getEncoded(), 64);
+ writer.write("-----END PRIVATE KEY-----");
+ writer.newLine();
}
File publicKeyFile = new File(privateKeyFile.getParentFile(),
privateKeyFile.getName() + ".pub");
+ StringBuilder builder = new StringBuilder();
+ PublicKeyEntry.appendPublicKeyEntry(builder, newKey.getPublic());
+ builder.append(' ').append(TEST_USER);
try (OutputStream out = new FileOutputStream(publicKeyFile)) {
- pair.writePublicKey(out, TEST_USER);
+ out.write(builder.toString().getBytes(StandardCharsets.US_ASCII));
}
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();
+ private static void write(BufferedWriter out, byte[] bytes, int lineLength)
+ throws IOException {
+ String data = Base64.getEncoder().encodeToString(bytes);
+ int last = data.length();
+ for (int i = 0; i < last; i += lineLength) {
+ if (i + lineLength <= last) {
+ out.write(data.substring(i, i + lineLength));
+ } else {
+ out.write(data.substring(i));
+ }
+ out.newLine();
}
+ Arrays.fill(bytes, (byte) 0);
}
/**
@@ -167,7 +191,8 @@ public abstract class SshTestHarness extends RepositoryTestCase {
*/
protected static String createKnownHostsFile(File file, String host,
int port, File publicKey) throws IOException {
- List<String> lines = Files.readAllLines(publicKey.toPath(), UTF_8);
+ List<String> 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.