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

coheigea pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ws-wss4j.git


The following commit(s) were added to refs/heads/master by this push:
     new d6323f3e8 Set trust when there is no KeyInfo and the certificate comes 
from a local keystore (#708)
d6323f3e8 is described below

commit d6323f3e82738d91a687d8abc47e79c946a6d682
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Fri Sep 18 12:10:29 2026 +0100

    Set trust when there is no KeyInfo and the certificate comes from a local 
keystore (#708)
---
 .../wss4j/dom/processor/SignatureProcessor.java    |  7 ++++
 .../apache/wss4j/dom/message/SignatureTest.java    | 42 ++++++++++++++++++++++
 2 files changed, 49 insertions(+)

diff --git 
a/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/SignatureProcessor.java
 
b/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/SignatureProcessor.java
index 9a2a43778..8db6097e7 100644
--- 
a/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/SignatureProcessor.java
+++ 
b/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/SignatureProcessor.java
@@ -145,6 +145,13 @@ public class SignatureProcessor implements Processor {
         if (keyInfoElement == null) {
             certs = getDefaultCerts(data.getSigVerCrypto());
             principal = certs[0].getSubjectX500Principal();
+            // The message carries no KeyInfo, so the signing certificate was 
not supplied by the
+            // sender: it was taken from the receiver's own signature 
verification keystore, under
+            // its configured default alias. The credential is therefore 
trusted by construction
+            // and there is nothing here for a Validator to decide - an 
attacker cannot influence
+            // which certificate the signature is verified against. Verifying 
the signature against
+            // it does establish the sender's identity, so the result may be 
stamped as validated.
+            trustEstablished = true;
         } else {
             int result = 0;
             Node node = keyInfoElement.getFirstChild();
diff --git 
a/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/SignatureTest.java 
b/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/SignatureTest.java
index 3b276ea0e..074a19dee 100644
--- 
a/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/SignatureTest.java
+++ 
b/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/SignatureTest.java
@@ -127,6 +127,48 @@ public class SignatureTest {
             "An X.509 signature that passed trust validation must be reported 
as validated");
     }
 
+    /**
+     * A Signature with no KeyInfo at all. The signing certificate is then not 
supplied by the
+     * sender, but taken from the receiver's own signature verification 
keystore under its
+     * configured default alias, so an attacker cannot influence which 
certificate the signature
+     * is verified against. That credential is trusted by construction and the 
result must be
+     * reported as validated - otherwise a consumer keying off 
TAG_VALIDATED_TOKEN treats a
+     * signature by the operator's own configured identity as untrusted.
+     */
+    @Test
+    public void testX509SignatureNoKeyInfo() throws Exception {
+        Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+        WSSecHeader secHeader = new WSSecHeader(doc);
+        secHeader.insertSecurityHeader();
+
+        WSSecSignature builder = new WSSecSignature(secHeader);
+        builder.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", 
"security");
+        Document signedDoc = builder.build(crypto);
+
+        // Strip the KeyInfo. It is not referenced by the SignedInfo, so the 
signature still
+        // verifies, and the receiver falls back to the default certificate of 
its own keystore -
+        // which crypto.properties configures to the certificate used above.
+        Element signature =
+            XMLUtils.findElement(signedDoc.getDocumentElement(), "Signature", 
WSConstants.SIG_NS);
+        assertNotNull(signature);
+        Element keyInfo = XMLUtils.getDirectChildElement(signature, "KeyInfo", 
WSConstants.SIG_NS);
+        assertNotNull(keyInfo);
+        signature.removeChild(keyInfo);
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug(XMLUtils.prettyDocumentToString(signedDoc));
+        }
+
+        WSHandlerResult results = verify(signedDoc);
+
+        WSSecurityEngineResult actionResult =
+            results.getActionResults().get(WSConstants.SIGN).get(0);
+        
assertNotNull(actionResult.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE));
+        
assertTrue((Boolean)actionResult.get(WSSecurityEngineResult.TAG_VALIDATED_TOKEN),
+            "A signature verified against the receiver's own default 
certificate must be "
+            + "reported as validated");
+    }
+
     @Test
     public void testX509SignatureISAttached() throws Exception {
         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);

Reply via email to