[tor-commits] [arm/master] Using Stem's connect() method

atagar at torproject.org atagar at torproject.org
Thu Apr 10 16:13:28 UTC 2014


commit 3aa83a9de0056425c47d3f3695ec6a299218c4f0
Author: Damian Johnson <atagar at torproject.org>
Date:   Thu Apr 10 09:13:47 2014 -0700

    Using Stem's connect() method
    
    Replacing our connection and authentication code in favor of stem's shiny new
    method for this.
---
 arm/__init__.py              |    2 +-
 arm/arguments.py             |    2 +-
 arm/config/strings.cfg       |   38 ---------------------
 arm/starter.py               |   21 ++++++++----
 arm/util/__init__.py         |   77 +++---------------------------------------
 test/util/authenticate.py    |   73 ---------------------------------------
 test/util/init_controller.py |   67 ------------------------------------
 7 files changed, 21 insertions(+), 259 deletions(-)

diff --git a/arm/__init__.py b/arm/__init__.py
index c203b5f..25e322f 100644
--- a/arm/__init__.py
+++ b/arm/__init__.py
@@ -2,7 +2,7 @@
 Scripts involved in validating user input, system state, and initializing arm.
 """
 
-__all__ = ["starter", "prereq", "version", "config_panel", "controller", "header_panel", "log_panel", "popups", "torrc_panel"]
+__all__ = ["starter", "arguments", "prereq", "version", "config_panel", "controller", "header_panel", "log_panel", "popups", "torrc_panel"]
 
 __version__ = '1.4.6_dev'
 __release_date__ = 'April 28, 2011'
diff --git a/arm/arguments.py b/arm/arguments.py
index 3d4a656..b527564 100644
--- a/arm/arguments.py
+++ b/arm/arguments.py
@@ -25,7 +25,7 @@ DEFAULT_ARGS = {
   'print_help': False,
 }
 
-OPT = 'i:s:c:d:bl:vh'
+OPT = 'i:s:c:d:l:vh'
 
 OPT_EXPANDED = [
   'interface=',
diff --git a/arm/config/strings.cfg b/arm/config/strings.cfg
index 17a9cd7..3ac3b3c 100644
--- a/arm/config/strings.cfg
+++ b/arm/config/strings.cfg
@@ -3,7 +3,6 @@
 # User facing strings. These are sorted into the following namespaces...
 #
 #   * config    parsing or handling configuration options
-#   * connect   connection and authentication to tor
 #   * debug     concerns the --debug argument
 #   * misc      anything that doesn't fit into a present namespace
 #   * setup     notificaitons or issues arising while starting arm
@@ -18,15 +17,6 @@ msg.config.unable_to_load_settings Unable to load arm's internal configurations:
 msg.config.unable_to_read_file Failed to load configuration (using defaults): "{error}"
 msg.config.nothing_loaded No armrc loaded, using defaults. You can customize arm by placing a configuration file at {path} (see the armrc.sample for its options).
 
-msg.connect.general_auth_failure Unable to authenticate: {error}
-msg.connect.incorrect_password Incorrect password
-msg.connect.no_control_port Unable to connect to tor. Maybe it's running without a ControlPort?
-msg.connect.password_prompt Tor controller password:
-msg.connect.socket_doesnt_exist The socket file you specified ({path}) doesn't exist
-msg.connect.tor_isnt_running Unable to connect to tor. Are you sure it's running?
-msg.connect.unable_to_use_port Unable to connect to {address}:{port}: {error}
-msg.connect.unable_to_use_socket Unable to connect to '{path}': {error}
-
 msg.debug.saving_to_path Saving a debug log to {path}, please check it for sensitive information before sharing it.
 msg.debug.unable_to_write_file Unable to write to our debug log file ({path}): {error}
 
@@ -53,26 +43,6 @@ msg.usage.not_a_valid_port '{port_input}' isn't a valid port number
 msg.usage.unrecognized_log_flags Unrecognized event flags: {flags}
 msg.usage.unable_to_set_color_override "{color}" isn't a valid color
 
-msg.connect.missing_password_bug
-|BUG: You provided a password but despite this stem reported that it was
-|missing. This shouldn't happen - please let us know about it!
-|
-|  http://bugs.torproject.org
-
-msg.connect.unreadable_cookie_file
-|We were unable to read tor's authentication cookie...
-|
-|  Path: {path}
-|  Issue: {issue}
-
-msg.connect.wrong_port_type
-|Please check in your torrc that {port} is the ControlPort. Maybe you
-|configured it to be the ORPort or SocksPort instead?
-
-msg.connect.wrong_socket_type
-|Unable to connect to tor. Are you sure the interface you specified belongs to
-|tor?
-
 msg.debug.header
 |Arm {arm_version} Debug Dump
 |Stem Version: {stem_version}
@@ -99,14 +69,6 @@ msg.setup.unknown_term
 |Either update your terminfo database or run arm using "TERM=xterm arm".
 |
 
-msg.uncrcognized_auth_type
-|Tor is using a type of authentication we do not recognize...
-|
-|  {auth_methods}
-|
-|Please check that arm is up to date and if there is an existing issue on
-|'http://bugs.torproject.org'. If there isn't one then let us know!
-
 msg.usage.help_output
 |Usage arm [OPTION]
 |Terminal status monitor for Tor relays.
diff --git a/arm/starter.py b/arm/starter.py
index 9493415..ba7c9af 100644
--- a/arm/starter.py
+++ b/arm/starter.py
@@ -22,11 +22,12 @@ import arm.util.tracker
 import arm.util.ui_tools
 
 import stem
+import stem.connection
 import stem.util.conf
 import stem.util.log
 import stem.util.system
 
-from arm.util import BASE_DIR, init_controller, authenticate, msg, trace, info, notice, warn, load_settings
+from arm.util import BASE_DIR, init_controller, msg, trace, info, notice, warn, load_settings
 
 CONFIG = stem.util.conf.get_config('arm')
 
@@ -64,13 +65,21 @@ def main():
 
   _load_user_armrc(args.config)
 
-  try:
-    controller = init_controller(args)
-    authenticate(controller, CONFIG.get('tor.password', None), CONFIG.get('tor.chroot', ''))
-  except ValueError as exc:
-    print exc
+  control_port = None if args.user_provided_socket else (args.control_address, args.control_port)
+  control_socket = None if args.user_provided_port else args.control_socket
+
+  controller = stem.connection.connect(
+    control_port = control_port,
+    control_socket = control_socket,
+    password = CONFIG.get('tor.password', None),
+    password_prompt = True,
+    chroot_path = CONFIG.get('tor.chroot', ''),
+  )
+
+  if controller is None:
     exit(1)
 
+  init_controller(controller)
   _warn_if_root(controller)
   _warn_if_unable_to_get_pid(controller)
   _setup_freebsd_chroot(controller)
diff --git a/arm/util/__init__.py b/arm/util/__init__.py
index d94173b..d606a43 100644
--- a/arm/util/__init__.py
+++ b/arm/util/__init__.py
@@ -6,7 +6,6 @@ and safely working with curses (hiding some of the gory details).
 
 __all__ = ["connections", "panel", "sysTools", "text_input", "tor_config", "tor_tools", "tracker", "ui_tools"]
 
-import getpass
 import os
 
 import stem
@@ -29,57 +28,15 @@ def tor_controller():
   return TOR_CONTROLLER
 
 
-def init_controller(args):
+def init_controller(controller):
   """
