summary refs log tree commit diff
diff options
context:
space:
mode:
authorAndrew Morgan <andrew@amorgan.xyz>2019-05-08 11:52:25 -0700
committerAndrew Morgan <andrew@amorgan.xyz>2019-05-08 11:52:25 -0700
commitaee810a54812df76a78743a88772b1bb9063fcab (patch)
tree3768ebb926461063dbf2c6eeb87b1a22a6a46482
parentEnable federation blacklisting by default (diff)
downloadsynapse-aee810a54812df76a78743a88772b1bb9063fcab.tar.xz
Fix tests and various small review issues
-rw-r--r--synapse/http/client.py7
-rw-r--r--synapse/http/matrixfederationclient.py3
-rw-r--r--synapse/rest/media/v1/preview_url_resource.py16
-rw-r--r--tests/http/test_fedclient.py84
4 files changed, 37 insertions, 73 deletions
diff --git a/synapse/http/client.py b/synapse/http/client.py
index 368b0d49b7..77fe68818b 100644
--- a/synapse/http/client.py
+++ b/synapse/http/client.py
@@ -165,10 +165,10 @@ class BlacklistingAgentWrapper(Agent):
                 ip_address, self._ip_whitelist, self._ip_blacklist
             ):
                 logger.info(
-                    "Blocking access to %s because of blacklist. Returning 0 results" %
+                    "Blocking access to %s due to blacklist" %
                     (ip_address,)
                 )
-                e = SynapseError(404, "No results found")
+                e = SynapseError(403, "IP address blocked by IP blacklist entry")
                 return defer.fail(Failure(e))
         except Exception:
             # Not an IP
@@ -264,9 +264,6 @@ class SimpleHttpClient(object):
             uri (str): URI to query.
             data (bytes): Data to send in the request body, if applicable.
             headers (t.w.http_headers.Headers): Request headers.
-
-        Raises:
-            SynapseError: If the IP is blacklisted.
         """
         # A small wrapper around self.agent.request() so we can easily attach
         # counters to it
diff --git a/synapse/http/matrixfederationclient.py b/synapse/http/matrixfederationclient.py
index 6fe337e4bb..7eefc7b1fc 100644
--- a/synapse/http/matrixfederationclient.py
+++ b/synapse/http/matrixfederationclient.py
@@ -199,7 +199,8 @@ class MatrixFederationHttpClient(object):
             tls_client_options_factory,
         )
 
-        # Prevent direct connections to blacklisted IP addresses
+        # Use a BlacklistingAgentWrapper to prevent circumventing the IP
+        # blacklist via IP literals in server names
         self.agent = BlacklistingAgentWrapper(
             self.agent, self.reactor,
             ip_blacklist=hs.config.federation_ip_range_blacklist,
diff --git a/synapse/rest/media/v1/preview_url_resource.py b/synapse/rest/media/v1/preview_url_resource.py
index f1f24ebd1c..acf87709f2 100644
--- a/synapse/rest/media/v1/preview_url_resource.py
+++ b/synapse/rest/media/v1/preview_url_resource.py
@@ -329,18 +329,18 @@ class PreviewUrlResource(Resource):
                 # handler will return a SynapseError to the client instead of
                 # blank data or a 500.
                 raise
+            except DNSLookupError:
+                # DNS lookup returned no results
+                # Note: This will also be the case if one of the resolved IP
+                # addresses is blacklisted
+                raise SynapseError(
+                    502, "DNS resolution failure during URL preview generation",
+                    Codes.UNKNOWN
+                )
             except Exception as e:
                 # FIXME: pass through 404s and other error messages nicely
                 logger.warn("Error downloading %s: %r", url, e)
 
-                if isinstance(e, DNSLookupError):
-                    # DNS lookup returned no results
-                    # Note: This will also be the case if the found IP address
-                    # is blacklisted
-                    raise SynapseError(
-                        404, "No results found", Codes.UNKNOWN
-                    )
-
                 raise SynapseError(
                     500, "Failed to download content: %s" % (
                         traceback.format_exception_only(sys.exc_info()[0], e),
diff --git a/tests/http/test_fedclient.py b/tests/http/test_fedclient.py
index 148e55b7a5..0a7e498182 100644
--- a/tests/http/test_fedclient.py
+++ b/tests/http/test_fedclient.py
@@ -228,93 +228,59 @@ class FederationClientTests(HomeserverTestCase):
 
         # Try making a GET request to a blacklisted IPv4 address
         # ------------------------------------------------------
-        @defer.inlineCallbacks
-        def do_request():
-            with LoggingContext("one") as context:
-                fetch_d = cl.get_json("internal:8008", "foo/bar")
-
-                # Nothing happened yet
-                self.assertNoResult(fetch_d)
-
-                # should have reset logcontext to the sentinel
-                check_logcontext(LoggingContext.sentinel)
-
-                try:
-                    fetch_res = yield fetch_d
-                    defer.returnValue(fetch_res)
-                finally:
-                    check_logcontext(context)
-
         # Make the request
-        d = do_request()
-        self.pump()
+        d = cl.get_json("internal:8008", "foo/bar", timeout=10000)
 
-        # Nothing has happened yet
+        # Nothing happened yet
         self.assertNoResult(d)
 
+        self.pump(120)
+
         # Check that it was unable to resolve the address
         clients = self.reactor.tcpClients
         self.assertEqual(len(clients), 0)
 
+        f = self.failureResultOf(d)
+        self.assertIsInstance(f.value, RequestSendFailed)
+        self.assertIsInstance(f.value.inner_exception, DNSLookupError)
+
         # Try making a POST request to a blacklisted IPv6 address
         # -------------------------------------------------------
-        @defer.inlineCallbacks
-        def do_request():
-            with LoggingContext("one") as context:
-                fetch_d = cl.post_json("internalv6:8008", "foo/bar")
-
-                # Nothing happened yet
-                self.assertNoResult(fetch_d)
-
-                # should have reset logcontext to the sentinel
-                check_logcontext(LoggingContext.sentinel)
-
-                try:
-                    fetch_res = yield fetch_d
-                    defer.returnValue(fetch_res)
-                finally:
-                    check_logcontext(context)
-
         # Make the request
-        d = do_request()
-        self.pump()
+        d = cl.post_json("internalv6:8008", "foo/bar", timeout=10000)
 
         # Nothing has happened yet
         self.assertNoResult(d)
 
+        # Move the reactor forwards
+        self.pump(120)
+
         # Check that it was unable to resolve the address
         clients = self.reactor.tcpClients
         self.assertEqual(len(clients), 0)
 
+        # Check that it was due to a blacklisted DNS lookup
+        f = self.failureResultOf(d, RequestSendFailed)
+        self.assertIsInstance(f.value.inner_exception, DNSLookupError)
+
         # Try making a GET request to a non-blacklisted IPv4 address
         # ----------------------------------------------------------
-        @defer.inlineCallbacks
-        def do_request():
-            with LoggingContext("one") as context:
-                fetch_d = cl.post_json("fine:8008", "foo/bar")
-
-                # Nothing happened yet
-                self.assertNoResult(fetch_d)
-
-                # should have reset logcontext to the sentinel
-                check_logcontext(LoggingContext.sentinel)
-
-                try:
-                    fetch_res = yield fetch_d
-                    defer.returnValue(fetch_res)
-                finally:
-                    check_logcontext(context)
-
         # Make the request
-        d = do_request()
-        self.pump()
+        d = cl.post_json("fine:8008", "foo/bar", timeout=10000)
 
         # Nothing has happened yet
         self.assertNoResult(d)
 
+        # Move the reactor forwards
+        self.pump(120)
+
         # Check that it was able to resolve the address
         clients = self.reactor.tcpClients
-        self.assertEqual(len(clients), 1)
+        self.assertNotEqual(len(clients), 0)
+
+        # Connection will still fail as this IP address does not resolve to anything
+        f = self.failureResultOf(d, RequestSendFailed)
+        self.assertIsInstance(f.value.inner_exception, ConnectingCancelledError)
 
     def test_client_gets_headers(self):
         """