[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