[tor-commits] [stem/master] Function and testing for null authentication

atagar at torproject.org atagar at torproject.org
Mon Nov 28 18:10:26 UTC 2011


commit 312423c9d0b68cea486c3269ddcaf95fcb3314cc
Author: Damian Johnson <atagar at torproject.org>
Date:   Mon Nov 28 10:08:20 2011 -0800

    Function and testing for null authentication
    
    Function for authenticating to open connections and integration testing for it.
    The tests both check the happy case and responses we get in a variety of
    'authentication needed' scenarios.
---
 run_tests.py                            |    2 +
 stem/connection.py                      |   24 ++++++++++++
 test/integ/connection/__init__.py       |    2 +-
 test/integ/connection/authentication.py |   62 +++++++++++++++++++++++++++++++
 4 files changed, 89 insertions(+), 1 deletions(-)

diff --git a/run_tests.py b/run_tests.py
index 8dd141e..eee52ff 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -22,6 +22,7 @@ import test.unit.util.system
 import test.integ.socket.control_message
 import test.integ.util.conf
 import test.integ.util.system
+import test.integ.connection.authentication
 import test.integ.connection.protocolinfo
 
 import stem.util.enum
@@ -41,6 +42,7 @@ UNIT_TESTS = (("stem.socket.ControlMessage", test.unit.socket.control_message.Te
              )
 
 INTEG_TESTS = (("stem.socket.ControlMessage", test.integ.socket.control_message.TestControlMessage),
+              ("stem.connection.authenticate_*", test.integ.connection.authentication.TestAuthenticate),
               ("stem.connection.ProtocolInfoResponse", test.integ.connection.protocolinfo.TestProtocolInfo),
                ("stem.util.conf", test.integ.util.conf.TestConf),
                ("stem.util.system", test.integ.util.system.TestSystem),
diff --git a/stem/connection.py b/stem/connection.py
index b740d0d..bef8d50 100644
--- a/stem/connection.py
+++ b/stem/connection.py
@@ -38,6 +38,30 @@ LOGGER = logging.getLogger("stem")
 
 AuthMethod = stem.util.enum.Enum("NONE", "PASSWORD", "COOKIE", "UNKNOWN")
 
+def authenticate_none(control_socket):
+  """
+  Authenticates to an open control socket. All control connections need to
+  authenticate before they can be used, even if tor hasn't been configured to
+  use any authentication.
+  
+  If authentication fails then tor will close the control socket.
+  
+  Arguments:
+    control_socket (stem.socket.ControlSocket) - socket to be authenticated
+  
+  Raises:
+    ValueError if the empty authentication credentials aren't accepted
+    stem.socket.ProtocolError the content from the socket is malformed
+    stem.socket.SocketError if problems arise in using the socket
+  """
+  
+  control_socket.send("AUTHENTICATE")
+  auth_response = control_socket.recv()
+  
+  # if we got anything but an OK response then error
+  if str(auth_response) != "OK":
+    raise ValueError(str(auth_response))
+
 def get_protocolinfo_by_port(control_addr = "127.0.0.1", control_port = 9051, get_socket = False):
   """
   Issues a PROTOCOLINFO query to a control port, getting information about the
diff --git a/test/integ/connection/__init__.py b/test/integ/connection/__init__.py
index dd0925e..d570669 100644
--- a/test/integ/connection/__init__.py
+++ b/test/integ/connection/__init__.py
@@ -2,5 +2,5 @@
 Integration tests for stem.connection.
 """
 
-__all__ = ["protocolinfo"]
+__all__ = ["authenticate", "protocolinfo"]
 
diff --git a/test/integ/connection/authentication.py b/test/integ/connection/authentication.py
new file mode 100644
index 0000000..4ba0bfa
--- /dev/null
+++ b/test/integ/connection/authentication.py
@@ -0,0 +1,62 @@
+"""
+Integration tests for authenticating to the control socket via
+stem.connection.authenticate_* functions.
+"""
+
+import unittest
+
+import test.runner
+import stem.connection
+
+# Responses given by tor for various authentication failures. These may change
+# in the future and if they do then this test should be updated.
+
+COOKIE_AUTH_FAIL = "Authentication failed: Wrong length on authentication cookie."
+PASSWORD_AUTH_FAIL = "Authentication failed: Password did not match HashedControlPassword value from configuration. Maybe you tried a plain text password? If so, the standard requires that you put it in double quotes."
+MULTIPLE_AUTH_FAIL = "Authentication failed: Password did not match HashedControlPassword *or* authentication cookie."
+
+class TestAuthenticate(unittest.TestCase):
+  """
+  Tests the authentication methods. This should be run with the 'CONN_ALL'
+  integ target to exercise the widest range of use cases.
+  """
+  
+  def test_authenticate_none(self):
+    """
+    Tests the authenticate_none function.
+    """
+    
+    runner = test.runner.get_runner()
+    connection_type = runner.get_connection_type()
+    
+    if connection_type == test.runner.TorConnection.NONE:
+      self.skipTest("(no connection)")
+    
+    # If the connection has authentication then this will fail with a message
+    # based on the authentication type. If not then this will succeed.
+    
+    control_socket = test.runner.get_runner().get_tor_socket(False)
+    
+    connection_options = test.runner.CONNECTION_OPTS[connection_type]
+    cookie_auth = test.runner.OPT_COOKIE in connection_options
+    password_auth = test.runner.OPT_PASSWORD in connection_options
+    
+    if cookie_auth or password_auth:
+      if cookie_auth and password_auth: failure_msg = MULTIPLE_AUTH_FAIL
+      elif cookie_auth: failure_msg = COOKIE_AUTH_FAIL
+      else: failure_msg = PASSWORD_AUTH_FAIL
+      
+      try:
+        stem.connection.authenticate_none(control_socket)
+        self.fail()
+      except ValueError, exc:
+        self.assertEqual(failure_msg, str(exc))
+    else:
+      stem.connection.authenticate_none(control_socket)
+      
+      # issues a 'GETINFO config-file' query to confirm that we can use the socket
+      
+      control_socket.send("GETINFO config-file")
+      config_file_response = control_socket.recv()
+      self.assertEquals("config-file=%s\nOK" % runner.get_torrc_path(), str(config_file_response))
+



More information about the tor-commits mailing list