[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [arm/master] Dropping the TorCtl connection completely
commit 2cea89cad359352ff2a78988e5647a728516f65f
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
Date: Sun Dec 16 19:46:49 2012 -0800
Dropping the TorCtl connection completely
Removing the TorCtl connection from arm. Barring some lingering imports we
should now be able to drop the library from arm. Yay!
---
src/cli/controller.py | 27 +++--------
src/cli/headerPanel.py | 27 ++--------
src/starter.py | 122 ++++++++++-------------------------------------
src/util/torTools.py | 29 ++++++------
4 files changed, 53 insertions(+), 152 deletions(-)
diff --git a/src/cli/controller.py b/src/cli/controller.py
index 9c3a4eb..f01ef8a 100644
--- a/src/cli/controller.py
+++ b/src/cli/controller.py
@@ -543,26 +543,13 @@ class TorManager:
unsuccessful.
"""
- torctlConn, authType, authValue = TorCtl.preauth_connect(controlPort = int(CONFIG["wizard.default"]["Control"]))
-
- if not torctlConn:
- msg = "Unable to start tor, try running \"tor -f %s\" to see the error output" % self.getTorrcPath()
- raise IOError(msg)
-
- if authType == TorCtl.AUTH_TYPE.COOKIE:
- try:
- authCookieSize = os.path.getsize(authValue)
- if authCookieSize != 32:
- raise IOError("authentication cookie '%s' is the wrong size (%i bytes instead of 32)" % (authValue, authCookieSize))
-
- torctlConn.authenticate(authValue)
-
- controller = Controller.from_port(control_port = int(CONFIG["wizard.default"]["Control"]))
- controller.authenticate()
-
- torTools.getConn().init(torctlConn, controller)
- except Exception, exc:
- raise IOError("Unable to connect to Tor: %s" % exc)
+ try:
+ controller = Controller.from_port(control_port = int(CONFIG["wizard.default"]["Control"]))
+ controller.authenticate()
+
+ torTools.getConn().init(controller)
+ except Exception, exc:
+ raise IOError("Unable to connect to Tor: %s" % exc)
def shutdownDaemons():
"""
diff --git a/src/cli/headerPanel.py b/src/cli/headerPanel.py
index c9541c4..ce43e06 100644
--- a/src/cli/headerPanel.py
+++ b/src/cli/headerPanel.py
@@ -138,25 +138,23 @@ class HeaderPanel(panel.Panel, threading.Thread):
if key in (ord('n'), ord('N')) and torTools.getConn().isNewnymAvailable():
self.sendNewnym()
elif key in (ord('r'), ord('R')) and not self._isTorConnected:
- torctlConn, controller = None, None
+ controller = None
allowPortConnection, allowSocketConnection, _ = starter.allowConnectionTypes()
if os.path.exists(self._config["startup.interface.socket"]) and allowSocketConnection:
try:
- torctlConn = torTools.connect_socket(self._config["startup.interface.socket"])
-
# TODO: um... what about passwords?
controller = Controller.from_socket_file(self._config["startup.interface.socket"])
controller.authenticate()
except (IOError, stem.SocketError), exc:
- torctlConn, controller = None, None
+ controller = None
if not allowPortConnection:
cli.popups.showMsg("Unable to reconnect (%s)" % exc, 3)
elif not allowPortConnection:
cli.popups.showMsg("Unable to reconnect (socket '%s' doesn't exist)" % self._config["startup.interface.socket"], 3)
- if not torctlConn and allowPortConnection:
+ if not controller and allowPortConnection:
# TODO: This has diverged from starter.py's connection, for instance it
# doesn't account for relative cookie paths or multiple authentication
# methods. We can't use the starter.py's connection function directly
@@ -165,19 +163,6 @@ class HeaderPanel(panel.Panel, threading.Thread):
try:
ctlAddr, ctlPort = self._config["startup.interface.ipAddress"], self._config["startup.interface.port"]
- tmpConn, authType, authValue = TorCtl.TorCtl.preauth_connect(ctlAddr, ctlPort)
-
- if authType == TorCtl.TorCtl.AUTH_TYPE.PASSWORD:
- authValue = cli.popups.inputPrompt("Controller Password: ")
- if not authValue: raise IOError() # cancel reconnection
- elif authType == TorCtl.TorCtl.AUTH_TYPE.COOKIE:
- authCookieSize = os.path.getsize(authValue)
- if authCookieSize != 32:
- raise IOError("authentication cookie '%s' is the wrong size (%i bytes instead of 32)" % (authValue, authCookieSize))
-
- tmpConn.authenticate(authValue)
- torctlConn = tmpConn
-
controller = Controller.from_port(ctlAddr, ctlPort)
try:
@@ -185,7 +170,7 @@ class HeaderPanel(panel.Panel, threading.Thread):
except stem.connection.MissingPassword:
controller.authenticate(authValue) # already got the password above
except Exception, exc:
- torctlConn, controller = None, None
+ controller = None
# attempts to use the wizard port too
try:
@@ -196,8 +181,8 @@ class HeaderPanel(panel.Panel, threading.Thread):
# displays notice for the first failed connection attempt
if exc.args: cli.popups.showMsg("Unable to reconnect (%s)" % exc, 3)
- if torctlConn and controller:
- torTools.getConn().init(torctlConn, controller)
+ if controller:
+ torTools.getConn().init(controller)
log.log(log.NOTICE, "Reconnected to Tor's control port")
cli.popups.showMsg("Tor reconnected", 1)
else: isKeystrokeConsumed = False
diff --git a/src/starter.py b/src/starter.py
index 8b2bbb3..01a6086 100644
--- a/src/starter.py
+++ b/src/starter.py
@@ -29,10 +29,8 @@ import util.torInterpretor
import util.torTools
import util.uiTools
-import TorCtl.TorCtl
-import TorCtl.TorUtil
-
from stem.control import Controller
+import stem.connection
LOG_DUMP_PATH = os.path.expanduser("~/.arm/log")
DEFAULT_CONFIG = os.path.expanduser("~/.arm/armrc")
@@ -207,90 +205,27 @@ def _loadConfigurationDescriptions(pathPrefix):
msg = DESC_INTERNAL_LOAD_FAILED_MSG % util.sysTools.getFileErrorMsg(exc)
util.log.log(CONFIG["log.configDescriptions.internalLoadFailed"], msg)
-def _torCtlConnect(controlAddr="127.0.0.1", controlPort=9051, passphrase=None, incorrectPasswordMsg="", printError=True):
+def _getController(controlAddr="127.0.0.1", controlPort=9051, passphrase=None, incorrectPasswordMsg="", printError=True):
"""
- Custom handler for establishing a TorCtl connection.
+ Custom handler for establishing a stem connection (... needs an overhaul).
"""
- conn, controller = None, None
+ controller = None
try:
- #conn, authType, authValue = TorCtl.TorCtl.preauth_connect(controlAddr, controlPort)
- conn, authTypes, authValue = util.torTools.preauth_connect_alt(controlAddr, controlPort)
-
- if TorCtl.TorCtl.AUTH_TYPE.PASSWORD in authTypes:
- # password authentication, promting for the password if it wasn't provided
- #
- # TODO: When handling multi-auth we should try to authenticate via the
- # cookie first, then fall back to prompting the user for their password.
- # With the stack of fixes and hacks we have here jerry-rigging that in
- # without trying cookie auth twice will be a pita so leaving this alone
- # for now. Stem will handle most of this transparently, letting us handle
- # this much more elegantly.
-
- if not passphrase:
- try: passphrase = getpass.getpass("Controller password: ")
- except KeyboardInterrupt: return None, None
-
- if TorCtl.TorCtl.AUTH_TYPE.COOKIE in authTypes and authValue[0] != "/":
- # Connecting to the control port will probably fail if it's using cookie
- # authentication and the cookie path is relative (unfortunately this is
- # the case for TBB). This is discussed in:
- # https://trac.torproject.org/projects/tor/ticket/1101
- #
- # This is best effort. If we can't expand the path then it's still
- # attempted since we might be running in tor's pwd.
-
- torPid = util.torTools.getPid(controlPort)
- if torPid:
- try: conn._cookiePath = util.sysTools.expandRelativePath(authValue, torPid)
- except IOError: pass
+ chroot = util.torTools.getConn().getPathPrefix()
+ controller = Controller.from_port(controlAddr, controlPort)
- # appends the path prefix if it's set
- if TorCtl.TorCtl.AUTH_TYPE.COOKIE in authTypes:
- pathPrefix = util.torTools.getConn().getPathPrefix()
-
- # The os.path.join function is kinda stupid. If given an absolute path
- # with the second argument then it will swallow the prefix. Ie...
- # os.path.join("/tmp", "/foo") => "/foo"
-
- if pathPrefix:
- pathSuffix = conn._cookiePath
- if pathSuffix.startswith("/"): pathSuffix = pathSuffix[1:]
-
- conn._cookiePath = os.path.join(pathPrefix, pathSuffix)
-
- # Abort if the file isn't 32 bytes long. This is to avoid exposing
- # arbitrary file content to the port.
- #
- # Without this a malicious socket could, for instance, claim that
- # '~/.bash_history' or '~/.ssh/id_rsa' was its authentication cookie to
- # trick us into reading it for them with our current permissions.
- #
- # https://trac.torproject.org/projects/tor/ticket/4305
-
+ try:
+ controller.authenticate(password = passphrase, chroot_path = chroot)
+ except stem.connection.MissingPassword:
try:
- authCookieSize = os.path.getsize(conn._cookiePath)
- if authCookieSize != 32:
- raise IOError("authentication cookie '%s' is the wrong size (%i bytes instead of 32)" % (conn._cookiePath, authCookieSize))
- except Exception, exc:
- # if the above fails then either...
- # - raise an exception if cookie auth is the only method we have to
- # authenticate
- # - suppress the exception and try the other connection methods if we
- # have alternatives
- if len(authTypes) == 1: raise exc
- else: conn._authTypes.remove(TorCtl.TorCtl.AUTH_TYPE.COOKIE)
-
- conn.authenticate(passphrase)
-
- # Damn well everything above this is covered by stem. :P
+ passphrase = getpass.getpass("Controller password: ")
+ controller.authenticate(password = passphrase, chroot_path = chroot)
+ except:
+ return None
- controller = Controller.from_port(controlAddr, controlPort)
- controller.authenticate(password = passphrase, chroot_path = util.torTools.getConn().getPathPrefix())
-
- return conn, controller
+ return controller
except Exception, exc:
- if conn: conn.close()
if controller: controller.close()
# attempts to connect with the default wizard address too
@@ -304,19 +239,19 @@ def _torCtlConnect(controlAddr="127.0.0.1", controlPort=9051, passphrase=None, i
# connection failure. Otherwise, return the connection result.
if controlPort != wizardPort:
- connResult, controller = _torCtlConnect(controlAddr, wizardPort)
- if connResult != None: return connResult, controller
- else: return None, None # wizard connection attempt, don't print anything
+ controller = _getController(controlAddr, wizardPort)
+ if controller != None: return controller
+ else: return None # wizard connection attempt, don't print anything
if passphrase and str(exc) == "Unable to authenticate: password incorrect":
# provide a warning that the provided password didn't work, then try
# again prompting for the user to enter it
print incorrectPasswordMsg
- return _torCtlConnect(controlAddr, controlPort)
+ return _getController(controlAddr, controlPort)
elif printError:
print exc
- return None, None
+ return None
def _dumpConfig():
"""
@@ -488,21 +423,16 @@ if __name__ == '__main__':
print "Unrecognized event flag: %s" % flag
sys.exit()
- # temporarily disables TorCtl logging to prevent issues from going to stdout while starting
- TorCtl.TorUtil.loglevel = "NONE"
-
# By default attempts to connect using the control socket if it exists. This
# skips attempting to connect by socket or port if the user has given
# arguments for connecting to the other.
- conn, controller = None, None
+ controller = None
allowPortConnection, allowSocketConnection, allowDetachedStart = allowConnectionTypes()
socketPath = param["startup.interface.socket"]
if os.path.exists(socketPath) and allowSocketConnection:
try:
- conn = util.torTools.connect_socket(socketPath)
-
# TODO: um... what about passwords?
# https://trac.torproject.org/6881
@@ -514,12 +444,12 @@ if __name__ == '__main__':
elif not allowPortConnection:
print "Socket '%s' doesn't exist" % socketPath
- if (not conn or not controller) and allowPortConnection:
- # sets up TorCtl connection, prompting for the passphrase if necessary and
+ if not controller and allowPortConnection:
+ # sets up stem connection, prompting for the passphrase if necessary and
# sending problems to stdout if they arise
authPassword = config.get("startup.controlPassword", CONFIG["startup.controlPassword"])
incorrectPasswordMsg = "Password found in '%s' was incorrect" % configPath
- conn, controller = _torCtlConnect(controlAddr, controlPort, authPassword, incorrectPasswordMsg, not allowDetachedStart)
+ controller = _getController(controlAddr, controlPort, authPassword, incorrectPasswordMsg, not allowDetachedStart)
# removing references to the controller password so the memory can be freed
# (unfortunately python does allow for direct access to the memory so this
@@ -537,7 +467,7 @@ if __name__ == '__main__':
if pwLineNum != None:
del config.rawContents[i]
- if (conn is None or controller is None) and not allowDetachedStart: sys.exit(1)
+ if controller is None and not allowDetachedStart: sys.exit(1)
# initializing the connection may require user input (for the password)
# skewing the startup time results so this isn't counted
@@ -545,8 +475,8 @@ if __name__ == '__main__':
controllerWrapper = util.torTools.getConn()
torUser = None
- if conn and controller:
- controllerWrapper.init(conn, controller)
+ if controller:
+ controllerWrapper.init(controller)
# give a notice if tor is running with root
torUser = controllerWrapper.getMyUser()
diff --git a/src/util/torTools.py b/src/util/torTools.py
index 5ac29ea..0357b32 100644
--- a/src/util/torTools.py
+++ b/src/util/torTools.py
@@ -483,7 +483,6 @@ class Controller(TorCtl.PostEventListener):
def __init__(self):
TorCtl.PostEventListener.__init__(self)
- self.conn = None # None if uninitialized or controller's been closed
self.controller = None
self.connLock = threading.RLock()
self.statusListeners = [] # callback functions for tor's state changes
@@ -522,25 +521,22 @@ class Controller(TorCtl.PostEventListener):
# cached parameters for custom getters (None if unset or possibly changed)
self._cachedParam = {}
- def init(self, conn, controller):
+ def init(self, controller):
"""
Uses the given TorCtl instance for future operations, notifying listeners
about the change.
Arguments:
- conn - TorCtl instance to be used
controller - stem based Controller instance
"""
# TODO: We should reuse our controller instance so event listeners will be
# re-attached. This is a point of regression until we do... :(
- if conn.is_live() and controller.is_alive() and conn != self.conn:
+ if controller.is_alive() and controller != self.controller:
self.connLock.acquire()
- if self.conn: self.close() # shut down current connection
- self.conn = conn
-
+ if self.controller: self.close() # shut down current connection
self.controller = controller
log.log(log.INFO, "Stem connected to tor version %s" % self.controller.get_version())
@@ -583,10 +579,7 @@ class Controller(TorCtl.PostEventListener):
"""
self.connLock.acquire()
- if self.conn:
- self.conn.close()
- self.conn = None
-
+ if self.controller:
self.controller.close()
self.controller = None
@@ -610,8 +603,8 @@ class Controller(TorCtl.PostEventListener):
self.connLock.acquire()
result = False
- if self.conn:
- if self.conn.is_live() and self.controller.is_alive(): result = True
+ if self.controller:
+ if self.controller.is_alive(): result = True
else: self.close()
self.connLock.release()
@@ -622,7 +615,10 @@ class Controller(TorCtl.PostEventListener):
Provides the time of the last registered tor message.
"""
- return self.controller.get_latest_heartbeat()
+ if self.isAlive():
+ return self.controller.get_latest_heartbeat()
+ else:
+ return 0
def getInfo(self, param, default = UNDEFINED):
"""
@@ -912,7 +908,10 @@ class Controller(TorCtl.PostEventListener):
false otherwise.
"""
- return self.controller.is_geoip_unavailable()
+ if self.isAlive():
+ return self.controller.is_geoip_unavailable()
+ else:
+ return False
def getMyPid(self):
"""
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits