diff test/test_xmlrpc.py @ 8237:57325fea9982

issue2551116 - Replace xmlrpclib (xmlrpc.client) with defusedxml. defusedxml will be used to moneypatch the problematic client and server modules. Test added using an xml bomb.
author John Rouillard <rouilj@ieee.org>
date Sun, 29 Dec 2024 19:11:01 -0500
parents 978285986b2c
children 05405220dc38
line wrap: on
line diff
--- a/test/test_xmlrpc.py	Mon Dec 23 21:10:54 2024 -0500
+++ b/test/test_xmlrpc.py	Sun Dec 29 19:11:01 2024 -0500
@@ -5,7 +5,7 @@
 #
 
 from __future__ import print_function
-import unittest, os, shutil, errno, sys, difflib, re
+import unittest, os, shutil, errno, pytest, sys, difflib, re
 
 from roundup.anypy import xmlrpc_
 MultiCall = xmlrpc_.client.MultiCall
@@ -21,6 +21,19 @@
 from .test_mysql import skip_mysql
 from .test_postgresql import skip_postgresql
 
+from .pytest_patcher import mark_class
+from roundup.anypy.xmlrpc_ import client
+
+if client.defusedxml:
+    skip_defusedxml = lambda func, *args, **kwargs: func
+
+    skip_defusedxml_used = mark_class(pytest.mark.skip(
+        reason='Skipping non-defusedxml tests: defusedxml library in use'))
+else:
+    skip_defusedxml = mark_class(pytest.mark.skip(
+        reason='Skipping defusedxml tests: defusedxml library not available'))
+    
+    skip_defusedxml_used = lambda func, *args, **kwargs: func
 
 class XmlrpcTest(object):
 
@@ -314,6 +327,55 @@
         for n, r in enumerate(result):
             self.assertEqual(r, results[n])
 
+    @skip_defusedxml
+    def testDefusedXmlBomb(self):
+        self.XmlBomb(expectIn=b"defusedxml.common.EntitiesForbidden")
+
+    @skip_defusedxml_used
+    def testNonDefusedXmlBomb(self):
+        self.XmlBomb(expectIn=b"1234567890"*511)
+
+    def XmlBomb(self, expectIn=None):
+
+        bombInput = """<?xml version='1.0'?>
+        <!DOCTYPE xmlbomb [
+        <!ENTITY a "1234567890" >
+        <!ENTITY b "&a;&a;&a;&a;&a;&a;&a;&a;">
+        <!ENTITY c "&b;&b;&b;&b;&b;&b;&b;&b;">
+        <!ENTITY d "&c;&c;&c;&c;&c;&c;&c;&c;">
+        ]>
+        <methodCall>
+        <methodName>filter</methodName>
+        <params>
+        <param>
+        <value><string>&d;</string></value>
+        </param>
+        <param>
+        <value><array><data>
+        <value><string>0</string></value>
+        <value><string>2</string></value>
+        <value><string>3</string></value>
+        </data></array></value>
+        </param>
+        <param>
+        <value><struct>
+        <member>
+        <name>username</name>
+        <value><string>demo</string></value>
+        </member>
+        </struct></value>
+        </param>
+        </params>
+        </methodCall>
+        """
+        translator = TranslationService.get_translation(
+            language=self.instance.config["TRACKER_LANGUAGE"],
+            tracker_home=self.instance.config["TRACKER_HOME"])
+        self.server = RoundupDispatcher(self.db, self.instance.actions,
+            translator, allow_none = True)
+        response = self.server.dispatch(bombInput)
+        print(response)
+        self.assertIn(expectIn, response)
 
 class anydbmXmlrpcTest(XmlrpcTest, unittest.TestCase):
     backend = 'anydbm'

Roundup Issue Tracker: http://roundup-tracker.org/