[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [stem/master] ExitPolicy support for accept6 and reject6 rules
commit 12c2a7ec541fb11c5e00a0c67a47176f40606076
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
Date: Fri Mar 4 08:39:53 2016 -0800
ExitPolicy support for accept6 and reject6 rules
Thanks to teor for explaining these! Adding support for these exit policy rule
types...
https://trac.torproject.org/projects/tor/ticket/16103#comment:5
---
docs/change_log.rst | 1 +
stem/exit_policy.py | 37 +++++++++++++++++++++++++++----------
test/unit/exit_policy/rule.py | 19 +++++++++++++++++++
3 files changed, 47 insertions(+), 10 deletions(-)
diff --git a/docs/change_log.rst b/docs/change_log.rst
index 57667e1..8a92788 100644
--- a/docs/change_log.rst
+++ b/docs/change_log.rst
@@ -47,6 +47,7 @@ The following are only available within Stem's `git repository
* Dramatic, `300x performance improvement <https://github.com/DonnchaC/stem/pull/1>`_ for reading from the control port with python 3
* 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`)
* 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 293095b..0f80032 100644
--- a/stem/exit_policy.py
+++ b/stem/exit_policy.py
@@ -632,7 +632,12 @@ class ExitPolicyRule(object):
This should be treated as an immutable object.
+ .. versionchanged:: 1.5.0
+ Support for 'accept6/reject6' entries and our **is_ipv6_only** attribute.
+
: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
:var str address: address that this rule is for
@@ -645,17 +650,18 @@ class ExitPolicyRule(object):
"""
def __init__(self, rule):
- # policy ::= "accept" exitpattern | "reject" exitpattern
+ # policy ::= "accept[6]" exitpattern | "reject[6]" exitpattern
# exitpattern ::= addrspec ":" portspec
- if rule.startswith('accept'):
- self.is_accept = True
- elif rule.startswith('reject'):
- self.is_accept = False
- else:
- raise ValueError("An exit policy must start with either 'accept' or 'reject': %s" % rule)
+ self.is_accept = rule.startswith('accept')
+ self.is_ipv6_only = rule.startswith('accept6') or rule.startswith('reject6')
- exitpattern = rule[6:]
+ if rule.startswith('accept6') or rule.startswith('reject6'):
+ exitpattern = rule[7:]
+ elif rule.startswith('accept') or rule.startswith('reject'):
+ exitpattern = rule[6:]
+ else:
+ raise ValueError("An exit policy must start with either 'accept[6]' or 'reject[6]': %s" % rule)
if not exitpattern.startswith(' '):
raise ValueError('An exit policy should have a space separating its accept/reject from the exit pattern: %s' % rule)
@@ -738,6 +744,9 @@ class ExitPolicyRule(object):
# validate our input and check if the argument doesn't match our address type
if address is not None:
+ if self.is_ipv6_only and stem.util.connection.is_valid_ipv4_address(address):
+ return False # accept6/reject6 don't match ipv4
+
address_type = self.get_address_type()
if stem.util.connection.is_valid_ipv4_address(address):
@@ -868,7 +877,10 @@ class ExitPolicyRule(object):
to re-create this rule.
"""
- label = 'accept ' if self.is_accept else 'reject '
+ if self.is_ipv6_only:
+ label = 'accept6 ' if self.is_accept else 'reject6 '
+ else:
+ label = 'accept ' if self.is_accept else 'reject '
if self.is_address_wildcard():
label += '*:'
@@ -906,7 +918,7 @@ class ExitPolicyRule(object):
if self._hash is None:
my_hash = 0
- for attr in ('is_accept', 'address', 'min_port', 'max_port'):
+ for attr in ('is_accept', 'is_ipv6_only', 'address', 'min_port', 'max_port'):
my_hash *= 1024
attr_value = getattr(self, attr)
@@ -951,6 +963,10 @@ class ExitPolicyRule(object):
# ip4mask ::= an IPv4 mask in dotted-quad format
# num_ip4_bits ::= an integer between 0 and 32
+ if self.is_ipv6_only:
+ rule_start = 'accept6' if self.is_accept else 'reject6'
+ raise ValueError("'%s' rules should have an IPv6 address, not IPv4 (%s)" % (rule_start, self.address))
+
self._address_type = _address_type_to_int(AddressType.IPv4)
if addr_extra is None:
@@ -1054,6 +1070,7 @@ class MicroExitPolicyRule(ExitPolicyRule):
def __init__(self, is_accept, min_port, max_port):
self.is_accept = is_accept
+ self.is_ipv6_only = False
self.address = None # wildcard address
self.min_port = min_port
self.max_port = max_port
diff --git a/test/unit/exit_policy/rule.py b/test/unit/exit_policy/rule.py
index ecd96a8..9ff0181 100644
--- a/test/unit/exit_policy/rule.py
+++ b/test/unit/exit_policy/rule.py
@@ -42,6 +42,8 @@ class TestExitPolicyRule(unittest.TestCase):
test_inputs = (
'accept *:*',
'reject *:*',
+ 'accept6 *:*',
+ 'reject6 *:*',
'accept *:80',
'accept *:80-443',
'accept 127.0.0.1:80',
@@ -83,6 +85,10 @@ class TestExitPolicyRule(unittest.TestCase):
'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),
+ 'reject6 *:*': (True, True),
+ 'reject6 *:80': (True, False),
+ 'reject6 [0000:0000:0000:0000:0000:0000:0000:0000]/128:80': (False, False),
+
'accept 192.168.0.1:0-65535': (False, True),
'accept 192.168.0.1:1-65535': (False, True),
'accept 192.168.0.1:2-65535': (False, False),
@@ -352,3 +358,16 @@ class TestExitPolicyRule(unittest.TestCase):
for match_args, expected_result in matches.items():
self.assertEqual(expected_result, rule.is_match(*match_args))
+
+ def test_ipv6_only_entries(self):
+ # accept6/reject6 shouldn't allow ipv4 addresses
+
+ self.assertRaises(ValueError, ExitPolicyRule, 'accept6 192.168.0.1:*')
+ self.assertRaises(ValueError, ExitPolicyRule, 'reject6 192.168.0.1:*')
+
+ # wildcards match all ipv6 but *not* ipv4
+
+ rule = ExitPolicyRule('accept6 *:*')
+ self.assertTrue(rule.is_ipv6_only)
+ self.assertTrue(rule.is_match('FE80:0000:0000:0000:0202:B3FF:FE1E:8329', 443))
+ self.assertFalse(rule.is_match('192.168.0.1', 443))
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits