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);