-  Provides a Controller for the endpoint specified in the given arguments.
+  Sets the Controller used by arm.
 
-  :param namedtuple args: arguments that arm was started with
-
-  :returns: :class:`~stem.control.Controller` for the given arguments
-
-  :raises: **ValueError** if unable to acquire a controller connection
+  :param Controller controller: control connection to be used by arm
   """
 
   global TOR_CONTROLLER
-  TOR_CONTROLLER = _get_controller(args)
-  return TOR_CONTROLLER
-
-
-def authenticate(controller, password, chroot_path = ''):
-  """
-  Authenticates to the given Controller.
-
-  :param stem.control.Controller controller: controller to be authenticated
-  :param str password: password to authenticate with, **None** if nothing was
-    provided
-  :param str chroot_path: chroot tor resides within
-
-  :raises: **ValueError** if unable to authenticate
-  """
-
-  try:
-    controller.authenticate(password = password, chroot_path = chroot_path)
-  except stem.connection.IncorrectSocketType:
-    control_socket = controller.get_socket()
-
-    if isinstance(control_socket, stem.socket.ControlPort):
-      raise ValueError(msg('connect.wrong_port_type', port = control_socket.get_port()))
-    else:
-      raise ValueError(msg('connect.wrong_socket_type'))
-  except stem.connection.UnrecognizedAuthMethods as exc:
-    raise ValueError(msg('uncrcognized_auth_type', auth_methods = ', '.join(exc.unknown_auth_methods)))
-  except stem.connection.IncorrectPassword:
-    raise ValueError(msg('connect.incorrect_password'))
-  except stem.connection.MissingPassword:
-    if password:
-      raise ValueError(msg('connect.missing_password_bug'))
-
-    password = getpass.getpass(msg('connect.password_prompt') + ' ')
-    return authenticate(controller, password)
-  except stem.connection.UnreadableCookieFile as exc:
-    raise ValueError(msg('connect.unreadable_cookie_file', path = exc.cookie_path, issue = str(exc)))
-  except stem.connection.AuthenticationFailure as exc:
-    raise ValueError(msg('connect.general_auth_failure', error = exc))
+  TOR_CONTROLLER = controller
 
 
 def msg(message, **attr):
@@ -155,29 +112,3 @@ def _log(runlevel, message, **attr):
   """
 
   stem.util.log.log(runlevel, msg(message, **attr))
