summaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit.ssh.apache.test/tst
diff options
context:
space:
mode:
authorThomas Wolf <thomas.wolf@paranor.ch>2022-04-01 16:56:05 +0200
committerThomas Wolf <thomas.wolf@paranor.ch>2022-05-01 08:48:44 +0200
commit4dd9a94ec532aa2512dc220ab9d2f4929264c741 (patch)
tree308e89a844e2caf4757ba53b2682bb94221cdf8e /org.eclipse.jgit.ssh.apache.test/tst
parent8b8999dca8d71b976da94715e06162510bb51460 (diff)
downloadjgit-4dd9a94ec532aa2512dc220ab9d2f4929264c741.tar.gz
jgit-4dd9a94ec532aa2512dc220ab9d2f4929264c741.zip
[sshd] Better user feedback on authentication failure
When authentication fails, JGit produces an exception with an error message telling the user that it could not log in (including the host name). The causal chain has an SshException from Apache MINA sshd with message "No more authentication methods available". This is not very helpful. The user was left without any indication why authentication failed. Include in the exception message a log of all attempted authentications. That way, the user can see which keys were tried, in which order and with which signature algorithms. The log also reports authentication attempts for gssapi-with-mic or password authentication. For keyboard-interactive Apache MINA sshd is lacking a callback interface. The way Apache MINA sshd loads keys from files, the file names are lost in higher layers. Add a mechanism to record on the session for each key fingerprint the file it was loaded from, if any. That way the exception message can refer to keys by file name, which is easier to understand by users than the rather cryptic key fingerprints. Bug: 571390 Change-Id: Ic4b6ce6b99f307d5e798fcc91b16b9ffd995d224 Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
Diffstat (limited to 'org.eclipse.jgit.ssh.apache.test/tst')
-rw-r--r--org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/transport/sshd/ApacheSshTest.java74
1 files changed, 73 insertions, 1 deletions
diff --git a/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/transport/sshd/ApacheSshTest.java b/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/transport/sshd/ApacheSshTest.java
index 3d7c7651c1..a8fcca7b8e 100644
--- a/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/transport/sshd/ApacheSshTest.java
+++ b/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/transport/sshd/ApacheSshTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018, 2020 Thomas Wolf <thomas.wolf@paranor.ch> and others
+ * Copyright (C) 2018, 2022 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
@@ -789,4 +789,76 @@ public class ApacheSshTest extends SshTestBase {
session.disconnect();
}
}
+
+ private void verifyAuthLog(String message, String first) {
+ assertTrue(message.contains(System.lineSeparator()));
+ String[] lines = message.split(System.lineSeparator());
+ int pubkeyIndex = -1;
+ int passwordIndex = -1;
+ for (int i = 0; i < lines.length; i++) {
+ String line = lines[i];
+ if (i == 0) {
+ assertTrue(line.contains(first));
+ }
+ if (line.contains("publickey:")) {
+ if (pubkeyIndex < 0) {
+ pubkeyIndex = i;
+ assertTrue(line.contains("/userkey"));
+ }
+ } else if (line.contains("password:")) {
+ if (passwordIndex < 0) {
+ passwordIndex = i;
+ assertTrue(line.contains("attempt 1"));
+ }
+ }
+ }
+ assertTrue(pubkeyIndex > 0 && passwordIndex > 0);
+ assertTrue(pubkeyIndex < passwordIndex);
+ }
+
+ @Test
+ public void testAuthFailureMessageCancel() throws Exception {
+ File userKey = new File(getTemporaryDirectory(), "userkey");
+ copyTestResource("id_ed25519", userKey);
+ File publicKey = new File(getTemporaryDirectory(), "userkey.pub");
+ copyTestResource("id_ed25519.pub", publicKey);
+ // Don't set this as the user's key; we do want to try with a wrong key.
+ server.enablePasswordAuthentication();
+ TestCredentialsProvider provider = new TestCredentialsProvider(
+ "wrongpass");
+ TransportException e = assertThrows(TransportException.class,
+ () -> cloneWith("ssh://git/doesntmatter", defaultCloneDir,
+ provider, //
+ "Host git", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + userKey.getAbsolutePath(), //
+ "PreferredAuthentications publickey,password"));
+ verifyAuthLog(e.getMessage(), "canceled");
+ }
+
+ @Test
+ public void testAuthFailureMessage() throws Exception {
+ File userKey = new File(getTemporaryDirectory(), "userkey");
+ copyTestResource("id_ed25519", userKey);
+ File publicKey = new File(getTemporaryDirectory(), "userkey.pub");
+ copyTestResource("id_ed25519.pub", publicKey);
+ // Don't set this as the user's key; we do want to try with a wrong key.
+ server.enablePasswordAuthentication();
+ // Enough passwords not to cancel authentication
+ TestCredentialsProvider provider = new TestCredentialsProvider(
+ "wrongpass", "wrongpass", "wrongpass");
+ TransportException e = assertThrows(TransportException.class,
+ () -> cloneWith("ssh://git/doesntmatter", defaultCloneDir,
+ provider, //
+ "Host git", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + userKey.getAbsolutePath(), //
+ "PreferredAuthentications publickey,password"));
+ verifyAuthLog(e.getMessage(), "log in");
+ }
+
}