[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[tor-commits] [stem/master] ExitPolicy's behavior around 'strictness' was incorrect



commit db0518c03e2b79500a9132fa82e077fa978972fa
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
Date:   Wed Jan 28 10:15:51 2015 -0800

    ExitPolicy's behavior around 'strictness' was incorrect
    
    Our docs state that...
    
    * 'strict' is true: we can exit to *all* instances of the given address or port
    * 'strict' is false: we can exit to *any* instances of the given address or port
    
    Caught thanks to nskinkel...
    
      https://trac.torproject.org/projects/tor/ticket/14314
---
 docs/change_log.rst             |    4 ++++
 stem/exit_policy.py             |   19 ++++++++++++++-----
 test/unit/exit_policy/policy.py |   11 +++++++++++
 test/unit/exit_policy/rule.py   |   32 ++++++++++++++++----------------
 4 files changed, 45 insertions(+), 21 deletions(-)

diff --git a/docs/change_log.rst b/docs/change_log.rst
index e60dd35..21c2105 100644
--- a/docs/change_log.rst
+++ b/docs/change_log.rst
@@ -49,6 +49,10 @@ performance
 Stem also now runs directly under both python2 and python3 without a 2to3
 conversion (:trac:`14075`).
 
+ * **Controller**
+
+  * The 'strict' argument of :func:`~stem.exit_policy.ExitPolicy.can_exit_to` didn't behave as documented (:trac:`14314`)
+
  * **Descriptors**
 
   * Lazy-loading descriptors, improving performance by 25-70% depending on what type it is (:trac:`14011`)
diff --git a/stem/exit_policy.py b/stem/exit_policy.py
index 53d0043..16f8721 100644
--- a/stem/exit_policy.py
+++ b/stem/exit_policy.py
@@ -748,14 +748,21 @@ class ExitPolicyRule(object):
     if port is not None and not stem.util.connection.is_valid_port(port):
       raise ValueError("'%s' isn't a valid port" % port)
 
+    # If we're not matching against an address or port but the rule has one
+    # then we're a fuzzy match. When that happens...
+    #
+    # * If strict and a reject rule then we're a match ('can exit to *all* instances').
+    # * If not strict and an accept rule then match ('an exit ot *any* instance').
+
+    fuzzy_match = False
+
     if not self.is_address_wildcard():
       # Already got the integer representation of our mask and our address
       # with the mask applied. Just need to check if this address with the
       # mask applied matches.
 
       if address is None:
-        if strict:
-          return False
+        fuzzy_match = True
       else:
         comparison_addr_bin = int(stem.util.connection._get_address_binary(address), 2)
         comparison_addr_bin &= self._get_mask_bin()
@@ -765,12 +772,14 @@ class ExitPolicyRule(object):
 
     if not self.is_port_wildcard():
       if port is None:
-        if strict:
-          return False
+        fuzzy_match = True
       elif port < self.min_port or port > self.max_port:
         return False
 
-    return True
+    if fuzzy_match:
+      return strict != self.is_accept
+    else:
+      return True
 
   def get_address_type(self):
     """
diff --git a/test/unit/exit_policy/policy.py b/test/unit/exit_policy/policy.py
index d4eaa75..79f99e1 100644
--- a/test/unit/exit_policy/policy.py
+++ b/test/unit/exit_policy/policy.py
@@ -65,6 +65,17 @@ class TestExitPolicy(unittest.TestCase):
       self.assertEqual(expected_result, policy.can_exit_to(ip_addr, index))
       self.assertEqual(expected_result, policy.can_exit_to(port = index))
 
+  def test_can_exit_to_strictness(self):
+    # Check our 'strict' argument.
+
+    policy = ExitPolicy('reject 1.0.0.0/8:80', 'accept *:*')
+    self.assertEqual(False, policy.can_exit_to(None, 80, strict = True))  # can't exit to *all* instances of port 80
+    self.assertEqual(True, policy.can_exit_to(None, 80, strict = False))  # can exit to *an* instance of port 80
+
+    policy = ExitPolicy('accept 1.0.0.0/8:80', 'reject *:*')
+    self.assertEqual(False, policy.can_exit_to(None, 80, strict = True))  # can't exit to *all* instances of port 80
+    self.assertEqual(True, policy.can_exit_to(None, 80, strict = False))  # can exit to *an* instance of port 80
+
   def test_is_exiting_allowed(self):
     test_inputs = {
       (): True,
diff --git a/test/unit/exit_policy/rule.py b/test/unit/exit_policy/rule.py
index 1661442..5458c10 100644
--- a/test/unit/exit_policy/rule.py
+++ b/test/unit/exit_policy/rule.py
@@ -239,10 +239,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): True,
-        (None, 80, True): False,
-        (None, None, False): True,
-        (None, None, True): False,
+        (None, 80, False): False,
+        (None, 80, True): True,
+        (None, None, False): False,
+        (None, None, True): True,
       },
     }
 
@@ -265,8 +265,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): True,
-        (None, 80, True): False,
+        (None, 80, False): False,
+        (None, 80, True): True,
         ('192.168.0.50', None): True,
       },
       'reject 0.0.0.0/24:*': {
@@ -276,8 +276,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): True,
-        (None, 80, True): False,
+        (None, 80, False): False,
+        (None, 80, True): True,
         ('0.0.0.0', None): True,
       },
     }
@@ -296,8 +296,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): True,
-        (None, 80, True): False,
+        (None, 80, False): False,
+        (None, 80, True): True,
         ('FE80:0000:0000:0000:0202:B3FF:FE1E:8329', None): True,
       },
       'reject [FE80:0000:0000:0000:0202:B3FF:FE1E:8329]/112:*': {
@@ -306,8 +306,8 @@ 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): True,
-        (None, 80, True): False,
+        (None, 80, False): False,
+        (None, 80, True): True,
         ('FE80:0000:0000:0000:0202:B3FF:FE1E:8329', None, False): True,
         ('FE80:0000:0000:0000:0202:B3FF:FE1E:8329', None, True): True,
       },
@@ -326,8 +326,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): True,
-        ('192.168.0.50', None, True): False,
+        ('192.168.0.50', None, False): False,
+        ('192.168.0.50', None, True): True,
       },
       'reject *:80-85': {
         ('192.168.0.50', 79): False,
@@ -336,8 +336,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): True,
-        ('192.168.0.50', None, True): False,
+        ('192.168.0.50', None, False): False,
+        ('192.168.0.50', None, True): True,
       },
     }
 

_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits