1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.xml.secure;
19
20 import static org.junit.jupiter.api.Assertions.assertNotNull;
21 import static org.junit.jupiter.api.Assertions.assertNull;
22 import static org.junit.jupiter.api.Assertions.assertThrows;
23 import static org.junit.jupiter.api.Assertions.assertTrue;
24
25 import javax.xml.transform.Source;
26 import javax.xml.transform.TransformerConfigurationException;
27 import javax.xml.transform.TransformerFactory;
28 import javax.xml.transform.sax.SAXSource;
29 import javax.xml.transform.stream.StreamSource;
30
31 import org.junit.jupiter.api.Assumptions;
32 import org.junit.jupiter.api.Tag;
33 import org.junit.jupiter.api.Test;
34 import org.xml.sax.InputSource;
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 @Tag("trax")
52 class AssociatedStylesheetTest {
53
54 private static TransformerFactory secureFactory() {
55 final TransformerFactory factory = SecureTransformerFactory.newInstance();
56 factory.setErrorListener(AttackTestSupport.STRICT_REPORTER);
57 return factory;
58 }
59
60 @Test
61 void secureGetAssociatedStylesheetIgnoresExternalDtd() throws TransformerConfigurationException {
62
63
64 final Source associated = secureFactory()
65 .getAssociatedStylesheet(AttackTestSupport.resourceSource("associated-stylesheet.xml"), null, null, null);
66 assertNotNull(associated, "expected the associated stylesheet PI to be found");
67 assertNull(associated.getSystemId(), "the PI href must not come back as a live URI: " + associated.getSystemId());
68 }
69
70 @Test
71 void secureGetAssociatedStylesheetIgnoresExternalDtdWithCallerReader() throws Exception {
72
73
74 final SAXSource source = new SAXSource(SecureSAXParserFactory.newInstance().newSAXParser().getXMLReader(),
75 new InputSource(AttackTestSupport.resourceUrl("associated-stylesheet.xml").toString()));
76 final Source associated = secureFactory().getAssociatedStylesheet(source, null, null, null);
77 assertNotNull(associated, "expected the associated stylesheet PI to be found");
78 assertNull(associated.getSystemId(), "the PI href must not come back as a live URI: " + associated.getSystemId());
79 }
80
81 @Test
82 void secureGetAssociatedStylesheetOptsInThroughResolver() throws TransformerConfigurationException {
83
84
85 final StreamSource opted = new StreamSource(AttackTestSupport.resourceUrl("included.xsl").toString());
86 final TransformerFactory factory = secureFactory();
87 factory.setURIResolver((href, base) -> href != null && href.endsWith("included.xsl") ? opted : null);
88 final Source associated = factory
89 .getAssociatedStylesheet(AttackTestSupport.resourceSource("associated-stylesheet-plain.xml"), null, null, null);
90 assertNotNull(associated, "expected the associated stylesheet PI to be found");
91 assertNotNull(associated.getSystemId(), "an opted-in href must resolve to the caller's stylesheet, not to the empty default");
92 assertTrue(associated.getSystemId().endsWith("included.xsl"), "unexpected associated stylesheet: " + associated.getSystemId());
93 }
94
95 @Test
96 void secureGetAssociatedStylesheetReturnsStylesheet() throws TransformerConfigurationException {
97
98 final Source associated = secureFactory()
99 .getAssociatedStylesheet(AttackTestSupport.resourceSource("associated-stylesheet-plain.xml"), null, null, null);
100 assertNotNull(associated, "expected the associated stylesheet PI to be found");
101 assertNull(associated.getSystemId(), "the PI href must not come back as a live URI: " + associated.getSystemId());
102 }
103
104 @Test
105 void unconfiguredGetAssociatedStylesheetFetchesExternalDtd() {
106
107
108 Assumptions.assumeFalse(AttackTestSupport.IS_ANDROID, "Android's KXmlParser does not fetch external DTDs");
109 assertThrows(TransformerConfigurationException.class, () -> TransformerFactory.newInstance()
110 .getAssociatedStylesheet(AttackTestSupport.resourceSource("associated-stylesheet.xml"), null, null, null));
111 }
112 }