-
-
-def _get_controller(args):
-  """
-  Provides a Controller for the endpoint specified in the given arguments.
-  """
-
-  if os.path.exists(args.control_socket):
-    try:
-      return stem.control.Controller.from_socket_file(args.control_socket)
-    except stem.SocketError as exc:
-      if args.user_provided_socket:
-        raise ValueError(msg('connect.unable_to_use_socket', path = args.control_socket, error = exc))
-  elif args.user_provided_socket:
-    raise ValueError(msg('connect.socket_doesnt_exist', path = args.control_socket))
-
-  try:
-    return stem.control.Controller.from_port(args.control_address, args.control_port)
-  except stem.SocketError as exc:
-    if args.user_provided_port:
-      raise ValueError(msg('connect.unable_to_use_port', address = args.control_address, port = args.control_port, error = exc))
-
-  if not stem.util.system.is_running('tor'):
-    raise ValueError(msg('connect.tor_isnt_running'))
-  else:
-    raise ValueError(msg('connect.no_control_port'))
diff --git a/test/util/authenticate.py b/test/util/authenticate.py
deleted file mode 100644
index 9dae10b..0000000
--- a/test/util/authenticate.py
+++ /dev/null
@@ -1,73 +0,0 @@
-import unittest
-
-from mock import Mock, patch
-
-from arm.util import (
-  init_controller,
-  authenticate,
-)
-
-import stem
-import stem.connection
-import stem.socket
-
-
-class TestAuthenticate(unittest.TestCase):
-  def test_success(self):
-    controller = Mock()
-
-    authenticate(controller, None)
-    controller.authenticate.assert_called_with(password = None, chroot_path = '')
-    controller.authenticate.reset_mock()
-
-    authenticate(controller, 's3krit!!!', '/my/chroot')
-    controller.authenticate.assert_called_with(password = 's3krit!!!', chroot_path = '/my/chroot')
-
-  @patch('getpass.getpass')
-  def test_success_with_password_prompt(self, getpass_mock):
-    controller = Mock()
-
-    def authenticate_mock(password, **kwargs):
-      if password is None:
-        raise stem.connection.MissingPassword('no password')
-      elif password == 'my_password':
-        return None  # success
-      else:
-        raise ValueError("Unexpected authenticate_mock input: %s" % password)
-
-    controller.authenticate.side_effect = authenticate_mock
-    getpass_mock.return_value = 'my_password'
-
-    authenticate(controller, None)
-    controller.authenticate.assert_any_call(password = None, chroot_path = '')
-    controller.authenticate.assert_any_call(password = 'my_password', chroot_path = '')
-
-  def test_failure(self):
-    controller = Mock()
-
-    controller.authenticate.side_effect = stem.connection.IncorrectSocketType('unable to connect to socket')
-    controller.get_socket.return_value = stem.socket.ControlPort(connect = False)
-    self._assert_authenticate_fails_with(controller, 'Please check in your torrc that 9051 is the ControlPort.')
-
-    controller.get_socket.return_value = stem.socket.ControlSocketFile(connect = False)
-    self._assert_authenticate_fails_with(controller, 'Are you sure the interface you specified belongs to')
-
-    controller.authenticate.side_effect = stem.connection.UnrecognizedAuthMethods('unable to connect', ['telepathy'])
-    self._assert_authenticate_fails_with(controller, 'Tor is using a type of authentication we do not recognize...\n\n  telepathy')
-
-    controller.authenticate.side_effect = stem.connection.IncorrectPassword('password rejected')
-    self._assert_authenticate_fails_with(controller, 'Incorrect password')
-
-    controller.authenticate.side_effect = stem.connection.UnreadableCookieFile('permission denied', '/tmp/my_cookie', False)
-    self._assert_authenticate_fails_with(controller, "We were unable to read tor's authentication cookie...\n\n  Path: /tmp/my_cookie\n  Issue: permission denied")
-
-    controller.authenticate.side_effect = stem.connection.OpenAuthRejected('crazy failure')
-    self._assert_authenticate_fails_with(controller, 'Unable to authenticate: crazy failure')
-
-  def _assert_authenticate_fails_with(self, controller, msg):
-    try:
-      init_controller(authenticate(controller, None))
-      self.fail()
-    except ValueError as exc:
-      if not msg in str(exc):
-        self.fail("Expected...\n\n%s\n\n... which couldn't be found in...\n\n%s" % (msg, exc))
diff --git a/test/util/init_controller.py b/test/util/init_controller.py
deleted file mode 100644
index cbbeffa..0000000
--- a/test/util/init_controller.py
+++ /dev/null
@@ -1,67 +0,0 @@
-import unittest
-
-from mock import Mock, patch
-
-from arm.arguments import parse
-from arm.util import init_controller
-
-import stem
-import stem.connection
-import stem.socket
-
-
-class TestGetController(unittest.TestCase):
-  @patch('os.path.exists', Mock(return_value = True))
-  @patch('stem.util.system.is_running')
-  @patch('stem.control.Controller.from_socket_file', Mock(side_effect = stem.SocketError('failed')))
-  @patch('stem.control.Controller.from_port', Mock(side_effect = stem.SocketError('failed')))
-  def test_failue_with_the_default_endpoint(self, is_running_mock):
-    is_running_mock.return_value = False
-    self._assert_init_controller_fails_with([], "Unable to connect to tor. Are you sure it's running?")
-
-    is_running_mock.return_value = True
-    self._assert_init_controller_fails_with([], "Unable to connect to tor. Maybe it's running without a ControlPort?")
-
-  @patch('os.path.exists')
-  @patch('stem.util.system.is_running', Mock(return_value = True))
-  @patch('stem.control.Controller.from_socket_file', Mock(side_effect = stem.SocketError('failed')))
-  @patch('stem.control.Controller.from_port', Mock(side_effect = stem.SocketError('failed')))
-  def test_failure_with_a_custom_endpoint(self, path_exists_mock):
-    path_exists_mock.return_value = True
-    self._assert_init_controller_fails_with(['--interface', '80'], "Unable to connect to 127.0.0.1:80: failed")
-    self._assert_init_controller_fails_with(['--socket', '/tmp/my_socket'], "Unable to connect to '/tmp/my_socket': failed")
-
-    path_exists_mock.return_value = False
-    self._assert_init_controller_fails_with(['--interface', '80'], "Unable to connect to 127.0.0.1:80: failed")
-    self._assert_init_controller_fails_with(['--socket', '/tmp/my_socket'], "The socket file you specified (/tmp/my_socket) doesn't exist")
-
-  @patch('os.path.exists', Mock(return_value = False))
-  @patch('stem.control.Controller.from_port')
-  def test_getting_a_control_port(self, from_port_mock):
-    from_port_mock.return_value = 'success'
-
-    self.assertEqual('success', init_controller(parse([])))
-    from_port_mock.assert_called_once_with('127.0.0.1', 9051)
-    from_port_mock.reset_mock()
-
-    self.assertEqual('success', init_controller(parse(['--interface', '255.0.0.10:80'])))
-    from_port_mock.assert_called_once_with('255.0.0.10', 80)
-
-  @patch('os.path.exists', Mock(return_value = True))
-  @patch('stem.control.Controller.from_socket_file')
-  def test_getting_a_control_socket(self, from_socket_file_mock):
-    from_socket_file_mock.return_value = 'success'
-
-    self.assertEqual('success', init_controller(parse([])))
-    from_socket_file_mock.assert_called_once_with('/var/run/tor/control')
-    from_socket_file_mock.reset_mock()
-
-    self.assertEqual('success', init_controller(parse(['--socket', '/tmp/my_socket'])))
-    from_socket_file_mock.assert_called_once_with('/tmp/my_socket')
-
-  def _assert_init_controller_fails_with(self, args, msg):
-    try:
-      init_controller(parse(args))
-      self.fail()
-    except ValueError as exc:
-      self.assertEqual(msg, str(exc))



More information about the tor-commits mailing list