package org.jboss.resteasy.test.xxe; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.container.test.api.RunAsClient; import org.jboss.arquillian.junit.Arquillian; import org.jboss.resteasy.category.NotForForwardCompatibility; import org.jboss.resteasy.client.jaxrs.ResteasyClient; import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder; import org.jboss.resteasy.test.xxe.resource.SecureProcessingBar; import org.jboss.resteasy.test.xxe.resource.SecureProcessingFavoriteMovie; import org.jboss.resteasy.test.xxe.resource.SecureProcessingFavoriteMovieXmlRootElement; import org.jboss.resteasy.test.xxe.resource.SecureProcessingFavoriteMovieXmlType; import org.jboss.resteasy.test.xxe.resource.ObjectFactory; import org.jboss.resteasy.test.xxe.resource.SecureProcessingResource; import org.jboss.resteasy.util.HttpResponseCodes; import org.jboss.resteasy.utils.TestUtil; import org.jboss.shrinkwrap.api.Archive; import org.jboss.shrinkwrap.api.spec.WebArchive; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import javax.ws.rs.client.Entity; import javax.ws.rs.core.Response; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.startsWith; import static org.hamcrest.Matchers.isEmptyString; import static org.hamcrest.core.StringContains.containsString; import static org.jboss.resteasy.utils.PortProviderUtil.generateURL; /** * @tpSubChapter XXE * @tpChapter Integration tests * @tpTestCaseDetails Regression test for RESTEASY-1103 * RestEasy is vulnerable to XML Entity Denial of Service XXE is disabled. * @tpSince RESTEasy 3.0.16 */ @RunWith(Arquillian.class) @RunAsClient public class SecureProcessingTest { protected final Logger logger = LogManager.getLogger(SecureProcessingTest.class.getName()); static ResteasyClient client; private static final String URL_PREFIX = "RESTEASY-1103-"; protected static String bigAttributeDoc; static { StringBuffer sb = new StringBuffer(); sb.append("<secureProcessingBar "); for (int i = 0; i < 12000; i++) { sb.append("attr" + i + "=\"x\" "); } sb.append(">secureProcessingBar</secureProcessingBar>"); bigAttributeDoc = sb.toString(); } String bigElementDoctype = "<!DOCTYPE foodocument [" + "<!ENTITY foo 'foo'>" + "<!ENTITY foo1 '&foo;&foo;&foo;&foo;&foo;&foo;&foo;&foo;&foo;&foo;'>" + "<!ENTITY foo2 '&foo1;&foo1;&foo1;&foo1;&foo1;&foo1;&foo1;&foo1;&foo1;&foo1;'>" + "<!ENTITY foo3 '&foo2;&foo2;&foo2;&foo2;&foo2;&foo2;&foo2;&foo2;&foo2;&foo2;'>" + "<!ENTITY foo4 '&foo3;&foo3;&foo3;&foo3;&foo3;&foo3;&foo3;&foo3;&foo3;&foo3;'>" + "<!ENTITY foo5 '&foo4;&foo4;&foo4;&foo4;&foo4;&foo4;&foo4;&foo4;&foo4;&foo4;'>" + "<!ENTITY foo6 '&foo5;&foo5;&foo5;&foo5;&foo5;&foo5;&foo5;&foo5;&foo5;&foo5;'>" + "]>"; String bigXmlRootElement = bigElementDoctype + "<secureProcessingFavoriteMovieXmlRootElement><title>&foo6;</title></secureProcessingFavoriteMovieXmlRootElement>"; String bigXmlType = bigElementDoctype + "<favoriteMovie><title>&foo6;</title></favoriteMovie>"; String bigJAXBElement = bigElementDoctype + "<favoriteMovieXmlType><title>&foo6;</title></favoriteMovieXmlType>"; String bigCollection = bigElementDoctype + "<collection>" + "<secureProcessingFavoriteMovieXmlRootElement><title>&foo6;</title></secureProcessingFavoriteMovieXmlRootElement>" + "<secureProcessingFavoriteMovieXmlRootElement><title>&foo6;</title></secureProcessingFavoriteMovieXmlRootElement>" + "</collection>"; String bigMap = bigElementDoctype + "<map>" + "<entry key=\"key1\">" + "<secureProcessingFavoriteMovieXmlRootElement><title>&foo6;</title></secureProcessingFavoriteMovieXmlRootElement>" + "</entry>" + "<entry key=\"key2\">" + "<secureProcessingFavoriteMovieXmlRootElement><title>&foo6;</title></secureProcessingFavoriteMovieXmlRootElement>" + "</entry>" + "</map>"; String bar = "<!DOCTYPE secureProcessingBar SYSTEM \"src/test/resources/org/jboss/resteasy/test/xxe/SecureProcessing_external.dtd\"><secureProcessingBar><s>junk</s></secureProcessingBar>"; String filename = TestUtil.getResourcePath(SecureProcessingTest.class, "SecureProcessiongTestpasswd"); String externalXmlRootElement = "<?xml version=\"1.0\"?>\r" + "<!DOCTYPE foo\r" + "[<!ENTITY xxe SYSTEM \"" + filename + "\">\r" + "]>\r" + "<secureProcessingFavoriteMovieXmlRootElement><title>&xxe;</title></secureProcessingFavoriteMovieXmlRootElement>"; String externalXmlType = "<?xml version=\"1.0\"?>\r" + "<!DOCTYPE foo\r" + "[<!ENTITY xxe SYSTEM \"" + filename + "\">\r" + "]>\r" + "<favoriteMovie><title>&xxe;</title></favoriteMovie>"; String externalJAXBElement = "<?xml version=\"1.0\"?>\r" + "<!DOCTYPE foo\r" + "[<!ENTITY xxe SYSTEM \"" + filename + "\">\r" + "]>\r" + "<favoriteMovieXmlType><title>&xxe;</title></favoriteMovieXmlType>"; String externalCollection = "<?xml version=\"1.0\"?>\r" + "<!DOCTYPE foo\r" + "[<!ENTITY xxe SYSTEM \"" + filename + "\">\r" + "]>\r" + "<collection>" + " <secureProcessingFavoriteMovieXmlRootElement><title>&xxe;</title></secureProcessingFavoriteMovieXmlRootElement>" + " <secureProcessingFavoriteMovieXmlRootElement><title>&xxe;</title></secureProcessingFavoriteMovieXmlRootElement>" + "</collection>"; String externalMap = "<?xml version=\"1.0\"?>\r" + "<!DOCTYPE foo\r" + "[<!ENTITY xxe SYSTEM \"" + filename + "\">\r" + "]>\r" + "<map>" + "<entry key=\"american\">" + "<secureProcessingFavoriteMovieXmlRootElement><title>&xxe;</title></secureProcessingFavoriteMovieXmlRootElement>" + "</entry>" + "<entry key=\"french\">" + "<secureProcessingFavoriteMovieXmlRootElement><title>&xxe;</title></secureProcessingFavoriteMovieXmlRootElement>" + "</entry>" + "</map>"; @Deployment(name = "fff", order = 14) public static Archive<?> createTestArchive_fff() { return createTestArchive("fff", "false_false_false"); } @Deployment(name = "fft", order = 15) public static Archive<?> createTestArchive_fft() { return createTestArchive("fft", "false_false_true"); } @Deployment(name = "ftd", order = 16) public static Archive<?> createTestArchive_ftd() { return createTestArchive("ftd", "false_true_default"); } @Deployment(name = "ftf", order = 17) public static Archive<?> createTestArchive_ftf() { return createTestArchive("ftf", "false_true_false"); } @Deployment(name = "ftt", order = 18) public static Archive<?> createTestArchive_ftt() { return createTestArchive("ftt", "false_true_true"); } @Deployment(name = "tdd", order = 19) public static Archive<?> createTestArchive_tdd() { return createTestArchive("tdd", "true_default_default"); } @Deployment(name = "tdf", order = 20) public static Archive<?> createTestArchive_tdf() { return createTestArchive("tdf", "true_default_false"); } @Deployment(name = "tdt", order = 21) public static Archive<?> createTestArchive_tdt() { return createTestArchive("tdt", "true_default_true"); } @Deployment(name = "tfd", order = 22) public static Archive<?> createTestArchive_tfd() { return createTestArchive("tfd", "true_false_default"); } @Deployment(name = "tff", order = 23) public static Archive<?> createTestArchive_tff() { return createTestArchive("tff", "true_false_false"); } @Deployment(name = "tft", order = 24) public static Archive<?> createTestArchive_tft() { return createTestArchive("tft", "true_false_true"); } @Deployment(name = "ttd", order = 25) public static Archive<?> createTestArchive_ttd() { return createTestArchive("ttd", "true_true_default"); } @Deployment(name = "ttf", order = 26) public static Archive<?> createTestArchive_ttf() { return createTestArchive("ttf", "true_true_false"); } @Deployment(name = "ttt", order = 27) public static Archive<?> createTestArchive_ttt() { return createTestArchive("ttt", "true_true_true"); } static Archive<?> createTestArchive(String warExt, String webXmlExt) { WebArchive war = TestUtil.prepareArchive(URL_PREFIX + warExt); war.addClasses(SecureProcessingBar.class, SecureProcessingFavoriteMovie.class, SecureProcessingFavoriteMovieXmlRootElement.class); war.addClasses(SecureProcessingFavoriteMovieXmlType.class, ObjectFactory.class); war.addAsWebInfResource(SecureProcessingTest.class.getPackage(), "SecureProcessing_external.dtd", "external.dtd"); war.addAsWebInfResource(SecureProcessingTest.class.getPackage(), "SecureProcessing_web_" + webXmlExt + ".xml", "web.xml"); return TestUtil.finishContainerPrepare(war, null, SecureProcessingResource.class); } @Before public void init() { client = new ResteasyClientBuilder().build(); } @After public void after() throws Exception { client.close(); } /** * @tpTestDetails "resteasy.document.secure.processing.feature" is set to false * "resteasy.document.secure.disableDTDs" is set to false * "resteasy.document.expand.entity.references" is set to false * @tpSince RESTEasy 3.0.16 */ @Test public void testSecurityFalseDTDsFalseExpansionFalse() throws Exception { doTestPassesPassesPassesFails("fff"); } /** * @tpTestDetails "resteasy.document.secure.processing.feature" is set to false * "resteasy.document.secure.disableDTDs" is set to false * "resteasy.document.expand.entity.references" is set to true * @tpSince RESTEasy 3.0.16 */ @Test public void testSecurityFalseDTDsFalseExpansionTrue() throws Exception { doTestPassesPassesPassesPasses("fft"); } /** * @tpTestDetails "resteasy.document.secure.processing.feature" is set to false * "resteasy.document.secure.disableDTDs" is set to true * "resteasy.document.expand.entity.references" is set to default value * @tpSince RESTEasy 3.0.16 */ @Test public void testSecurityFalseDTDsTrueExpansionDefault() throws Exception { doTestSkipPassesFailsSkip("ftd"); } /** * @tpTestDetails "resteasy.document.secure.processing.feature" is set to false * "resteasy.document.secure.disableDTDs" is set to true * "resteasy.document.expand.entity.references" is set to false * @tpSince RESTEasy 3.0.16 */ @Test public void testSecurityFalseDTDsTrueExpansionFalse() throws Exception { doTestSkipPassesFailsSkip("ftf"); } /** * @tpTestDetails "resteasy.document.secure.processing.feature" is set to false * "resteasy.document.secure.disableDTDs" is set to true * "resteasy.document.expand.entity.references" is set to true * @tpSince RESTEasy 3.0.16 */ @Test public void testSecurityFalseDTDsTrueExpansionTrue() throws Exception { doTestSkipPassesFailsSkip("ftt"); } /** * @tpTestDetails "resteasy.document.secure.processing.feature" is set to true * "resteasy.document.secure.disableDTDs" is set to default value * "resteasy.document.expand.entity.references" is set to default value * @tpSince RESTEasy 3.0.16 */ @Test public void testSecurityTrueDTDsDefaultExpansionDefault() throws Exception { doTestSkipFailsFailsSkip("tdd"); } /** * @tpTestDetails "resteasy.document.secure.processing.feature" is set to true * "resteasy.document.secure.disableDTDs" is set to default value * "resteasy.document.expand.entity.references" is set to false * @tpSince RESTEasy 3.0.16 */ @Test public void testSecurityTrueDTDsDefaultExpansionFalse() throws Exception { doTestSkipFailsFailsSkip("tdf"); } /** * @tpTestDetails "resteasy.document.secure.processing.feature" is set to true * "resteasy.document.secure.disableDTDs" is set to default value * "resteasy.document.expand.entity.references" is set to true * @tpSince RESTEasy 3.0.16 */ @Test public void testSecurityTrueDTDsDefaultExpansionTrue() throws Exception { doTestSkipFailsFailsSkip("tdt"); } /** * @tpTestDetails "resteasy.document.secure.processing.feature" is set to true * "resteasy.document.secure.disableDTDs" is set to false * "resteasy.document.expand.entity.references" is set to default value * @tpSince RESTEasy 3.0.16 */ @Test public void testSecurityTrueDTDsFalseExpansionDefault() throws Exception { doTestFailsFailsPassesFails("tfd"); } /** * @tpTestDetails "resteasy.document.secure.processing.feature" is set to true * "resteasy.document.secure.disableDTDs" is set to false * "resteasy.document.expand.entity.references" is set to false * @tpSince RESTEasy 3.0.16 */ @Test public void testSecurityTrueDTDsFalseExpansionFalse() throws Exception { doTestFailsFailsPassesFails("tff"); } /** * @tpTestDetails "resteasy.document.secure.processing.feature" is set to true * "resteasy.document.secure.disableDTDs" is set to false * "resteasy.document.expand.entity.references" is set to true * @tpSince RESTEasy 3.0.16 */ @Test public void testSecurityTrueDTDsFalseExpansionTrue() throws Exception { doTestFailsFailsPassesPasses("tft"); } /** * @tpTestDetails "resteasy.document.secure.processing.feature" is set to true * "resteasy.document.secure.disableDTDs" is set to true * "resteasy.document.expand.entity.references" is set to default value * @tpSince RESTEasy 3.0.16 */ @Test public void testSecurityTrueDTDsTrueExpansionDefault() throws Exception { doTestSkipFailsFailsSkip("ttd"); } /** * @tpTestDetails "resteasy.document.secure.processing.feature" is set to true * "resteasy.document.secure.disableDTDs" is set to true * "resteasy.document.expand.entity.references" is set to false * @tpSince RESTEasy 3.0.16 */ @Test public void testSecurityTrueDTDsTrueExpansionFalse() throws Exception { doTestSkipFailsFailsSkip("ttf"); } /** * @tpTestDetails "resteasy.document.secure.processing.feature" is set to true * "resteasy.document.secure.disableDTDs" is set to true * "resteasy.document.expand.entity.references" is set to true * @tpSince RESTEasy 3.0.16 */ @Test public void testSecurityTrueDTDsTrueExpansionTrue() throws Exception { doTestSkipFailsFailsSkip("ttt"); } /** * @tpTestDetails "resteasy.document.secure.processing.feature" is set to true * "resteasy.document.secure.disableDTDs" is set to true * "resteasy.document.expand.entity.references" is set to true * @tpSince RESTEasy 3.1.0 */ @Test @Category({NotForForwardCompatibility.class}) public void testSecurityTrueDTDsTrueExpansionTrueWithApacheLinkMessage() throws Exception { doTestSkipFailsFailsSkipWithApacheLinkMessage("ttt"); } void doTestSkipFailsFailsSkipWithApacheLinkMessage(String ext) throws Exception { doMaxAttributesFails(ext); doDTDFailsWithApacheLinkMessage(ext); } void doTestSkipFailsFailsSkip(String ext) throws Exception { doMaxAttributesFails(ext); doDTDFails(ext); } void doTestSkipPassesFailsSkip(String ext) throws Exception { doMaxAttributesPasses(ext); doDTDFails(ext); } void doTestFailsFailsPassesFails(String ext) throws Exception { doEntityExpansionFails(ext); doMaxAttributesFails(ext); doDTDPasses(ext); doExternalEntityExpansionFails(ext); } void doTestFailsFailsPassesPasses(String ext) throws Exception { doEntityExpansionFails(ext); doMaxAttributesFails(ext); doDTDPasses(ext); doExternalEntityExpansionPasses(ext); } void doTestPassesPassesPassesFails(String ext) throws Exception { doEntityExpansionPasses(ext); doMaxAttributesPasses(ext); doDTDPasses(ext); doDTDPasses(ext); doExternalEntityExpansionFails(ext); } void doTestPassesPassesPassesPasses(String ext) throws Exception { doEntityExpansionPasses(ext); doMaxAttributesPasses(ext); doDTDPasses(ext); doDTDPasses(ext); doExternalEntityExpansionPasses(ext); } void doEntityExpansionFails(String ext) throws Exception { logger.info("entering doEntityExpansionFails(" + ext + ")"); { logger.info("Request body: " + bigXmlRootElement); Response response = client.target(generateURL("/entityExpansion/xmlRootElement/", URL_PREFIX + ext)).request() .post(Entity.entity(bigXmlRootElement, "application/xml")); Assert.assertEquals(HttpResponseCodes.SC_BAD_REQUEST, response.getStatus()); String entity = response.readEntity(String.class); logger.info("doEntityExpansionFails() result: " + entity); Assert.assertThat("Wrong type of exception", entity, containsString("javax.xml.bind.UnmarshalException")); } { Response response = client.target(generateURL("/entityExpansion/xmlType/", URL_PREFIX + ext)).request() .post(Entity.entity(bigXmlType, "application/xml")); Assert.assertEquals(HttpResponseCodes.SC_BAD_REQUEST, response.getStatus()); String entity = response.readEntity(String.class); logger.info("doEntityExpansionFails() result: " + entity); Assert.assertThat("Wrong type of exception", entity, containsString("javax.xml.bind.UnmarshalException")); } { Response response = client.target(generateURL("/entityExpansion/JAXBElement/", URL_PREFIX + ext)).request() .post(Entity.entity(bigJAXBElement, "application/xml")); Assert.assertEquals(HttpResponseCodes.SC_BAD_REQUEST, response.getStatus()); String entity = response.readEntity(String.class); logger.info("doEntityExpansionFails() result: " + entity); Assert.assertThat("Wrong type of exception", entity, containsString("javax.xml.bind.UnmarshalException")); } { Response response = client.target(generateURL("/entityExpansion/collection/", URL_PREFIX + ext)).request() .post(Entity.entity(bigCollection, "application/xml")); Assert.assertEquals(HttpResponseCodes.SC_BAD_REQUEST, response.getStatus()); String entity = response.readEntity(String.class); logger.info("doEntityExpansionFails() result: " + entity); Assert.assertThat("Wrong type of exception", entity, containsString("javax.xml.bind.UnmarshalException")); } { Response response = client.target(generateURL("/entityExpansion/map/", URL_PREFIX + ext)).request() .post(Entity.entity(bigMap, "application/xml")); Assert.assertEquals(HttpResponseCodes.SC_BAD_REQUEST, response.getStatus()); String entity = response.readEntity(String.class); logger.info("doEntityExpansionFails() result: " + entity); Assert.assertThat("Wrong type of exception", entity, containsString("javax.xml.bind.UnmarshalException")); } } void doEntityExpansionPasses(String ext) throws Exception { logger.info("entering doEntityExpansionFails(" + ext + ")"); { logger.info("Request body: " + bigXmlRootElement); Response response = client.target(generateURL("/entityExpansion/xmlRootElement/", URL_PREFIX + ext)).request() .post(Entity.entity(bigXmlRootElement, "application/xml")); Assert.assertEquals(HttpResponseCodes.SC_OK, response.getStatus()); String entity = response.readEntity(String.class); int len = Math.min(entity.length(), 30); logger.info("doEntityExpansionPasses() result: " + entity.substring(0, len) + "..."); Assert.assertEquals("Wrong number of received \"foo\" in text", 1000000, countFoos(entity)); } { Response response = client.target(generateURL("/entityExpansion/xmlType/", URL_PREFIX + ext)).request() .post(Entity.entity(bigXmlType, "application/xml")); Assert.assertEquals(HttpResponseCodes.SC_OK, response.getStatus()); String entity = response.readEntity(String.class); int len = Math.min(entity.length(), 30); logger.info("doEntityExpansionPasses() result: " + entity.substring(0, len) + "..."); Assert.assertEquals("Wrong number of received \"foo\" in text", 1000000, countFoos(entity)); } { Response response = client.target(generateURL("/entityExpansion/JAXBElement/", URL_PREFIX + ext)).request() .post(Entity.entity(bigJAXBElement, "application/xml")); Assert.assertEquals(HttpResponseCodes.SC_OK, response.getStatus()); String entity = response.readEntity(String.class); int len = Math.min(entity.length(), 30); logger.info("doEntityExpansionPasses() result: " + entity.substring(0, len) + "..."); Assert.assertEquals("Wrong number of received \"foo\" in text", 1000000, countFoos(entity)); } { Response response = client.target(generateURL("/entityExpansion/collection/", URL_PREFIX + ext)).request() .post(Entity.entity(bigCollection, "application/xml")); Assert.assertEquals(HttpResponseCodes.SC_OK, response.getStatus()); String entity = response.readEntity(String.class); int len = Math.min(entity.length(), 30); logger.info("doEntityExpansionPasses() result: " + entity.substring(0, len) + "..."); Assert.assertEquals("Wrong number of received \"foo\" in text", 2000000, countFoos(entity)); } { Response response = client.target(generateURL("/entityExpansion/map/", URL_PREFIX + ext)).request() .post(Entity.entity(bigMap, "application/xml")); Assert.assertEquals(HttpResponseCodes.SC_OK, response.getStatus()); String entity = response.readEntity(String.class); int len = Math.min(entity.length(), 30); logger.info("doEntityExpansionPasses() result: " + entity.substring(0, len) + "..."); Assert.assertEquals("Wrong number of received \"foo\" in text", 2000000, countFoos(entity)); } } void doMaxAttributesFails(String ext) throws Exception { logger.info("entering doMaxAttributesFails(" + ext + ")"); Response response = client.target(generateURL("/maxAttributes/", URL_PREFIX + ext)).request() .post(Entity.entity(bigAttributeDoc, "application/xml")); logger.info("doMaxAttributesFails() status: " + response.getStatus()); String entity = response.readEntity(String.class); logger.info("doMaxAttributesFails() result: " + entity); } void doMaxAttributesPasses(String ext) throws Exception { logger.info("entering doMaxAttributesPasses(" + ext + ")"); Response response = client.target(generateURL("/maxAttributes/", URL_PREFIX + ext)).request() .post(Entity.entity(bigAttributeDoc, "application/xml")); logger.info("doMaxAttributesPasses() status: " + response.getStatus()); String entity = response.readEntity(String.class); logger.info("doMaxAttributesPasses() result: " + entity); Assert.assertEquals(HttpResponseCodes.SC_NO_CONTENT, response.getStatus()); } void doDTDFails(String ext) throws Exception { logger.info("entering doDTDFails(" + ext + ")"); Response response = client.target(generateURL("/DTD/", URL_PREFIX + ext)).request() .post(Entity.entity(bar, "application/xml")); logger.info("status: " + response.getStatus()); String entity = response.readEntity(String.class); logger.info("doDTDFails(): result: " + entity); Assert.assertEquals(HttpResponseCodes.SC_BAD_REQUEST, response.getStatus()); Assert.assertThat("Wrong exception in response", entity, startsWith("javax.xml.bind.UnmarshalException")); Assert.assertThat("Wrong content of response", entity, containsString("DOCTYPE")); Assert.assertThat("Wrong content of response", entity, containsString("true")); } void doDTDFailsWithApacheLinkMessage(String ext) throws Exception { logger.info("entering doDTDFails(" + ext + ")"); Response response = client.target(generateURL("/DTD/", URL_PREFIX + ext)).request() .post(Entity.entity(bar, "application/xml")); logger.info("status: " + response.getStatus()); String entity = response.readEntity(String.class); logger.info("doDTDFails(): result: " + entity); Assert.assertEquals(HttpResponseCodes.SC_BAD_REQUEST, response.getStatus()); Assert.assertThat("Wrong exception in response", entity, startsWith("javax.xml.bind.UnmarshalException")); Assert.assertThat("Wrong content of response", entity, containsString("DOCTYPE")); Assert.assertThat("Wrong content of response", entity, containsString("http://apache.org/xml/features/disallow-doctype-decl")); Assert.assertThat("Wrong content of response", entity, containsString("true")); } void doDTDPasses(String ext) throws Exception { logger.info("entering doDTDPasses(" + ext + ")"); Response response = client.target(generateURL("/DTD/", URL_PREFIX + ext)).request() .post(Entity.entity(bar, "application/xml")); logger.info("status: " + response.getStatus()); String entity = response.readEntity(String.class); logger.info("doDTDPasses() result: " + entity); Assert.assertEquals(HttpResponseCodes.SC_OK, response.getStatus()); Assert.assertThat("Wrong content of response", entity, containsString("junk")); } void doExternalEntityExpansionFails(String ext) throws Exception { logger.info("entering doExternalEntityExpansionFails(" + ext + ")"); { Response response = client.target(generateURL("/entityExpansion/xmlRootElement/", URL_PREFIX + ext)).request() .post(Entity.entity(externalXmlRootElement, "application/xml")); String entity = response.readEntity(String.class); logger.info("doExternalEntityExpansionFails() result: " + entity); Assert.assertEquals(HttpResponseCodes.SC_OK, response.getStatus()); Assert.assertThat("Wrong content of response", entity, isEmptyString()); } { Response response = client.target(generateURL("/entityExpansion/xmlType/", URL_PREFIX + ext)).request() .post(Entity.entity(externalXmlType, "application/xml")); String entity = response.readEntity(String.class); logger.info("doExternalEntityExpansionFails() result: " + entity); Assert.assertEquals(HttpResponseCodes.SC_OK, response.getStatus()); Assert.assertThat("Wrong content of response", entity, isEmptyString()); } { Response response = client.target(generateURL("/entityExpansion/JAXBElement/", URL_PREFIX + ext)).request() .post(Entity.entity(externalJAXBElement, "application/xml")); String entity = response.readEntity(String.class); logger.info("doExternalEntityExpansionFails() result: " + entity); Assert.assertEquals(HttpResponseCodes.SC_OK, response.getStatus()); Assert.assertThat("Wrong content of response", entity, isEmptyString()); } { Response response = client.target(generateURL("/entityExpansion/collection/", URL_PREFIX + ext)).request() .post(Entity.entity(externalCollection, "application/xml")); String entity = response.readEntity(String.class); logger.info("doExternalEntityExpansionFails() result: " + entity); Assert.assertEquals(HttpResponseCodes.SC_OK, response.getStatus()); Assert.assertThat("Wrong content of response", entity, isEmptyString()); } { Response response = client.target(generateURL("/entityExpansion/map/", URL_PREFIX + ext)).request() .post(Entity.entity(externalMap, "application/xml")); String entity = response.readEntity(String.class); logger.info("doExternalEntityExpansionFails() result: " + entity); Assert.assertEquals(HttpResponseCodes.SC_OK, response.getStatus()); Assert.assertThat("Wrong content of response", entity, isEmptyString()); } } void doExternalEntityExpansionPasses(String ext) throws Exception { logger.info("entering doExternalEntityExpansionPasses(" + ext + ")"); { logger.info("externalXmlRootElement: " + externalXmlRootElement); Response response = client.target(generateURL("/entityExpansion/xmlRootElement/", URL_PREFIX + ext)).request() .post(Entity.entity(externalXmlRootElement, "application/xml")); String entity = response.readEntity(String.class); int len = Math.min(entity.length(), 30); logger.info("doExternalEntityExpansionPasses() result: " + entity.substring(0, len) + "..."); Assert.assertEquals(HttpResponseCodes.SC_OK, response.getStatus()); Assert.assertThat("Content of response should contain password", entity, is("xx:xx:xx:xx:xx:xx:xx")); } { Response response = client.target(generateURL("/entityExpansion/xmlType/", URL_PREFIX + ext)).request() .post(Entity.entity(externalXmlType, "application/xml")); String entity = response.readEntity(String.class); int len = Math.min(entity.length(), 30); logger.info("doExternalEntityExpansionPasses() result: " + entity.substring(0, len) + "..."); Assert.assertEquals(HttpResponseCodes.SC_OK, response.getStatus()); Assert.assertThat("Content of response should contain password", entity, is("xx:xx:xx:xx:xx:xx:xx")); } { Response response = client.target(generateURL("/entityExpansion/JAXBElement/", URL_PREFIX + ext)).request() .post(Entity.entity(externalJAXBElement, "application/xml")); String entity = response.readEntity(String.class); int len = Math.min(entity.length(), 30); logger.info("doExternalEntityExpansionPasses() result: " + entity.substring(0, len) + "..."); Assert.assertEquals(HttpResponseCodes.SC_OK, response.getStatus()); Assert.assertThat("Content of response should contain password", entity, is("xx:xx:xx:xx:xx:xx:xx")); } { Response response = client.target(generateURL("/entityExpansion/collection/", URL_PREFIX + ext)).request() .post(Entity.entity(externalCollection, "application/xml")); String entity = response.readEntity(String.class); int len = Math.min(entity.length(), 30); logger.info("doExternalEntityExpansionPasses() result: " + entity.substring(0, len) + "..."); Assert.assertEquals(HttpResponseCodes.SC_OK, response.getStatus()); Assert.assertThat("Content of response should contain password twice", entity, is("xx:xx:xx:xx:xx:xx:xxxx:xx:xx:xx:xx:xx:xx")); } { Response response = client.target(generateURL("/entityExpansion/map/", URL_PREFIX + ext)).request() .post(Entity.entity(externalMap, "application/xml")); String entity = response.readEntity(String.class); int len = Math.min(entity.length(), 30); logger.info("doExternalEntityExpansionPasses() result: " + entity.substring(0, len) + "..."); Assert.assertEquals(HttpResponseCodes.SC_OK, response.getStatus()); Assert.assertThat("Content of response should contain password twice", entity, is("xx:xx:xx:xx:xx:xx:xxxx:xx:xx:xx:xx:xx:xx")); } } /** * Get count of "foo" substring in input string */ private int countFoos(String s) { int count = 0; int pos = 0; while (pos >= 0) { pos = s.indexOf("foo", pos); if (pos >= 0) { count++; pos += 3; } } return count; } }