commit 200dd8ad376257ee9e1ee4713254d6f4ba1c9f17 Author: Damian Johnson atagar@torproject.org Date: Fri Mar 4 09:30:29 2016 -0800
Expand *4 and *6 exit poicy wildcards
Like accept6 and reject6, we have a couple new wildcards to specify all IPv4 or IPv6 addresses. This is akin to being a '/0' so simply translating 'em into that. :P --- docs/change_log.rst | 1 + stem/exit_policy.py | 34 ++++++++++++++-------------------- test/unit/exit_policy/rule.py | 28 +++++++++++++++++++++++++--- 3 files changed, 40 insertions(+), 23 deletions(-)
diff --git a/docs/change_log.rst b/docs/change_log.rst index 8a92788..b01602a 100644 --- a/docs/change_log.rst +++ b/docs/change_log.rst @@ -48,6 +48,7 @@ The following are only available within Stem's `git repository * Added `stem.manual <api/manual.html>`_, which provides information available about Tor from `its manual https://www.torproject.org/docs/tor-manual.html.en`_ (:trac:`8251`) * :func:`~stem.connection.connect` and :func:`~stem.control.Controller.from_port` now connect to both port 9051 (relay's default) and 9151 (Tor Browser's default) (:trac:`16075`) * :class:`~stem.exit_policy.ExitPolicy` support for *accept6* and *reject6* rules (:trac:`16103`) + * :class:`~stem.exit_policy.ExitPolicy` support for **4* and **6* wildcards (:trac:`16103`) * Added `support for NETWORK_LIVENESS events <api/response.html#stem.response.events.NetworkLivenessEvent>`_ (:spec:`44aac63`) * Added :func:`~stem.control.Controller.is_set` to the :class:`~stem.control.Controller` * Added :func:`~stem.control.Controller.is_user_traffic_allowed` to the :class:`~stem.control.Controller` diff --git a/stem/exit_policy.py b/stem/exit_policy.py index 587ef14..f71a638 100644 --- a/stem/exit_policy.py +++ b/stem/exit_policy.py @@ -153,12 +153,6 @@ def get_config_policy(rules, ip_address = None): else: result.append(ExitPolicyRule(rule))
- # torrc policies can apply to IPv4 or IPv6, so we need to make sure /0 - # addresses aren't treated as being a full wildcard - - for rule in result: - rule._submask_wildcard = False - return ExitPolicy(*result)
@@ -635,6 +629,9 @@ class ExitPolicyRule(object): .. versionchanged:: 1.5.0 Support for 'accept6/reject6' entries and our **is_ipv6_only** attribute.
+ .. versionchanged:: 1.5.0 + Support for '*4' and '*6' wildcards. + :var bool is_accept: indicates if exiting is allowed or disallowed :var bool is_ipv6_only: indicates if this is an accept6 or reject6 rule, only matching ipv6 addresses @@ -695,11 +692,6 @@ class ExitPolicyRule(object): self._apply_addrspec(rule, addrspec) self._apply_portspec(rule, portspec)
- # If true then a submask of /0 is treated by is_address_wildcard() as being - # a wildcard. - - self._submask_wildcard = True - # Flags to indicate if this rule seems to be expanded from the 'private' # keyword or tor's default policy suffix.
@@ -708,20 +700,14 @@ class ExitPolicyRule(object):
def is_address_wildcard(self): """ - **True** if we'll match against any address, **False** otherwise. + **True** if we'll match against **any** address, **False** otherwise.
- Note that if this policy can apply to both IPv4 and IPv6 then this is - different from being for a /0 (since, for instance, 0.0.0.0/0 wouldn't - match against an IPv6 address). That said, /0 addresses are highly unusual - and most things citing exit policies are IPv4 specific anyway, making this - moot. + Note that this is different than *4, *6, or '/0' address which are + wildcards for only either IPv4 or IPv6.
:returns: **bool** for if our address matching is a wildcard """
- if self._submask_wildcard and self.get_masked_bits() == 0: - return True - return self._address_type == _address_type_to_int(AddressType.WILDCARD)
def is_port_wildcard(self): @@ -960,6 +946,14 @@ class ExitPolicyRule(object): # Parses the addrspec... # addrspec ::= "*" | ip4spec | ip6spec
+ # Expand IPv4 and IPv6 specific wildcards into /0 entries so we have one + # fewer bizarre special case headaches to deal with. + + if addrspec == '*4': + addrspec = '0.0.0.0/0' + elif addrspec == '*6': + addrspec = '[0000:0000:0000:0000:0000:0000:0000:0000]/0' + if '/' in addrspec: self.address, addr_extra = addrspec.split('/', 1) else: diff --git a/test/unit/exit_policy/rule.py b/test/unit/exit_policy/rule.py index 780f7cb..59dc5d2 100644 --- a/test/unit/exit_policy/rule.py +++ b/test/unit/exit_policy/rule.py @@ -44,6 +44,7 @@ class TestExitPolicyRule(unittest.TestCase): 'reject *:*', 'accept6 *:*', 'reject6 *:*', + 'accept *:80', 'accept *:80-443', 'accept 127.0.0.1:80', @@ -64,6 +65,11 @@ class TestExitPolicyRule(unittest.TestCase): 'accept 192.168.0.1/255.255.255.0:80': 'accept 192.168.0.1/24:80', 'accept [::]/32:*': 'accept [0000:0000:0000:0000:0000:0000:0000:0000]/32:*', 'accept [::]/128:*': 'accept [0000:0000:0000:0000:0000:0000:0000:0000]:*', + + 'accept *4:*': 'accept 0.0.0.0/0:*', + 'accept *6:*': 'accept [0000:0000:0000:0000:0000:0000:0000:0000]/0:*', + 'accept6 *4:*': 'accept6 0.0.0.0/0:*', + 'accept6 *6:*': 'accept6 [0000:0000:0000:0000:0000:0000:0000:0000]/0:*', }
for rule_arg, expected_str in test_inputs.items(): @@ -77,11 +83,16 @@ class TestExitPolicyRule(unittest.TestCase): 'accept 192.168.0.1:*': (False, True), 'accept 192.168.0.1:80': (False, False),
- 'reject 127.0.0.1/0:*': (True, True), - 'reject 127.0.0.1/0.0.0.0:*': (True, True), + 'reject *4:*': (False, True), + 'reject *6:*': (False, True), + 'reject6 *4:*': (False, True), + 'reject6 *6:*': (False, True), + + 'reject 127.0.0.1/0:*': (False, True), + 'reject 127.0.0.1/0.0.0.0:*': (False, True), 'reject 127.0.0.1/16:*': (False, True), 'reject 127.0.0.1/32:*': (False, True), - 'reject [0000:0000:0000:0000:0000:0000:0000:0000]/0:80': (True, False), + 'reject [0000:0000:0000:0000:0000:0000:0000:0000]/0:80': (False, False), 'reject [0000:0000:0000:0000:0000:0000:0000:0000]/64:80': (False, False), 'reject [0000:0000:0000:0000:0000:0000:0000:0000]/128:80': (False, False),
@@ -256,6 +267,14 @@ class TestExitPolicyRule(unittest.TestCase): (None, None, False): False, (None, None, True): True, }, + 'reject *4:*': { + ('192.168.0.1', 80): True, + ('FE80:0000:0000:0000:0202:B3FF:FE1E:8329', 80): False, + }, + 'reject *6:*': { + ('192.168.0.1', 80): False, + ('FE80:0000:0000:0000:0202:B3FF:FE1E:8329', 80): True, + }, }
for rule_arg, matches in test_inputs.items(): @@ -368,6 +387,9 @@ class TestExitPolicyRule(unittest.TestCase): self.assertFalse(rule.is_match('FE80:0000:0000:0000:0202:B3FF:FE1E:8329')) self.assertFalse(rule.is_match())
+ rule = ExitPolicyRule('accept6 *4:*') + self.assertTrue(rule._skip_rule) + # wildcards match all ipv6 but *not* ipv4
rule = ExitPolicyRule('accept6 *:*')