Skip to content

Commit 3483bd7

Browse files
msohngerritforge-ltd
authored andcommitted
Merge "[ssh known_hosts] Handle unknown keys better"
2 parents 9ad4310 + 3edab4e commit 3483bd7

File tree

2 files changed

+62
-20
lines changed

2 files changed

+62
-20
lines changed

org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyDatabaseTest.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,29 @@ public void testAddNewKey3() throws Exception {
478478
new KnownHostsConfig(), null));
479479
}
480480

481+
@Test
482+
public void testUnknownKeyType() throws Exception {
483+
List<String> initialKnownHosts = List.of(
484+
"localhost,127.0.0.1 " + PublicKeyEntry.toString(ec384)
485+
.replace("ecdsa", "foo"),
486+
"some.other.com " + PublicKeyEntry.toString(ec384));
487+
Files.write(knownHosts, initialKnownHosts);
488+
TestCredentialsProvider ui = new TestCredentialsProvider(true, true);
489+
assertTrue(database.accept("localhost", LOCAL, ec384,
490+
new KnownHostsConfig(
491+
ServerKeyDatabase.Configuration.StrictHostKeyChecking.ASK),
492+
ui));
493+
assertEquals(1, ui.invocations);
494+
// The "modified key" dialog has two questions; whereas the "add new
495+
// key" is just a simple question.
496+
assertEquals(2, ui.questions);
497+
List<String> expected = new ArrayList<>(initialKnownHosts);
498+
expected.add("localhost,127.0.0.1 " + PublicKeyEntry.toString(ec384));
499+
assertFile(knownHosts, expected);
500+
assertTrue(database.accept("127.0.0.1:22", LOCAL, ec384,
501+
new KnownHostsConfig(), null));
502+
}
503+
481504
private void assertFile(Path path, List<String> lines) throws Exception {
482505
assertEquals(lines, Files.readAllLines(path).stream()
483506
.filter(s -> !s.isBlank()).toList());
@@ -489,6 +512,8 @@ private static class TestCredentialsProvider extends CredentialsProvider {
489512

490513
int invocations = 0;
491514

515+
int questions = 0;
516+
492517
TestCredentialsProvider(boolean accept, boolean store) {
493518
values = new boolean[] { accept, store };
494519
}
@@ -512,6 +537,7 @@ public boolean get(URIish uri, CredentialItem... items)
512537
if (item instanceof CredentialItem.YesNoType) {
513538
((CredentialItem.YesNoType) item)
514539
.setValue(i < values.length && values[i++]);
540+
questions++;
515541
}
516542
}
517543
return true;

org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyDatabase.java

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
import org.apache.sshd.common.config.keys.OpenSshCertificate;
5454
import org.apache.sshd.common.config.keys.PublicKeyEntry;
5555
import org.apache.sshd.common.config.keys.PublicKeyEntryResolver;
56+
import org.apache.sshd.common.config.keys.UnsupportedSshPublicKey;
5657
import org.apache.sshd.common.digest.BuiltinDigests;
5758
import org.apache.sshd.common.mac.Mac;
5859
import org.apache.sshd.common.util.io.ModifiableFileWatcher;
@@ -185,6 +186,9 @@ public List<PublicKey> lookup(@NonNull String connectAddress,
185186
for (HostKeyFile file : filesToUse) {
186187
for (HostEntryPair current : file.get()) {
187188
KnownHostEntry entry = current.getHostEntry();
189+
if (current.getServerKey() instanceof UnsupportedSshPublicKey) {
190+
continue;
191+
}
188192
if (!isRevoked(entry) && !isCertificateAuthority(entry)) {
189193
for (SshdSocketAddress host : candidates) {
190194
if (entry.isHostMatch(host.getHostName(),
@@ -235,12 +239,20 @@ public boolean accept(@NonNull String connectAddress,
235239
remoteAddress, modified[0].getServerKey(),
236240
serverKey, path);
237241
if (toDo == AskUser.ModifiedKeyHandling.ALLOW_AND_STORE) {
238-
try {
239-
updateModifiedServerKey(serverKey, modified[0], path);
240-
knownHostsFiles.get(path).resetReloadAttributes();
241-
} catch (IOException e) {
242-
LOG.warn(format(SshdText.get().knownHostsCouldNotUpdate,
243-
path));
242+
if (modified[0]
243+
.getServerKey() instanceof UnsupportedSshPublicKey) {
244+
// Never update a line containing an unknown key type,
245+
// always add.
246+
addKeyToFile(filesToUse.get(0), candidates, serverKey, ask,
247+
config);
248+
} else {
249+
try {
250+
updateModifiedServerKey(serverKey, modified[0], path);
251+
knownHostsFiles.get(path).resetReloadAttributes();
252+
} catch (IOException e) {
253+
LOG.warn(format(SshdText.get().knownHostsCouldNotUpdate,
254+
path));
255+
}
244256
}
245257
}
246258
if (toDo == AskUser.ModifiedKeyHandling.DENY) {
@@ -253,19 +265,8 @@ public boolean accept(@NonNull String connectAddress,
253265
return true;
254266
} else if (ask.acceptUnknownKey(remoteAddress, serverKey)) {
255267
if (!filesToUse.isEmpty()) {
256-
HostKeyFile toUpdate = filesToUse.get(0);
257-
path = toUpdate.getPath();
258-
try {
259-
if (Files.exists(path) || !askAboutNewFile
260-
|| ask.createNewFile(path)) {
261-
updateKnownHostsFile(candidates, serverKey, path,
262-
config);
263-
toUpdate.resetReloadAttributes();
264-
}
265-
} catch (Exception e) {
266-
LOG.warn(format(SshdText.get().knownHostsCouldNotUpdate,
267-
path), e);
268-
}
268+
addKeyToFile(filesToUse.get(0), candidates, serverKey, ask,
269+
config);
269270
}
270271
return true;
271272
}
@@ -379,6 +380,21 @@ private List<HostKeyFile> addUserHostKeyFiles(List<String> fileNames) {
379380
return userFiles;
380381
}
381382

383+
private void addKeyToFile(HostKeyFile file,
384+
Collection<SshdSocketAddress> candidates, PublicKey serverKey,
385+
AskUser ask, Configuration config) {
386+
Path path = file.getPath();
387+
try {
388+
if (Files.exists(path) || !askAboutNewFile
389+
|| ask.createNewFile(path)) {
390+
updateKnownHostsFile(candidates, serverKey, path, config);
391+
file.resetReloadAttributes();
392+
}
393+
} catch (Exception e) {
394+
LOG.warn(format(SshdText.get().knownHostsCouldNotUpdate, path), e);
395+
}
396+
}
397+
382398
private void updateKnownHostsFile(Collection<SshdSocketAddress> candidates,
383399
PublicKey serverKey, Path path, Configuration config)
384400
throws Exception {
@@ -663,7 +679,7 @@ private List<HostEntryPair> reload(Path path) throws IOException {
663679
}
664680
try {
665681
PublicKey serverKey = keyPart.resolvePublicKey(null,
666-
PublicKeyEntryResolver.IGNORING);
682+
PublicKeyEntryResolver.UNSUPPORTED);
667683
if (serverKey == null) {
668684
LOG.warn(format(
669685
SshdText.get().knownHostsUnknownKeyType,

0 commit comments

Comments
 (0)