Repository navigation
Answer XML-RPC with Roller's own server and drop Apache XML-RPC - #263
Conversation
Apache XML-RPC is end of life. Its last release, 3.1.3, has an unfixed denial-of-service issue (CVE-2016-5004), and Roller's servlet layer was already a fork because xmlrpc-server has no Jakarta release. It also inflated gzip-encoded request bodies without any limit. The Blogger and MetaWeblog endpoint now runs on a small server in the xmlrpc package: - XmlRpcRequestParser reads methodCall documents with SafeSAXBuilder (no DOCTYPE, nothing resolved). It accepts only the specification's value types and caps nesting at 32 levels. Structs become Maps and arrays Object[], as before, so the handlers' casts still hold. - XmlRpcResponseWriter writes methodResponse and fault documents in UTF-8. Dates use the old yyyyMMddTHH:mm:ss format in the server's zone, and characters XML 1.0 forbids are dropped (the filter now lives in XmlCharacters and is shared with AtomWriter). - XmlRpcServer exposes each handler's public, non-void methods, inherited ones included, as prefix.method, and picks the overload whose parameter types fit, as the library's property mapping did. Handler faults keep their codes. Any other failure is logged and answered with fault 1000, so internal details aren't sent to the client. - RollerXmlRpcServlet caps the request at 1 MiB, or at the largest allowed upload as base64 while uploads are on. It answers 413 above that, and the cap also applies to the decompressed size of a gzip body. xmlrpc-common, xmlrpc-server, ws-commons-util, the forked RollerXmlRpcServletServer, the XmlRpcServlet.properties mapping, the enabledForExtensions init-param and SecureXmlParsers.installForXmlRpc are removed. The handlers now throw Roller's own XmlRpcException and XmlRpcNotAuthorizedException, with the same fault codes. New tests cover dispatch, overloads, inherited methods, faults, the writer's types and escaping, and the servlet's caps, including a gzip body that is small compressed but far over the cap decompressed. The existing handler permission tests pass unchanged apart from imports.
# Conflicts: # CHANGES.md
CodeQL flagged two places on this PR. The parser's build() call was flagged as XXE because CodeQL doesn't follow the settings SafeSAXBuilder makes in its constructor, so the parser now also sets disallow-doctype-decl next to the call; behaviour is unchanged. The servlet's response was flagged for writing an exception message. XmlRpcException now keeps the client-facing fault string as its own field, and the server writes that, which makes clear the text is meant for the client. Unexpected failures still get the generic fault.
# Conflicts: # CHANGES.md
… entry Testing against a copy of raibledesigns.com showed both: the old library wrote each surrogate half of an emoji as its own character reference, so clients rejected the response, and stored carriage returns reached clients normalised to LF.
snoopdave
left a comment
There was a problem hiding this comment.
PR-Review: 1 inline comment posted, plus 1 general issue below.
|
PR-Review: General Issues The following issues were found but cannot be attached to a specific line in the diff:
|
The cap followed uploads.file.maxsize with no ceiling. The whole body is read into memory and parsed into a document before anyone is authenticated, so a site allowing 100 MB uploads accepted about 137 MB per anonymous request. The cap still rises with the upload size but stops at 32 MiB, which fits a file of about 23 MB as base64. CHANGES and the install guide say so.
|
Both points from the review are addressed. Request cap. 7edbfb9 stops the cap at 32 MiB whatever Client interop. I ran Python 3.15's With the real client, on this branch:
Then the request shapes other clients send, as raw XML:
Two differences from master:
|
|
A correction to my comment above: |
The request parser caught JDOMException and IOException, but JDOM also refuses some documents with unchecked exceptions: an XML 1.1 document may hold a reference to a control character or a name starting with a supplementary-plane character, which the JDK's parser accepts and JDOM's verifier does not. Those escaped the servlet, so an unauthenticated request got an HTTP 500 with Roller's error page, which prints the exception's message, and a stack trace went to the log each time. Master answers the same requests with a fault. The parser now turns any failure to build the document into the usual parse fault, and the server answers the generic fault for any other unchecked exception so nothing a request does reaches the container. XmlRpcServerTest covers the XML 1.1 cases and, since nothing did before, that a document type declaration is refused without reading the file it names.
Apache XML-RPC is end of life. 3.1.3, its last release, has an unfixed denial-of-service issue (CVE-2016-5004, the open Dependabot alert). Roller's servlet layer was already a fork, because
xmlrpc-serverhas no Jakarta release. One concrete problem in that fork: it inflated gzip-encoded request bodies with no limit.This replaces the library with a small server in
webservices/xmlrpc. Clients see the same methods, faults and fault codes.XmlRpcRequestParser:SafeSAXBuilder, so DOCTYPEs are refused and nothing is resolved;Object[]as before, so the handlers' casts are unchanged;yyyyMMddTHH:mm:ssform, plus the dashed, fractional and zoned variants clients send.XmlRpcResponseWriter:methodResponseand fault documents, with dates in the old format and the server's zone;util/XmlCharacters, andAtomWriteruses the same one.XmlRpcServer:prefix.method, like the library's property mapping. SometaWeblog.getUsersBlogsstill works.int/boolean publishpairs still work;RollerXmlRpcServlet:Removed:
xmlrpc-common,xmlrpc-server,ws-commons-util, the forkedRollerXmlRpcServletServer,XmlRpcServlet.properties, theenabledForExtensionsinit-param andSecureXmlParsers.installForXmlRpc(). The handlers now throw Roller's ownXmlRpcExceptionandXmlRpcNotAuthorizedException.Tests:
XmlRpcServerTest: dispatch, overloads, inherited methods, struct and array conversion, faults, no leaked internals, and that every Blogger and MetaWeblog name is registered.XmlRpcResponseWriterTest: types, dates, escaping, well-formed output and faults.RollerXmlRpcServletTest: both size checks, gzip accepted, a gzip body small on the wire but far over the cap decompressed, bad encodings, and the upload-based cap.XmlRpcExtensionTypeTest: now runs against the new parser.XMLRPCWeblogPermissionTest: passes with only its imports changed.mvn install: 684 tests pass.I haven't tested this with a desktop blogging client against a running server. That would be a good check before the RC.