[tor-commits] [stem/master] Switching exit policy's can_exit_to() and is_match() be permissive

atagar at torproject.org atagar at torproject.org
Sun Mar 24 02:57:13 UTC 2013


commit caee7d6c968fd6cd9912dc4a554d66e303316b61
Author: Damian Johnson <atagar at torproject.org>
Date:   Sat Mar 23 19:50:52 2013 -0700

    Switching exit policy's can_exit_to() and is_match() be permissive
    
    Switching how the ExitPolicy's can_exit_to() and ExitPolicyRule's is_match()
    handle an undefined address or port. Previously we reported if we matched or
    allowed exiting to *all* instance of the defined destination. Now, however,
    rather if we match against *any*.
    
    Change was requested by Aaron Johnson. You can still get the old behavior by
    setting the 'strict' argument.
---
 stem/exit_policy.py           |   29 ++++++++++++++++++-----------
 test/unit/exit_policy/rule.py |   33 ++++++++++++++++++++++-----------
 2 files changed, 40 insertions(+), 22 deletions(-)

diff --git a/stem/exit_policy.py b/stem/exit_policy.py
index d187d62..2b0d6d4 100644
--- a/stem/exit_policy.py
+++ b/stem/exit_policy.py
@@ -156,29 +156,31 @@ class ExitPolicy(object):
     self._summary_representation = None
     self._can_exit_to_cache = {}
 
-  def can_exit_to(self, address = None, port = None):
+  def can_exit_to(self, address = None, port = None, strict = False):
     """
     Checks if this policy allows exiting to a given destination or not. If the
-    address or port is omitted then this will check if we allow for its
-    wildcard.
+    address or port is omitted then this will check if we're allowed to exit to
+    any instances of the defined address or port.
 
     :param str address: IPv4 or IPv6 address (with or without brackets)
     :param int port: port number
+    :param bool strict: if the address or port is excluded then check if we can
+      exit to **all** instances of the defined address or port
 
     :returns: **True** if exiting to this destination is allowed, **False** otherwise
     """
 
-    if not (address, port) in self._can_exit_to_cache:
+    if not (address, port, strict) in self._can_exit_to_cache:
       result = self._is_allowed_default
 
       for rule in self._get_rules():
-        if rule.is_match(address, port):
+        if rule.is_match(address, port, strict):
           result = rule.is_accept
           break
 
-      self._can_exit_to_cache[(address, port)] = result
+      self._can_exit_to_cache[(address, port, strict)] = result
 
-    return self._can_exit_to_cache[(address, port)]
+    return self._can_exit_to_cache[(address, port, strict)]
 
   def is_exiting_allowed(self):
     """
@@ -529,13 +531,16 @@ class ExitPolicyRule(object):
 
     return self.min_port in (0, 1) and self.max_port == 65535
 
-  def is_match(self, address = None, port = None):
+  def is_match(self, address = None, port = None, strict = False):
     """
     **True** if we match against the given destination, **False** otherwise. If
-    the address or port is omitted then that'll only match against a wildcard.
+    the address or port is omitted then this will check if we're allowed to
+    exit to any instances of the defined address or port.
 
     :param str address: IPv4 or IPv6 address (with or without brackets)
     :param int port: port number
+    :param bool strict: if the address or port is excluded then check if we can
+      exit to **all** instances of the defined address or port
 
     :returns: **bool** indicating if we match against this destination
 
@@ -566,7 +571,8 @@ class ExitPolicyRule(object):
       # mask applied matches.
 
       if address is None:
-        return False
+        if strict:
+          return False
       else:
         comparison_addr_bin = int(stem.util.connection._get_address_binary(address), 2)
         comparison_addr_bin &= self._get_mask_bin()
@@ -576,7 +582,8 @@ class ExitPolicyRule(object):
 
     if not self.is_port_wildcard():
       if port is None:
-        return False
+        if strict:
+          return False
       elif port < self.min_port or port > self.max_port:
         return False
 
