GitLab is used only for code review, issue tracking and project management. Canonical locations for source code are still https://gitweb.torproject.org/ https://git.torproject.org/ and git-rw.torproject.org.

Commit a6c55026 authored by Alex Catarineu's avatar Alex Catarineu

Bug 40001: Add test for 'Communicating security expectations TB patch'

parent 72d4af38
......@@ -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 {
......
......@@ -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',
......
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")')
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<img src="http://www.torproject.org/static/images/tor-logo@2x.png"/>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<iframe src="http://www.torproject.org"></iframe>
</body>
</html>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment