You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@santuario.apache.org by co...@apache.org on 2020/02/14 16:52:47 UTC

svn commit: r1874026 - in /santuario/xml-security-java/branches/2.1.x-fixes: ./ src/main/java/org/apache/xml/security/stax/impl/ src/test/java/org/apache/xml/security/test/stax/ src/test/java/org/apache/xml/security/test/stax/utils/

Author: coheigea
Date: Fri Feb 14 16:52:46 2020
New Revision: 1874026

URL: http://svn.apache.org/viewvc?rev=1874026&view=rev
Log:
SANTUARIO--523 XMLSecurityStreamReader now correctly reads info from XML declara
tion. Thanks to Peter De Maeyer for the patch.

Modified:
    santuario/xml-security-java/branches/2.1.x-fixes/pom.xml
    santuario/xml-security-java/branches/2.1.x-fixes/src/main/java/org/apache/xml/security/stax/impl/XMLSecurityStreamReader.java
    santuario/xml-security-java/branches/2.1.x-fixes/src/test/java/org/apache/xml/security/test/stax/XMLSecurityStreamReaderTest.java
    santuario/xml-security-java/branches/2.1.x-fixes/src/test/java/org/apache/xml/security/test/stax/utils/XmlReaderToWriter.java

Modified: santuario/xml-security-java/branches/2.1.x-fixes/pom.xml
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/branches/2.1.x-fixes/pom.xml?rev=1874026&r1=1874025&r2=1874026&view=diff
==============================================================================
--- santuario/xml-security-java/branches/2.1.x-fixes/pom.xml (original)
+++ santuario/xml-security-java/branches/2.1.x-fixes/pom.xml Fri Feb 14 16:52:46 2020
@@ -531,6 +531,7 @@
         <junit.version>4.12</junit.version>
         <log4j.version>1.2.17</log4j.version>
         <bcprov.version>1.64</bcprov.version>
+        <hamcrest.version>2.2</hamcrest.version>
         <xmlunit.version>1.6</xmlunit.version>
         <commons.codec.version>1.13</commons.codec.version>
         <woodstox.core.version>5.0.3</woodstox.core.version>
@@ -582,6 +583,12 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest</artifactId>
+            <version>${hamcrest.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>org.eclipse.jetty</groupId>
             <artifactId>jetty-server</artifactId>
             <version>${jetty.version}</version>

Modified: santuario/xml-security-java/branches/2.1.x-fixes/src/main/java/org/apache/xml/security/stax/impl/XMLSecurityStreamReader.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/branches/2.1.x-fixes/src/main/java/org/apache/xml/security/stax/impl/XMLSecurityStreamReader.java?rev=1874026&r1=1874025&r2=1874026&view=diff
==============================================================================
--- santuario/xml-security-java/branches/2.1.x-fixes/src/main/java/org/apache/xml/security/stax/impl/XMLSecurityStreamReader.java (original)
+++ santuario/xml-security-java/branches/2.1.x-fixes/src/main/java/org/apache/xml/security/stax/impl/XMLSecurityStreamReader.java Fri Feb 14 16:52:46 2020
@@ -33,6 +33,7 @@ import javax.xml.stream.events.DTD;
 import javax.xml.stream.events.EntityReference;
 import javax.xml.stream.events.Namespace;
 import javax.xml.stream.events.ProcessingInstruction;
+import javax.xml.stream.events.StartDocument;
 
 import org.apache.xml.security.exceptions.XMLSecurityException;
 import org.apache.xml.security.stax.ext.InputProcessorChain;
@@ -49,7 +50,11 @@ public class XMLSecurityStreamReader imp
 
     private final InputProcessorChain inputProcessorChain;
     private XMLSecEvent currentXMLSecEvent;
-    private boolean skipDocumentEvents = false;
+    private final boolean skipDocumentEvents;
+    private String version;
+    private boolean standalone;
+    private boolean standaloneSet;
+    private String characterEncodingScheme;
 
     private static final String ERR_STATE_NOT_ELEM = "Current state not START_ELEMENT or END_ELEMENT";
     private static final String ERR_STATE_NOT_STELEM = "Current state not START_ELEMENT";
@@ -75,9 +80,20 @@ public class XMLSecurityStreamReader imp
             inputProcessorChain.reset();
             currentXMLSecEvent = inputProcessorChain.processEvent();
             eventType = currentXMLSecEvent.getEventType();
-            if (eventType == START_DOCUMENT && this.skipDocumentEvents) {
-                currentXMLSecEvent = inputProcessorChain.processEvent();
-                eventType = currentXMLSecEvent.getEventType();
+            if (eventType == START_DOCUMENT) {
+                // Even when skipDocumentEvents is true, we still want to get the information out of the event.
+                // We only skip the event itself.
+                StartDocument startDocument = (StartDocument) currentXMLSecEvent;
+                version = startDocument.getVersion();
+                if (startDocument.encodingSet()) {
+                    characterEncodingScheme = startDocument.getCharacterEncodingScheme();
+                }
+                standalone = startDocument.isStandalone();
+                standaloneSet = startDocument.standaloneSet();
+                if (skipDocumentEvents) {
+                    currentXMLSecEvent = inputProcessorChain.processEvent();
+                    eventType = currentXMLSecEvent.getEventType();
+                }
             }
         } catch (XMLSecurityException e) {
             throw new XMLStreamException(e);
@@ -592,22 +608,22 @@ public class XMLSecurityStreamReader imp
 
     @Override
     public String getVersion() {
-        return null;
+        return version;
     }
 
     @Override
     public boolean isStandalone() {
-        return false;
+        return standalone;
     }
 
     @Override
     public boolean standaloneSet() {
-        return false;
+        return standaloneSet;
     }
 
     @Override
     public String getCharacterEncodingScheme() {
-        return null;
+        return characterEncodingScheme;
     }
 
     @Override

Modified: santuario/xml-security-java/branches/2.1.x-fixes/src/test/java/org/apache/xml/security/test/stax/XMLSecurityStreamReaderTest.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/branches/2.1.x-fixes/src/test/java/org/apache/xml/security/test/stax/XMLSecurityStreamReaderTest.java?rev=1874026&r1=1874025&r2=1874026&view=diff
==============================================================================
--- santuario/xml-security-java/branches/2.1.x-fixes/src/test/java/org/apache/xml/security/test/stax/XMLSecurityStreamReaderTest.java (original)
+++ santuario/xml-security-java/branches/2.1.x-fixes/src/test/java/org/apache/xml/security/test/stax/XMLSecurityStreamReaderTest.java Fri Feb 14 16:52:46 2020
@@ -41,6 +41,7 @@ import javax.xml.transform.TransformerFa
 import javax.xml.transform.stax.StAXSource;
 import javax.xml.transform.stream.StreamResult;
 import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -48,6 +49,9 @@ import java.nio.charset.StandardCharsets
 import java.util.HashSet;
 import java.util.Set;
 
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+
 /**
  */
 public class XMLSecurityStreamReaderTest extends Assert {
@@ -98,6 +102,70 @@ public class XMLSecurityStreamReaderTest
     }
 
     @Test
+    public void testDocumentDeclaration() throws Exception {
+        String xml = "<?xml version='1.1' encoding='ISO-8859-1' standalone='yes'?>\n"
+                + "<Document/>";
+        ByteArrayInputStream xmlInput = new ByteArrayInputStream(xml.getBytes(StandardCharsets.ISO_8859_1));
+        XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
+        XMLStreamReader stdXmlStreamReader = xmlInputFactory.createXMLStreamReader(xmlInput);
+        InboundSecurityContextImpl securityContext = new InboundSecurityContextImpl();
+        InputProcessorChainImpl inputProcessorChain = new InputProcessorChainImpl(securityContext);
+        inputProcessorChain.addProcessor(new EventReaderProcessor(stdXmlStreamReader));
+        XMLSecurityProperties securityProperties = new XMLSecurityProperties();
+        securityProperties.setSkipDocumentEvents(false);
+        XMLSecurityStreamReader xmlSecurityStreamReader = new XMLSecurityStreamReader(inputProcessorChain, securityProperties);
+        advanceToFirstEvent(xmlSecurityStreamReader);
+        assertThat(xmlSecurityStreamReader.getEventType(), is(XMLStreamConstants.START_DOCUMENT));
+        assertThat(xmlSecurityStreamReader.getVersion(), is(equalTo("1.1")));
+        assertThat(xmlSecurityStreamReader.getCharacterEncodingScheme(), is(equalTo("ISO-8859-1")));
+        assertThat(xmlSecurityStreamReader.isStandalone(), is(true));
+        assertThat(xmlSecurityStreamReader.standaloneSet(), is(true));
+
+        assertThat(xmlSecurityStreamReader.hasNext(), is(true));
+        assertThat(xmlSecurityStreamReader.next(), is(XMLStreamConstants.START_ELEMENT));
+        // Strictly speaking, we should assert that getVersion() etc. throw when not on a START_DOCUMENT event.
+        // However, we have to be lenient to compensate for XML reader implementations such as Xalan,
+        // which access getVersion() etc. when they're positioned on START_ELEMENT, _beyond_ START_DOCUMENT.
+        assertThat(xmlSecurityStreamReader.getVersion(), is(equalTo("1.1")));
+        assertThat(xmlSecurityStreamReader.getCharacterEncodingScheme(), is(equalTo("ISO-8859-1")));
+        assertThat(xmlSecurityStreamReader.isStandalone(), is(true));
+        assertThat(xmlSecurityStreamReader.standaloneSet(), is(true));
+    }
+
+    @Test
+    public void testDocumentDeclarationWhenSkipDocumentEvents() throws Exception {
+        String xml = "<?xml version='1.1' encoding='ISO-8859-1' standalone='yes'?>\n"
+                + "<Document/>";
+        ByteArrayInputStream xmlInput = new ByteArrayInputStream(xml.getBytes(StandardCharsets.ISO_8859_1));
+        XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
+        XMLStreamReader stdXmlStreamReader = xmlInputFactory.createXMLStreamReader(xmlInput);
+        InboundSecurityContextImpl securityContext = new InboundSecurityContextImpl();
+        InputProcessorChainImpl inputProcessorChain = new InputProcessorChainImpl(securityContext);
+        inputProcessorChain.addProcessor(new EventReaderProcessor(stdXmlStreamReader));
+        XMLSecurityProperties securityProperties = new XMLSecurityProperties();
+        securityProperties.setSkipDocumentEvents(true);
+        XMLSecurityStreamReader xmlSecurityStreamReader = new XMLSecurityStreamReader(inputProcessorChain, securityProperties);
+        advanceToFirstEvent(xmlSecurityStreamReader);
+        assertThat(xmlSecurityStreamReader.getEventType(), is(XMLStreamConstants.START_ELEMENT));
+        assertThat(xmlSecurityStreamReader.getVersion(), is(equalTo("1.1")));
+        assertThat(xmlSecurityStreamReader.getCharacterEncodingScheme(), is(equalTo("ISO-8859-1")));
+        assertThat(xmlSecurityStreamReader.isStandalone(), is(true));
+        assertThat(xmlSecurityStreamReader.standaloneSet(), is(true));
+    }
+
+    /**
+     * This method advances the reader until it's <i>on</i> the first event, if that's not already the case.
+     * Depending on the implementation, the {@code xmlStreamReader} may be positioned <i>before</i> or <i>on</i>
+     * the first event upon creation.
+     */
+    private static void advanceToFirstEvent(XMLStreamReader xmlStreamReader) throws XMLStreamException {
+        if (xmlStreamReader.getEventType() <= 0) {
+            assertThat(xmlStreamReader.hasNext(), is(true));
+            xmlStreamReader.next();
+        }
+    }
+
+    @Test
     public void testCorrectness() throws Exception {
         XMLSecurityProperties securityProperties = new XMLSecurityProperties();
         InboundSecurityContextImpl securityContext = new InboundSecurityContextImpl();
@@ -115,6 +183,10 @@ public class XMLSecurityStreamReaderTest
                 "org/apache/xml/security/c14n/inExcl/plain-soap-1.1.xml"));
 
         //hmm why does a streamreader return a DOCUMENT_EVENT before we did call next() ??
+        // A: Because some implementations of XMLStreamReader are positioned _on_ the first event rather than before it
+        // upon construction.
+        // Woodstox is a typical example of such an implementation.
+        // We have to compensate for both types of implementation, see the method advanceToFirstEvent(XMLStreamReader).
         int stdXMLEventType = stdXmlStreamReader.getEventType();
         int secXMLEventType = xmlSecurityStreamReader.getEventType();
         do {
@@ -207,7 +279,7 @@ public class XMLSecurityStreamReaderTest
                 case XMLStreamConstants.START_DOCUMENT:
                     Assert.assertEquals(stdXmlStreamReader.getCharacterEncodingScheme(), xmlSecurityStreamReader.getCharacterEncodingScheme());
                     Assert.assertEquals(stdXmlStreamReader.getEncoding(), xmlSecurityStreamReader.getEncoding());
-                    //Assert.assertEquals(stdXmlStreamReader.getVersion(), xmlSecurityStreamReader.getVersion());
+                    Assert.assertEquals(stdXmlStreamReader.getVersion(), xmlSecurityStreamReader.getVersion());
                     break;
                 case XMLStreamConstants.END_DOCUMENT:
                     break;
@@ -261,17 +333,24 @@ public class XMLSecurityStreamReaderTest
         return stringBuilder.toString();
     }
 
+    private static XMLStreamReader createXmlStreamReader() throws XMLStreamException {
+        XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
+        xmlInputFactory.setProperty(XMLInputFactory.IS_COALESCING, true);
+        xmlInputFactory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
+        return xmlInputFactory.createXMLStreamReader(InputProcessor.class.getClassLoader().getResourceAsStream(
+                        "org/apache/xml/security/c14n/inExcl/plain-soap-1.1.xml"));
+    }
+
     class EventReaderProcessor implements InputProcessor {
 
         private XMLStreamReader xmlStreamReader;
 
+        EventReaderProcessor(XMLStreamReader xmlStreamReader) {
+            this.xmlStreamReader = xmlStreamReader;
+        }
+
         EventReaderProcessor() throws Exception {
-            XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
-            xmlInputFactory.setProperty(XMLInputFactory.IS_COALESCING, true);
-            xmlInputFactory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
-            xmlStreamReader =
-                xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream(
-                    "org/apache/xml/security/c14n/inExcl/plain-soap-1.1.xml"));
+            this(createXmlStreamReader());
         }
 
         @Override

Modified: santuario/xml-security-java/branches/2.1.x-fixes/src/test/java/org/apache/xml/security/test/stax/utils/XmlReaderToWriter.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/branches/2.1.x-fixes/src/test/java/org/apache/xml/security/test/stax/utils/XmlReaderToWriter.java?rev=1874026&r1=1874025&r2=1874026&view=diff
==============================================================================
--- santuario/xml-security-java/branches/2.1.x-fixes/src/test/java/org/apache/xml/security/test/stax/utils/XmlReaderToWriter.java (original)
+++ santuario/xml-security-java/branches/2.1.x-fixes/src/test/java/org/apache/xml/security/test/stax/utils/XmlReaderToWriter.java Fri Feb 14 16:52:46 2020
@@ -31,6 +31,13 @@ public final class XmlReaderToWriter {
 
     public static void writeAll(XMLStreamReader xmlr, XMLStreamWriter writer)
             throws XMLStreamException {
+        // Some implementations, Woodstox for example, already position their reader ON the first event, which is.
+        // typically a START_DOCUMENT event.
+        // If already positioned on an event, that is indicated by the event type.
+        // Make sure we don't miss the initial event.
+        if (xmlr.getEventType() > 0) {
+            write(xmlr, writer);
+        }
         while (xmlr.hasNext()) {
             xmlr.next();
             write(xmlr, writer);