diff --git a/test/unit/exit_policy/rule.py b/test/unit/exit_policy/rule.py
index 1bf3911..0fe369b 100644
--- a/test/unit/exit_policy/rule.py
+++ b/test/unit/exit_policy/rule.py
@@ -216,8 +216,10 @@ class TestExitPolicyRule(unittest.TestCase):
         ("FE80:0000:0000:0000:0202:B3FF:FE1E:8329", 80): True,
         ("[FE80:0000:0000:0000:0202:B3FF:FE1E:8329]", 80): True,
         ("192.168.0.1", None): True,
-        (None, 80): True,
-        (None, None): True,
+        (None, 80, False): True,
+        (None, 80, True): True,
+        (None, None, False): True,
+        (None, None, True): True,
       },
       "reject 255.255.255.255/0:*": {
         ("192.168.0.1", 80): True,
@@ -226,8 +228,10 @@ class TestExitPolicyRule(unittest.TestCase):
         ("FE80:0000:0000:0000:0202:B3FF:FE1E:8329", 80): False,
         ("[FE80:0000:0000:0000:0202:B3FF:FE1E:8329]", 80): False,
         ("192.168.0.1", None): True,
-        (None, 80): False,
-        (None, None): False,
+        (None, 80, False): True,
+        (None, 80, True): False,
+        (None, None, False): True,
+        (None, None, True): False,
       },
     }
 
@@ -249,7 +253,8 @@ class TestExitPolicyRule(unittest.TestCase):
         ("192.168.0.50", 80): True,
         ("192.168.0.51", 80): False,
         ("192.168.0.49", 80): False,
-        (None, 80): False,
+        (None, 80, False): True,
+        (None, 80, True): False,
         ("192.168.0.50", None): True,
       },
       "reject 0.0.0.0/24:*": {
@@ -259,7 +264,8 @@ class TestExitPolicyRule(unittest.TestCase):
         ("0.0.1.0", 80): False,
         ("0.1.0.0", 80): False,
         ("1.0.0.0", 80): False,
-        (None, 80): False,
+        (None, 80, False): True,
+        (None, 80, True): False,
         ("0.0.0.0", None): True,
       },
     }
@@ -278,7 +284,8 @@ class TestExitPolicyRule(unittest.TestCase):
         ("[FE80:0000:0000:0000:0202:B3FF:FE1E:8329]", 80): True,
         ("FE80:0000:0000:0000:0202:B3FF:FE1E:8330", 80): False,
         ("FE80:0000:0000:0000:0202:B3FF:FE1E:8328", 80): False,
-        (None, 80): False,
+        (None, 80, False): True,
+        (None, 80, True): False,
         ("FE80:0000:0000:0000:0202:B3FF:FE1E:8329", None): True,
       },
       "reject [FE80:0000:0000:0000:0202:B3FF:FE1E:8329]/112:*": {
@@ -287,8 +294,10 @@ class TestExitPolicyRule(unittest.TestCase):
         ("FE80:0000:0000:0000:0202:B3FF:FE1E:FFFF", 80): True,
         ("FE80:0000:0000:0000:0202:B3FF:FE1F:8329", 80): False,
         ("FE81:0000:0000:0000:0202:B3FF:FE1E:8329", 80): False,
-        (None, 80): False,
-        ("FE80:0000:0000:0000:0202:B3FF:FE1E:8329", None): True,
+        (None, 80, False): True,
+        (None, 80, True): False,
+        ("FE80:0000:0000:0000:0202:B3FF:FE1E:8329", None, False): True,
+        ("FE80:0000:0000:0000:0202:B3FF:FE1E:8329", None, True): True,
       },
     }
 
@@ -305,7 +314,8 @@ class TestExitPolicyRule(unittest.TestCase):
         ("192.168.0.50", 81): False,
         ("192.168.0.50", 79): False,
         (None, 80): True,
-        ("192.168.0.50", None): False,
+        ("192.168.0.50", None, False): True,
+        ("192.168.0.50", None, True): False,
       },
       "reject *:80-85": {
         ("192.168.0.50", 79): False,
@@ -314,7 +324,8 @@ class TestExitPolicyRule(unittest.TestCase):
         ("192.168.0.50", 85): True,
         ("192.168.0.50", 86): False,
         (None, 83): True,
-        ("192.168.0.50", None): False,
+        ("192.168.0.50", None, False): True,
+        ("192.168.0.50", None, True): False,
       },
     }
 



More information about the tor-commits mailing list