Skip to content

Commit e1b461a

Browse files
committed
Disable by default DTD parsing in webdav support, close AsyncHttpClient#1666
see https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing
1 parent 1e1a844 commit e1b461a

File tree

1 file changed

+19
-8
lines changed

1 file changed

+19
-8
lines changed

client/src/main/java/org/asynchttpclient/webdav/WebDavCompletionHandlerBase.java

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
package org.asynchttpclient.webdav;
1515

1616
import io.netty.handler.codec.http.HttpHeaders;
17-
import org.asynchttpclient.AsyncCompletionHandlerBase;
1817
import org.asynchttpclient.AsyncHandler;
1918
import org.asynchttpclient.HttpResponseBodyPart;
2019
import org.asynchttpclient.HttpResponseStatus;
@@ -42,11 +41,24 @@
4241
* @param <T> the result type
4342
*/
4443
public abstract class WebDavCompletionHandlerBase<T> implements AsyncHandler<T> {
45-
private final Logger logger = LoggerFactory.getLogger(AsyncCompletionHandlerBase.class);
44+
private static final Logger LOGGER = LoggerFactory.getLogger(WebDavCompletionHandlerBase.class);
45+
private static final DocumentBuilderFactory DOCUMENT_BUILDER_FACTORY;
4646
private final List<HttpResponseBodyPart> bodyParts = Collections.synchronizedList(new ArrayList<>());
4747
private HttpResponseStatus status;
4848
private HttpHeaders headers;
4949

50+
static {
51+
DOCUMENT_BUILDER_FACTORY = DocumentBuilderFactory.newInstance();
52+
if (Boolean.getBoolean("org.asynchttpclient.webdav.enableDtd")) {
53+
try {
54+
DOCUMENT_BUILDER_FACTORY.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
55+
} catch (ParserConfigurationException e) {
56+
LOGGER.error("Failed to disable doctype declaration");
57+
throw new ExceptionInInitializerError(e);
58+
}
59+
}
60+
}
61+
5062
/**
5163
* {@inheritDoc}
5264
*/
@@ -75,13 +87,12 @@ public final State onHeadersReceived(final HttpHeaders headers) {
7587
}
7688

7789
private Document readXMLResponse(InputStream stream) {
78-
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
7990
Document document;
8091
try {
81-
document = factory.newDocumentBuilder().parse(stream);
92+
document = DOCUMENT_BUILDER_FACTORY.newDocumentBuilder().parse(stream);
8293
parse(document);
8394
} catch (SAXException | IOException | ParserConfigurationException e) {
84-
logger.error(e.getMessage(), e);
95+
LOGGER.error(e.getMessage(), e);
8596
throw new RuntimeException(e);
8697
}
8798
return document;
@@ -94,7 +105,7 @@ private void parse(Document document) {
94105
Node node = statusNode.item(i);
95106

96107
String value = node.getFirstChild().getNodeValue();
97-
int statusCode = Integer.valueOf(value.substring(value.indexOf(" "), value.lastIndexOf(" ")).trim());
108+
int statusCode = Integer.parseInt(value.substring(value.indexOf(" "), value.lastIndexOf(" ")).trim());
98109
String statusText = value.substring(value.lastIndexOf(" "));
99110
status = new HttpStatusWrapper(status, statusText, statusCode);
100111
}
@@ -122,7 +133,7 @@ public final T onCompleted() throws Exception {
122133
*/
123134
@Override
124135
public void onThrowable(Throwable t) {
125-
logger.debug(t.getMessage(), t);
136+
LOGGER.debug(t.getMessage(), t);
126137
}
127138

128139
/**
@@ -134,7 +145,7 @@ public void onThrowable(Throwable t) {
134145
*/
135146
abstract public T onCompleted(WebDavResponse response) throws Exception;
136147

137-
private class HttpStatusWrapper extends HttpResponseStatus {
148+
private static class HttpStatusWrapper extends HttpResponseStatus {
138149

139150
private final HttpResponseStatus wrapped;
140151

0 commit comments

Comments
 (0)