def test_renderAnswer_textplain(self):
        """If the request format specifies 'plain', we should return content
        with mimetype 'text/plain'.
        """
        self.useBenignBridges()

        request = DummyRequest([self.pagename])
        request.args.update({'format': ['plain']})
        request.getClientIP = lambda: '4.4.4.4'
        request.method = b'GET'

        page = self.bridgesResource.render(request)
        self.assertTrue("html" not in str(page))

        # We just need to strip and split it because it looks like:
        #
        #   94.235.85.233:9492 0d9d0547c3471cddc473f7288a6abfb54562dc06
        #   255.225.204.145:9511 1fb89d618b3a12afe3529fd072127ea08fb50466
        #
        # (Yes, there are two leading spaces at the beginning of each line)
        #
        bridgeLines = [line.strip() for line in page.strip().split('\n')]

        for bridgeLine in bridgeLines:
            bridgeLine = bridgeLine.split(' ')
            self.assertEqual(len(bridgeLine), 2)

            # Check that the IP and port seem okay:
            ip, port = bridgeLine[0].rsplit(':')
            self.assertIsInstance(ipaddr.IPv4Address(ip), ipaddr.IPv4Address)
            self.assertIsInstance(int(port), int)
            self.assertGreater(int(port), 0)
            self.assertLessEqual(int(port), 65535)
示例#2
0
    def test_render_GET_RTLlang(self):
        """Test rendering a request for plain bridges in Arabic."""

        if 'ar' not in _langs.get_langs():
            self.skipTest("'ar' language unsupported")

        self.useBenignBridges()

        request = DummyRequest([b"bridges?transport=obfs3"])
        request.method = b'GET'
        request.getClientIP = lambda: '3.3.3.3'
        # For some strange reason, the 'Accept-Language' value *should not* be
        # a list, unlike all the other headers and args…
        request.headers.update({'accept-language': 'ar,en,en_US,'})

        page = self.bridgesResource.render(request)
        self.assertSubstring(b"rtl.css", page)
        self.assertSubstring(
            # "I need an alternative way to get bridges!"
            "أحتاج إلى وسيلة بديلة للحصول على bridges".encode("utf-8"),
            page)

        for bridgeLine in self.parseBridgesFromHTMLPage(page):
            # Check that each bridge line had the expected number of fields:
            bridgeLine = bridgeLine.split(' ')
            self.assertEqual(len(bridgeLine), 2)
    def test_render_GET_RTLlang_obfs3(self):
        """Test rendering a request for obfs3 bridges in Farsi."""
        self.useBenignBridges()

        request = DummyRequest([b"bridges?transport=obfs3"])
        request.method = b'GET'
        request.getClientIP = lambda: '3.3.3.3'
        request.headers.update({'accept-language': 'fa,en,en_US,'})
        # We actually have to set the request args manually when using a
        # DummyRequest:
        request.args.update({'transport': ['obfs3']})

        page = self.bridgesResource.render(request)
        self.assertSubstring("rtl.css", page)
        self.assertSubstring(
            # "How to use the above bridge lines" (since there should be
            # bridges in this response, we don't tell them about alternative
            # mechanisms for getting bridges)
            "چگونگی از پل‌های خود استفاده کنید", page)

        for bridgeLine in self.parseBridgesFromHTMLPage(page):
            # Check that each bridge line had the expected number of fields:
            bridgeLine = bridgeLine.split(' ')
            self.assertEqual(len(bridgeLine), 3)
            self.assertEqual(bridgeLine[0], 'obfs3')

            # Check that the IP and port seem okay:
            ip, port = bridgeLine[1].rsplit(':')
            self.assertIsInstance(ipaddr.IPv4Address(ip), ipaddr.IPv4Address)
            self.assertIsInstance(int(port), int)
            self.assertGreater(int(port), 0)
            self.assertLessEqual(int(port), 65535)
示例#4
0
    def test_render_GET_vanilla(self):
        """Test rendering a request for normal, vanilla bridges."""
        self.useBenignBridges()

        request = DummyRequest([self.pagename])
        request.method = b'GET'
        request.getClientIP = lambda: '1.1.1.1'

        page = self.bridgesResource.render(request)

        # The response should explain how to use the bridge lines:
        self.assertTrue("How to start using your bridges" in str(page))

        for b in self.parseBridgesFromHTMLPage(page):
            # Check that each bridge line had the expected number of fields:
            fields = b.split(' ')
            self.assertEqual(len(fields), 2)

            # Check that the IP and port seem okay:
            ip, port = fields[0].rsplit(':')
            self.assertIsInstance(ipaddress.ip_address(ip),
                                  ipaddress.IPv4Address)
            self.assertIsInstance(int(port), int)
            self.assertGreater(int(port), 0)
            self.assertLessEqual(int(port), 65535)
示例#5
0
    def test_renderAnswer_textplain(self):
        """If the request format specifies 'plain', we should return content
        with mimetype 'text/plain'.
        """
        self.useBenignBridges()

        request = DummyRequest([self.pagename])
        request.args.update({'format': ['plain']})
        request.getClientIP = lambda: '4.4.4.4'
        request.method = b'GET'

        page = self.bridgesResource.render(request)
        self.assertTrue("html" not in str(page))

        # We just need to strip and split it because it looks like:
        #
        #   94.235.85.233:9492 0d9d0547c3471cddc473f7288a6abfb54562dc06
        #   255.225.204.145:9511 1fb89d618b3a12afe3529fd072127ea08fb50466
        #
        # (Yes, there are two leading spaces at the beginning of each line)
        #
        bridgeLines = [line.strip() for line in page.strip().split(b'\n')]

        for bridgeLine in bridgeLines:
            bridgeLine = bridgeLine.split(b' ')
            self.assertEqual(len(bridgeLine), 2)

            # Check that the IP and port seem okay:
            ip, port = bridgeLine[0].rsplit(b':')
            self.assertIsInstance(ipaddress.ip_address(ip.decode("utf-8")),
                                  ipaddress.IPv4Address)
            self.assertIsInstance(int(port), int)
            self.assertGreater(int(port), 0)
            self.assertLessEqual(int(port), 65535)
    def test_render_GET_RTLlang_obfs3(self):
        """Test rendering a request for obfs3 bridges in Farsi."""
        self.useBenignBridges()

        request = DummyRequest([b"bridges?transport=obfs3"])
        request.method = b'GET'
        request.getClientIP = lambda: '3.3.3.3'
        request.headers.update({'accept-language': 'fa,en,en_US,'})
        # We actually have to set the request args manually when using a
        # DummyRequest:
        request.args.update({'transport': ['obfs3']})

        page = self.bridgesResource.render(request)
        self.assertSubstring("rtl.css", page)
        self.assertSubstring(
            # "How to use the above bridge lines" (since there should be
            # bridges in this response, we don't tell them about alternative
            # mechanisms for getting bridges)
            "چگونگی از پل‌های خود استفاده کنید",
            page)

        for bridgeLine in self.parseBridgesFromHTMLPage(page):
            # Check that each bridge line had the expected number of fields:
            bridgeLine = bridgeLine.split(' ')
            self.assertEqual(len(bridgeLine), 3)
            self.assertEqual(bridgeLine[0], 'obfs3')

            # Check that the IP and port seem okay:
            ip, port = bridgeLine[1].rsplit(':')
            self.assertIsInstance(ipaddr.IPv4Address(ip), ipaddr.IPv4Address)
            self.assertIsInstance(int(port), int)
            self.assertGreater(int(port), 0)
            self.assertLessEqual(int(port), 65535)
    def test_render_GET_RTLlang(self):
        """Test rendering a request for obfs3 bridges in Hebrew."""
        request = DummyRequest(["bridges?transport=obfs3"])
        request.method = b'GET'
        request.getClientIP = lambda: '3.3.3.3'
        request.headers.update({'accept-language': 'he'})
        # We actually have to set the request args manually when using a
        # DummyRequest:
        request.args.update({'transport': ['obfs2']})

        page = self.optionsResource.render(request)
        self.assertSubstring("rtl.css", page)
        self.assertSubstring("מהם גשרים?", page)
    def test_render_GET_RTLlang(self):
        """Test rendering a request for obfs3 bridges in Hebrew."""
        request = DummyRequest(["bridges?transport=obfs3"])
        request.method = b'GET'
        request.getClientIP = lambda: '3.3.3.3'
        request.headers.update({'accept-language': 'he'})
        # We actually have to set the request args manually when using a
        # DummyRequest:
        request.args.update({'transport': ['obfs2']})

        page = self.optionsResource.render(request)
        self.assertSubstring("rtl.css", page)
        self.assertSubstring("מהם גשרים?", page)
    def test_render_GET_malicious_returnchar(self):
        """Test rendering a request when the some of the bridges returned have
        malicious (HTML, Javascript, etc., in their) PT arguments.
        """
        self.useMaliciousBridges()

        request = DummyRequest([self.pagename])
        request.method = b'GET'
        request.getClientIP = lambda: '1.1.1.1'

        page = self.bridgesResource.render(request)
        self.assertTrue(
            'eww=Bridge 1.2.3.4:1234' in str(page),
            "Return characters in bridge lines should be removed.")
