This is an automated email from the ASF dual-hosted git repository.

tomaswolf pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git

commit a0ef7a567a97c94206378d9e8f8ea0b072bef947
Author: Thomas Wolf <[email protected]>
AuthorDate: Fri Apr 17 23:40:02 2026 +0200

    Host certificates: check both public keys for not being revoked
    
    It could be that the certificate is perfectly valid, but the
    certified host key is listed itself as being revoked.
---
 .../keyverifier/KnownHostsServerKeyVerifier.java    | 15 ++++++++++++++-
 .../common/signature/KnownHostsCertificateTest.java | 21 +++++++++++++++++++++
 2 files changed, 35 insertions(+), 1 deletion(-)

diff --git 
a/sshd-core/src/main/java/org/apache/sshd/client/keyverifier/KnownHostsServerKeyVerifier.java
 
b/sshd-core/src/main/java/org/apache/sshd/client/keyverifier/KnownHostsServerKeyVerifier.java
index 10d97b1d6..414979330 100644
--- 
a/sshd-core/src/main/java/org/apache/sshd/client/keyverifier/KnownHostsServerKeyVerifier.java
+++ 
b/sshd-core/src/main/java/org/apache/sshd/client/keyverifier/KnownHostsServerKeyVerifier.java
@@ -298,6 +298,18 @@ public class KnownHostsServerKeyVerifier
                 .filter(e -> isCert == 
"cert-authority".equals(e.getHostEntry().getMarker()))
                 .collect(Collectors.toList());
         if (!keyMatches.isEmpty()) {
+            if (serverKey instanceof OpenSshCertificate) {
+                // Also check whether the certified key has been revoked.
+                PublicKey certifiedKey = ((OpenSshCertificate) 
serverKey).getCertPubKey();
+                String certKeyType = KeyUtils.getKeyType(certifiedKey);
+                if (hostMatches.stream() //
+                        .filter(entry -> 
certKeyType.equals(entry.getHostEntry().getKeyEntry().getKeyType()))
+                        .filter(k -> KeyUtils.compareKeys(k.getServerKey(), 
certifiedKey))
+                        .anyMatch(entry -> 
"revoked".equals(entry.getHostEntry().getMarker()))) {
+                    handleRevokedKey(clientSession, remoteAddress, 
certifiedKey);
+                    return false;
+                }
+            }
             return true;
         }
 
@@ -306,7 +318,8 @@ public class KnownHostsServerKeyVerifier
         }
 
         Optional<HostEntryPair> anyNonRevokedMatch = hostMatches.stream()
-                .filter(k -> !"revoked".equals(k.getHostEntry().getMarker()))
+                .filter(k -> !"revoked".equals(k.getHostEntry().getMarker())
+                        && 
!"cert-authority".equals(k.getHostEntry().getMarker()))
                 .findAny();
 
         if (!anyNonRevokedMatch.isPresent()) {
diff --git 
a/sshd-core/src/test/java/org/apache/sshd/common/signature/KnownHostsCertificateTest.java
 
b/sshd-core/src/test/java/org/apache/sshd/common/signature/KnownHostsCertificateTest.java
index 9e0b6a5db..d6b47a407 100644
--- 
a/sshd-core/src/test/java/org/apache/sshd/common/signature/KnownHostsCertificateTest.java
+++ 
b/sshd-core/src/test/java/org/apache/sshd/common/signature/KnownHostsCertificateTest.java
@@ -20,6 +20,7 @@ package org.apache.sshd.common.signature;
 
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
 import java.security.KeyPair;
 import java.util.Arrays;
 import java.util.Collections;
@@ -199,4 +200,24 @@ class KnownHostsCertificateTest extends BaseTestSupport {
             s.auth().verify(AUTH_TIMEOUT);
         }
     }
+
+    @Test
+    void testHostCertificateWithRejectedHostKeyFails() throws Exception {
+        initKeys(KeyUtils.EC_ALGORITHM, 256, KeyUtils.EC_ALGORITHM, 256, 
"ecdsa-sha2-nistp256", "cert-authority");
+        Path knownHosts = tmp.resolve("known_hosts");
+        StringBuilder line = new StringBuilder();
+        line.append("@revoked ");
+        
line.append("[localhost]:").append(port).append(",[127.0.0.1]:").append(port).append('
 ');
+        line.append(PublicKeyEntry.toString(hostKey.getPublic()));
+        line.append('\n');
+        Files.write(knownHosts, Collections.singletonList(line.toString()), 
StandardOpenOption.APPEND);
+        client.setServerKeyVerifier(new 
KnownHostsServerKeyVerifier(AcceptAllServerKeyVerifier.INSTANCE, knownHosts));
+        assertThrows(SshException.class, () -> {
+            try (ClientSession s = client.connect(getCurrentTestName(), 
TEST_LOCALHOST, port).verify(CONNECT_TIMEOUT)
+                    .getSession()) {
+                s.addPasswordIdentity(getCurrentTestName());
+                s.auth().verify(AUTH_TIMEOUT);
+            }
+        });
+    }
 }

Reply via email to