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

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


The following commit(s) were added to refs/heads/2_4_x-fixes by this push:
     new 6bef3423c Fix timestamp parsing (#722)
6bef3423c is described below

commit 6bef3423c61ff42ff356f52b84218283ac7d02c8
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Mon Sep 21 12:52:49 2026 +0100

    Fix timestamp parsing (#722)
---
 .../apache/wss4j/dom/message/token/Timestamp.java  | 22 +++++++-
 .../apache/wss4j/dom/message/TimestampTest.java    | 65 ++++++++++++++++++++++
 2 files changed, 84 insertions(+), 3 deletions(-)

diff --git 
a/ws-security-dom/src/main/java/org/apache/wss4j/dom/message/token/Timestamp.java
 
b/ws-security-dom/src/main/java/org/apache/wss4j/dom/message/token/Timestamp.java
index e99153cdf..76b1a7ff9 100644
--- 
a/ws-security-dom/src/main/java/org/apache/wss4j/dom/message/token/Timestamp.java
+++ 
b/ws-security-dom/src/main/java/org/apache/wss4j/dom/message/token/Timestamp.java
@@ -38,7 +38,6 @@ import org.apache.wss4j.dom.WSConstants;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
-import org.w3c.dom.Text;
 
 /**
  * Timestamp according to SOAP Message Security 1.0,
@@ -79,7 +78,7 @@ public class Timestamp {
                             // We can't have a ValueType attribute as per the 
BSP spec
                             bspEnforcer.handleBSPRule(BSPRule.R3225);
                         }
-                        createdString = 
((Text)currentChildElement.getFirstChild()).getData();
+                        createdString = getRequiredText(currentChildElement);
                     } else {
                         // Test for multiple Created elements
                         bspEnforcer.handleBSPRule(BSPRule.R3203);
@@ -99,7 +98,7 @@ public class Timestamp {
                             // We can't have a ValueType attribute as per the 
BSP spec
                             bspEnforcer.handleBSPRule(BSPRule.R3226);
                         }
-                        strExpires = 
((Text)currentChildElement.getFirstChild()).getData();
+                        strExpires = getRequiredText(currentChildElement);
                     }
                 } else {
                     bspEnforcer.handleBSPRule(BSPRule.R3222);
@@ -155,6 +154,23 @@ public class Timestamp {
     }
 
 
+    /**
+     * Return the text content of a Created / Expires element. The element's 
first child is not
+     * necessarily a Text node - it may be absent, or be a comment - and 
reading it as one turned
+     * wire-supplied content into an unchecked exception rather than an 
INVALID_SECURITY fault.
+     */
+    private static String getRequiredText(Element element) throws 
WSSecurityException {
+        String text = XMLUtils.getElementText(element);
+        if (text == null) {
+            throw new WSSecurityException(
+                WSSecurityException.ErrorCode.INVALID_SECURITY,
+                "invalidTimestamp",
+                new Object[] {"The " + element.getLocalName() + " element has 
no text content"}
+            );
+        }
+        return text;
+    }
+
     /**
      * Constructs a <code>Timestamp</code> object according
      * to the defined parameters.
diff --git 
a/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/TimestampTest.java 
b/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/TimestampTest.java
index 1994b2778..09a5adda2 100644
--- 
a/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/TimestampTest.java
+++ 
b/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/TimestampTest.java
@@ -459,6 +459,71 @@ public class TimestampTest {
         verify(doc, Collections.singletonList(BSPRule.R3203));
     }
 
+    /**
+     * A "Created" element with no text content of its own must be rejected as 
an invalid
+     * Timestamp, not read as though its first child were a Text node.
+     */
+    @Test
+    public void testEmptyCreated() throws Exception {
+        Document doc = createTimestampWithCreatedContent(null);
+
+        try {
+            verify(doc);
+            fail("The timestamp validation should have failed on an empty 
Created element");
+        } catch (WSSecurityException ex) {
+            assertTrue(ex.getErrorCode() == 
WSSecurityException.ErrorCode.INVALID_SECURITY);
+        }
+    }
+
+    /**
+     * The first child of a "Created" element need not be a Text node - here 
it is a comment,
+     * which c14n excludes from the signed bytes in any case.
+     */
+    @Test
+    public void testCreatedWithLeadingComment() throws Exception {
+        ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
+        Document doc =
+            
createTimestampWithCreatedContent(DateUtil.getDateTimeFormatter(true).format(now),
 true);
+
+        verify(doc);
+    }
+
+    private Document createTimestampWithCreatedContent(String createdText) 
throws Exception {
+        return createTimestampWithCreatedContent(createdText, false);
+    }
+
+    private Document createTimestampWithCreatedContent(
+        String createdText, boolean leadingComment
+    ) throws Exception {
+        Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+        WSSecHeader secHeader = new WSSecHeader(doc);
+        secHeader.insertSecurityHeader();
+
+        Element timestampElement =
+            doc.createElementNS(
+                WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + 
WSConstants.TIMESTAMP_TOKEN_LN
+            );
+
+        Element elementCreated =
+            doc.createElementNS(
+                WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + 
WSConstants.CREATED_LN
+            );
+        if (leadingComment) {
+            elementCreated.appendChild(doc.createComment("a comment"));
+        }
+        if (createdText != null) {
+            elementCreated.appendChild(doc.createTextNode(createdText));
+        }
+        timestampElement.appendChild(elementCreated);
+
+        secHeader.getSecurityHeaderElement().appendChild(timestampElement);
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug(XMLUtils.prettyDocumentToString(doc));
+        }
+        return doc;
+    }
+
     /**
      * This is a test for processing an Timestamp where it contains no 
"Created" element.
      * This Timestamp should be rejected.

Reply via email to