示例#10
0
    def test_render_GET_malicious_newlines(self):
        """Test rendering a request when the some of the bridges returned have
        malicious (HTML, Javascript, etc., in their) PT arguments.
        """
        self.useMaliciousBridges()

        request = DummyRequest([self.pagename])
        request.method = b'GET'
        request.getClientIP = lambda: '1.1.1.1'

        page = self.bridgesResource.render(request)
        self.assertTrue(
            'bad=Bridge 6.6.6.6:6666 0123456789abcdef0123456789abcdef01234567' in str(page),
            "Newlines in bridge lines should be removed.")
示例#11
0
    def test_https_metrics(self):

        origFunc = metrics.resolveCountryCode
        metrics.resolveCountryCode = lambda _: "US"

        key1 = "https.obfs4.us.success.none"
        req1 = DummyRequest([b"bridges?transport=obfs4"])
        # We have to set the request args manually when using a DummyRequest.
        req1.args.update({'transport': ['obfs4']})
        req1.getClientIP = lambda: "3.3.3.3"

        self.metrix.recordValidHTTPSRequest(req1)
        self.assertTrue(self.metrix.hotMetrics[key1] == 1)

        key2 = "https.obfs4.us.fail.none"
        req2 = DummyRequest([b"bridges?transport=obfs4"])
        # We have to set the request args manually when using a DummyRequest.
        req2.args.update({'transport': ['obfs4']})
        req2.getClientIP = lambda: "3.3.3.3"
        self.metrix.recordInvalidHTTPSRequest(req2)
        self.assertTrue(self.metrix.hotMetrics[key2] == 1)

        metrics.resolveCountryCode = origFunc
示例#12
0
    def test_render_GET_malicious_returnchar(self):
        """Test rendering a request when the some of the bridges returned have
        malicious (HTML, Javascript, etc., in their) PT arguments.
        """
        self.useMaliciousBridges()

        request = DummyRequest([self.pagename])
        request.method = b'GET'
        request.getClientIP = lambda: '1.1.1.1'

        page = self.bridgesResource.render(request)
        self.assertTrue(
            'eww=Bridge 1.2.3.4:1234' in str(page),
            "Return characters in bridge lines should be removed.")
示例#13
0
    def test_render_GET_malicious_newlines(self):
        """Test rendering a request when the some of the bridges returned have
        malicious (HTML, Javascript, etc., in their) PT arguments.
        """
        self.useMaliciousBridges()

        request = DummyRequest([self.pagename])
        request.method = b'GET'
        request.getClientIP = lambda: '1.1.1.1'

        page = self.bridgesResource.render(request)
        self.assertTrue(
            'bad=Bridge 6.6.6.6:6666 0123456789abcdef0123456789abcdef01234567'
            in str(page), "Newlines in bridge lines should be removed.")
示例#14
0
    def test_render_GET_malicious_javascript(self):
        """Test rendering a request when the some of the bridges returned have
        malicious (HTML, Javascript, etc., in their) PT arguments.
        """
        self.useMaliciousBridges()

        request = DummyRequest([self.pagename])
        request.method = b'GET'
        request.getClientIP = lambda: '1.1.1.1'

        page = self.bridgesResource.render(request)
        self.assertTrue(
            "evil=<script>alert('fuuuu');</script>" in str(page),
            ("The characters &, <, >, ', and \" in bridge lines should be "
             "replaced with their corresponding HTML special characters."))
示例#15
0
    def test_render_GET_malicious_javascript(self):
        """Test rendering a request when the some of the bridges returned have
        malicious (HTML, Javascript, etc., in their) PT arguments.
        """
        self.useMaliciousBridges()

        request = DummyRequest([self.pagename])
        request.method = b'GET'
        request.getClientIP = lambda: '1.1.1.1'

        page = self.bridgesResource.render(request)
        self.assertTrue(
            "evil=&lt;script&gt;alert(&#39;fuuuu&#39;);&lt;/script&gt;"
            in str(page),
            ("The characters &, <, >, ', and \" in bridge lines should be "
             "replaced with their corresponding HTML special characters."))
示例#16
0
    def test_renderAnswer_GET_textplain_malicious(self):
        """If the request format specifies 'plain', we should return content
        with mimetype 'text/plain' and ASCII control characters replaced.
        """
        self.useMaliciousBridges()

        request = DummyRequest([self.pagename])
        request.args.update({'format': ['plain']})
        request.getClientIP = lambda: '4.4.4.4'
        request.method = b'GET'

        page = self.bridgesResource.render(request)
        self.assertTrue("html" not in str(page))
        self.assertTrue(
            'eww=Bridge 1.2.3.4:1234' in str(page),
            "Return characters in bridge lines should be removed.")
        self.assertTrue('bad=Bridge 6.6.6.6:6666' in str(page),
                        "Newlines in bridge lines should be removed.")
示例#17
0
    def test_renderAnswer_textplain_error(self):
        """If we hit some error while returning bridge lines in text/plain
        format, then our custom plaintext error message (the hardcoded HTML in
        ``server.replaceErrorPage``) should be returned.
        """
        self.useBenignBridges()

        request = DummyRequest([self.pagename])
        request.args.update({'format': ['plain']})
        request.getClientIP = lambda: '4.4.4.4'
        request.method = b'GET'

        # We'll cause a TypeError here due to calling '\n'.join(None)
        page = self.bridgesResource.renderAnswer(request, bridgeLines=None)

        # We don't want the fancy version:
        self.assertNotSubstring("Bad News Bears", page)
        self.assertSubstring("Sorry! Something went wrong with your request.",
                             page)
示例#18
0
    def test_renderAnswer_textplain_error(self):
        """If we hit some error while returning bridge lines in text/plain
        format, then our custom plaintext error message (the hardcoded HTML in
        ``server.replaceErrorPage``) should be returned.
        """
        self.useBenignBridges()

        request = DummyRequest([self.pagename])
        request.args.update({'format': ['plain']})
        request.getClientIP = lambda: '4.4.4.4'
        request.method = b'GET'

        # We'll cause a TypeError here due to calling '\n'.join(None)
        page = self.bridgesResource.renderAnswer(request, bridgeLines=None)

        # We don't want the fancy version:
        self.assertNotSubstring(b"Bad Request", page)
        self.assertSubstring(b"Sorry! Something went wrong with your request.",
                             page)
示例#19
0
    def test_renderAnswer_GET_textplain_malicious(self):
        """If the request format specifies 'plain', we should return content
        with mimetype 'text/plain' and ASCII control characters replaced.
        """
        self.useMaliciousBridges()

        request = DummyRequest([self.pagename])
        request.args.update({'format': ['plain']})
        request.getClientIP = lambda: '4.4.4.4'
        request.method = b'GET'

        page = self.bridgesResource.render(request)
        self.assertTrue("html" not in str(page))
        self.assertTrue(
            'eww=Bridge 1.2.3.4:1234' in str(page),
            "Return characters in bridge lines should be removed.")
        self.assertTrue(
            'bad=Bridge 6.6.6.6:6666' in str(page),
            "Newlines in bridge lines should be removed.")
示例#20
0
    def test_render_GET_RTLlang(self):
        """Test rendering a request for plain bridges in Arabic."""
        self.useBenignBridges()

        request = DummyRequest([b"bridges?transport=obfs3"])
        request.method = b'GET'
        request.getClientIP = lambda: '3.3.3.3'
        # For some strange reason, the 'Accept-Language' value *should not* be
        # a list, unlike all the other headers and args…
        request.headers.update({'accept-language': 'ar,en,en_US,'})

        page = self.bridgesResource.render(request)
        self.assertSubstring("rtl.css", page)
        self.assertSubstring(
            # "I need an alternative way to get bridges!"
            "أحتاج إلى وسيلة بديلة للحصول على bridges", page)

        for bridgeLine in self.parseBridgesFromHTMLPage(page):
            # Check that each bridge line had the expected number of fields:
            bridgeLine = bridgeLine.split(' ')
            self.assertEqual(len(bridgeLine), 2)
示例#21
0
    def test_render_GET_vanilla(self):
        """Test rendering a request for normal, vanilla bridges."""
        self.useBenignBridges()

        request = DummyRequest([self.pagename])
        request.method = b'GET'
        request.getClientIP = lambda: '1.1.1.1'

        page = self.bridgesResource.render(request)

        # The response should explain how to use the bridge lines:
        self.assertTrue("To enter bridges into Tor Browser" in str(page))

        for b in self.parseBridgesFromHTMLPage(page):
            # Check that each bridge line had the expected number of fields:
            fields = b.split(' ')
            self.assertEqual(len(fields), 2)

            # Check that the IP and port seem okay:
            ip, port = fields[0].rsplit(':')
            self.assertIsInstance(ipaddr.IPv4Address(ip), ipaddr.IPv4Address)
            self.assertIsInstance(int(port), int)
            self.assertGreater(int(port), 0)
            self.assertLessEqual(int(port), 65535)