[tor-commits] [tor-browser-bundle-testsuite/master] Bug 40001: Add test for 'Communicating security expectations TB patch'

gk at torproject.org gk at torproject.org
Thu Oct 15 18:41:27 UTC 2020


commit a6c55026833dbdb0a7769d7352579fd796e7573c
Author: Alex Catarineu <acat at torproject.org>
Date:   Mon Jun 29 19:37:00 2020 +0200

    Bug 40001: Add test for 'Communicating security expectations TB patch'
---
 TBBTestSuite/TestSuite/BrowserBundleTests.pm       |   6 +
 marionette/setup.py                                |   1 +
 .../test_onion_security_expectations.py            | 134 +++++++++++++++++++++
 test-data/mixed.html                               |   8 ++
 test-data/mixed_active.html                        |   8 ++
 5 files changed, 157 insertions(+)

diff --git a/TBBTestSuite/TestSuite/BrowserBundleTests.pm b/TBBTestSuite/TestSuite/BrowserBundleTests.pm
index 4a8908e..834641e 100644
--- a/TBBTestSuite/TestSuite/BrowserBundleTests.pm
+++ b/TBBTestSuite/TestSuite/BrowserBundleTests.pm
@@ -476,6 +476,12 @@ our @tests = (
         # Bug 30432: temporarily disable test
         enable          => sub { undef },
     },
+    {
+        name            => 'onion_security_expectations',
+        type            => 'marionette',
+        use_net         => 1,
+        descr           => 'Check onion security expectations',
+    },
 );
 
 sub set_test_prefs {
diff --git a/marionette/setup.py b/marionette/setup.py
index 78f4522..9dc9772 100644
--- a/marionette/setup.py
+++ b/marionette/setup.py
@@ -5,6 +5,7 @@ PACKAGE_VERSION = '0.3'
 deps = [
         'marionette_harness == 5.0.0',
         'marionette_driver == 3.0.0',
+        'stem == 1.8.0',
 ]
 
 setup(name='tor-browser-tests',
diff --git a/marionette/tor_browser_tests/test_onion_security_expectations.py b/marionette/tor_browser_tests/test_onion_security_expectations.py
new file mode 100644
index 0000000..866ae1e
--- /dev/null
+++ b/marionette/tor_browser_tests/test_onion_security_expectations.py
@@ -0,0 +1,134 @@
+from marionette_driver import By, Wait
+from marionette_driver.errors import MarionetteException, NoSuchElementException, TimeoutException
+from marionette_driver.legacy_actions import Actions
+from marionette_harness import MarionetteTestCase, WindowManagerMixin
+
+import testsuite
+
+from stem.control import Controller
+
+from urlparse import urlparse
+
+import time
+
+class OnionFixturesMixin(object):
+    def setUp(self):
+        super(OnionFixturesMixin, self).setUp()
+        tor_control_port = testsuite.TestSuite(
+        ).t['options']['tor-control-port']
+        with Controller.from_port(port=int(tor_control_port)) as controller:
+            controller.authenticate()
+            port = urlparse(self.marionette.absolute_url('')).port
+            response = controller.create_ephemeral_hidden_service(
+                {80: port},
+                key_content='ED25519-V3',
+                await_publication=True,
+                detached=True,
+            )
+            self.service_id = response.service_id
+
+    def tearDown(self):
+        tor_control_port = testsuite.TestSuite(
+        ).t['options']['tor-control-port']
+        with Controller.from_port(port=int(tor_control_port)) as controller:
+            controller.authenticate()
+            controller.remove_ephemeral_hidden_service(self.service_id)
+        super(OnionFixturesMixin, self).tearDown()
+
+
+class Test(OnionFixturesMixin, WindowManagerMixin, MarionetteTestCase):
+    def get_identity_class(self):
+        with self.marionette.using_context('chrome'):
+            return self.marionette.execute_script('''
+                return document.getElementById("identity-box").className;
+            ''')
+
+    def get_identity_icon(self):
+        with self.marionette.using_context('chrome'):
+            return self.marionette.execute_script('''
+                const el = document.getElementById("identity-icon");
+                return document.defaultView.getComputedStyle(el)["list-style-image"];
+            ''')
+
+    def get_connection_type(self):
+        m = self.marionette
+        with self.marionette.using_context('chrome'):
+            self.execute_chrome(
+                'document.getElementById("identity-popup-more-info").click()')
+            m.switch_to_window(m.chrome_window_handles[1])
+            Wait(m, timeout=m.timeout.page_load).until(
+                lambda _: m.find_element('id', 'security-technical-shortform').text != '')
+            text = m.find_element('id', 'security-technical-shortform').text
+            m.close_chrome_window()
+            m.switch_to_window(self.start_window)
+            return text
+
+    def execute_chrome(self, script):
+        with self.marionette.using_context('chrome'):
+            return self.marionette.execute_script(script)
+
+    def test_onion_security_expectations(self):
+        m = self.marionette
+        m.timeout.implicit = 10
+
+        # Wait some more time to make sure the onion service is set up
+        time.sleep(10)
+
+        # Regular onion
+        with m.using_context('content'):
+            m.navigate('http://' + self.service_id + '.onion')
+            self.assertTrue(self.execute_chrome(
+                "return !!gIdentityHandler._isSecureConnection;"))
+            self.assertEqual(self.get_identity_class(), 'onionUnknownIdentity')
+            self.assertEqual(self.get_connection_type(),
+                             'Connection Encrypted (Onion Service)')
+            self.assertEqual(self.get_identity_icon(),
+                             'url("chrome://browser/skin/onion.svg")')
+
+        # Onion with mixed display content
+        with m.using_context('content'):
+            m.navigate('http://' + self.service_id + '.onion/mixed.html')
+            self.assertFalse(self.execute_chrome(
+                "return !!gIdentityHandler._isSecureConnection;"))
+            self.assertEqual(self.get_identity_class(),
+                             'onionUnknownIdentity onionMixedDisplayContent')
+            self.assertEqual(self.get_connection_type(),
+                             'Connection Partially Encrypted')
+            self.assertEqual(self.get_identity_icon(),
+                             'url("chrome://browser/skin/onion-warning.svg")')
+
+        # Onion with mixed active content
+        with m.using_context('content'):
+            m.navigate('http://' + self.service_id +
+                       '.onion/mixed_active.html')
+            self.assertTrue(self.execute_chrome(
+                "return !!gIdentityHandler._isSecureConnection;"))
+            self.assertEqual(self.get_identity_class(), 'onionUnknownIdentity')
+            self.assertEqual(self.get_connection_type(),
+                             'Connection Encrypted (Onion Service)')
+            self.assertEqual(self.get_identity_icon(),
+                             'url("chrome://browser/skin/onion.svg")')
+            # Reload with mixed content protection disabled
+            self.execute_chrome(
+                'gIdentityHandler.disableMixedContentProtection();')
+            Wait(m, timeout=m.timeout.page_load).until(
+                lambda _: self.get_identity_class() != 'onionUnknownIdentity')
+            self.assertFalse(self.execute_chrome(
+                "return !!gIdentityHandler._isSecureConnection;"))
+            self.assertEqual(self.get_identity_class(),
+                             'onionUnknownIdentity onionMixedActiveContent')
+            self.assertEqual(self.get_connection_type(),
+                             'Connection Partially Encrypted')
+            self.assertEqual(self.get_identity_icon(),
+                             'url("chrome://browser/skin/onion-slash.svg")')
+
+        # Onion with valid TLS certificate
+        with m.using_context('content'):
+            m.navigate('https://3g2upl4pq6kufc4m.onion/')
+            self.assertTrue(self.execute_chrome(
+                "return !!gIdentityHandler._isSecureConnection;"))
+            self.assertEqual(self.get_identity_class(), 'onionVerifiedDomain')
+            self.assertEqual(self.get_connection_type(
+            ), 'Connection Encrypted (Onion Service, TLS_AES_256_GCM_SHA384, 256 bit keys, TLS 1.3)')
+            self.assertEqual(self.get_identity_icon(),
+                             'url("chrome://browser/skin/onion.svg")')
diff --git a/test-data/mixed.html b/test-data/mixed.html
new file mode 100644
index 0000000..3de98a1
--- /dev/null
+++ b/test-data/mixed.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<html>
+  <head>
+  </head>
+  <body>
+    <img src="http://www.torproject.org/static/images/tor-logo@2x.png"/>
+  </body>
+</html>
diff --git a/test-data/mixed_active.html b/test-data/mixed_active.html
new file mode 100644
index 0000000..23430ab
--- /dev/null
+++ b/test-data/mixed_active.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<html>
+  <head>
+  </head>
+  <body>
+    <iframe src="http://www.torproject.org"></iframe>
+  </body>
+</html>





More information about the tor-commits mailing list