[tor-commits] [stem/master] Add microdescriptor exit policy

atagar at torproject.org atagar at torproject.org
Thu Jul 19 16:01:03 UTC 2012


commit 30ba1019fcbeca9220e85fa5216b6bac1b5db16f
Author: Sathyanarayanan Gunasekaran <gsathya.ceg at gmail.com>
Date:   Tue Jul 3 02:03:12 2012 +0530

    Add microdescriptor exit policy
    
    The microdescriptor policy class can now parse
    exit policy summaries. Add tests for this
---
 stem/exit_policy.py      |   73 ++++++++++++++++++++++++++++++++++++++++++++++
 test/unit/exit_policy.py |   54 +++++++++++++++++++++++++++++++++-
 2 files changed, 126 insertions(+), 1 deletions(-)

diff --git a/stem/exit_policy.py b/stem/exit_policy.py
index 314110c..33f5cc1 100644
--- a/stem/exit_policy.py
+++ b/stem/exit_policy.py
@@ -10,6 +10,16 @@ easily parsed and compared, for instance...
 accept *:80 , accept *:443, reject *:*
 >>> print exit_policies.get_summary()
 accept 80, 443
+>>> exit_policies.check("www.google.com", 80)
+True
+
+>>> microdesc_exit_policy = stem.exit_policy.MicrodescriptorExitPolicy("accept 80,443")
+>>> print microdesc_exit_policy
+accept 80,443
+>>> microdesc_exit_policy.check("www.google.com", 80)
+True
+>>> microdesc_exit_policy.check(80)
+True
 
 ExitPolicyLine - Single rule from the exit policy
   |- __str__ - string representation
@@ -23,6 +33,11 @@ ExitPolicy - List of ExitPolicyLine objects
   |- get_summary - provides a summary description of the policy chain
   +- is_exiting_allowed - check if exit node
 
+MicrodescriptorExitPolicy - Microdescriptor exit policy
+  |- check - check if exiting to this port is allowed
+  |- ports - returns a list of ports
+  |- is_accept - check if it's a list of accepted/rejected ports
+  +- __str__ - return the summary
 """
 
 import stem.util.connection
@@ -271,6 +286,64 @@ class ExitPolicy:
     """
     return ', '.join([str(policy) for policy in self._policies])
   
+class MicrodescriptorExitPolicy:
+  """
+  Microdescriptor exit policy -  'accept 53,80,443'
+  """
+
+  def __init__(self, summary):
+    self.ports = []
+    self.is_accept = None
+    self.summary = summary
+    
+    # sanitize the input a bit, cleaning up tabs and stripping quotes
+    summary = self.summary.replace("\\t", " ").replace("\"", "")
+    
+    self.is_accept = summary.startswith("accept")
+    
+    # strips off "accept " or "reject " and extra spaces
+    summary = summary[7:].replace(" ", "")
+    
+    for ports in summary.split(','):
+      if '-' in ports:
+        port_range = ports.split("-", 1)
+        if not stem.util.connection.is_valid_port(port_range):
+          raise ExitPolicyError
+        self.ports.append(range(int(port_range[2])), int(port_range[1]))
+      if not stem.util.connection.is_valid_port(ports):
+          raise ExitPolicyError
+      self.ports.append(int(ports))
+      
+  def check(self, ip_address=None, port=None):
+    # stem is intelligent about the arguments
+    if not port:
+      if not '.' in str(ip_address):
+        port = ip_address
+    
+    port = int(port)
+    
+    if port in self.ports:
+      # its a list of accepted ports
+      if self.is_accept:
+        return True
+      else:
+        return False
+    else:
+      # its a list of rejected ports
+      if not self.is_accept:
+        return True
+      else:
+        return False
+    
+  def __str__(self):
+    return self.summary
+
+  def ports(self):
+    return self.ports
+
+  def is_accept(self):
+    return self.is_accept
+
 class ExitPolicyError(Exception):
   """
   Base error for exit policy issues.
diff --git a/test/unit/exit_policy.py b/test/unit/exit_policy.py
index d4fd7e0..b12cd9a 100644
--- a/test/unit/exit_policy.py
+++ b/test/unit/exit_policy.py
@@ -55,4 +55,56 @@ class TestExitPolicy(unittest.TestCase):
     """
     Tests if exiting to this ip is allowed.
     """
-    pass
+    
+    exit_policies = stem.exit_policy.ExitPolicy()
+    exit_policies = stem.exit_policy.ExitPolicy()
+    exit_policies.add("accept *:80")
+    exit_policies.add("accept *:443")
+    exit_policies.add("reject *:*")
+    
+    self.assertTrue(exit_policies.check("www.google.com", 80))
+    self.assertTrue(exit_policies.check("www.atagar.com", 443))
+    
+    self.assertFalse(exit_policies.check("www.atagar.com", 22))
+    self.assertFalse(exit_policies.check("www.atagar.com", 8118))
+    
+  def test_is_exiting_allowed(self):
+    """
+    Tests if this is an exit node
+    """
+    
+    exit_policies = stem.exit_policy.ExitPolicy()
+    exit_policies = stem.exit_policy.ExitPolicy()
+    exit_policies.add("accept *:80")
+    exit_policies.add("accept *:443")
+    exit_policies.add("reject *:*")
+    
+    self.assertTrue(exit_policies.is_exiting_allowed())
+    
+    exit_policies = stem.exit_policy.ExitPolicy()
+    exit_policies = stem.exit_policy.ExitPolicy()
+    exit_policies.add("reject *:*")
+    
+    self.assertFalse(exit_policies.is_exiting_allowed())
+    
+  def test_microdesc_exit_parsing(self):
+    microdesc_exit_policy = stem.exit_policy.MicrodescriptorExitPolicy("accept 80,443")
+    
+    self.assertEqual(str(microdesc_exit_policy),"accept 80,443")
+    
+    self.assertRaises(stem.exit_policy.ExitPolicyError, stem.exit_policy.MicrodescriptorExitPolicy, "accept 80,-443")
+    self.assertRaises(stem.exit_policy.ExitPolicyError, stem.exit_policy.MicrodescriptorExitPolicy, "accept 80,+443")
+    self.assertRaises(stem.exit_policy.ExitPolicyError, stem.exit_policy.MicrodescriptorExitPolicy, "accept 80,66666")
+    self.assertRaises(stem.exit_policy.ExitPolicyError, stem.exit_policy.MicrodescriptorExitPolicy, "reject 80,foo")
+    self.assertRaises(stem.exit_policy.ExitPolicyError, stem.exit_policy.MicrodescriptorExitPolicy, "bar 80,foo")
+    self.assertRaises(stem.exit_policy.ExitPolicyError, stem.exit_policy.MicrodescriptorExitPolicy, "foo")
+    self.assertRaises(stem.exit_policy.ExitPolicyError, stem.exit_policy.MicrodescriptorExitPolicy, "bar 80-foo")
+    
+  def test_micodesc_exit_check(self):
+    microdesc_exit_policy = stem.exit_policy.MicrodescriptorExitPolicy("accept 80,443")
+    
+    self.assertTrue(microdesc_exit_policy.check(80))
+    self.assertTrue(microdesc_exit_policy.check("www.atagar.com", 443))
+    
+    self.assertFalse(microdesc_exit_policy.check(22))
+    self.assertFalse(microdesc_exit_policy.check("www.atagar.com", 8118))





More information about the tor-commits mailing list