commit 565e18a6ff6189dd11d8a43ca77eed287743b479 Author: Damian Johnson atagar@torproject.org Date: Thu Jun 16 07:50:58 2011 -0700
TorCtl connect method inflexible
The connect method is a nice helper for cli initiation, but lacks sufficient call visibility to help in more general use cases. In particular it... - sends feedback to stdout - prompts for the controller password on stdin - suppresses exceptions
To get around this I'm adding a more generic 'connectionComp' that does the icky bits of the connection negotiation I was trying to hide while still giving the caller what it needs to handle the connection process however it'd like.
Tested by exercising the connect functionality with cookies, password, and connection components to handle my TBB cookie auth renegotiation fix. --- TorCtl.py | 62 +++++++++++++++++++++++++++++++++++++++++------------------- 1 files changed, 42 insertions(+), 20 deletions(-)
diff --git a/TorCtl.py b/TorCtl.py index 8680ee6..cb3b53f 100755 --- a/TorCtl.py +++ b/TorCtl.py @@ -108,36 +108,20 @@ def connect(controlAddr="127.0.0.1", controlPort=9051, passphrase=None): passphrase - authentication passphrase (if defined this is used rather than prompting the user) """ - - conn = None + try: - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.connect((controlAddr, controlPort)) - conn = Connection(s) - authType, authValue = conn.get_auth_type(), "" - + conn, authType, authValue = connectionComp(controlAddr, controlPort) + if authType == AUTH_TYPE.PASSWORD: # password authentication, promting for the password if it wasn't provided if passphrase: authValue = passphrase else: try: authValue = getpass.getpass() except KeyboardInterrupt: return None - elif authType == AUTH_TYPE.COOKIE: - authValue = conn.get_auth_cookie_path() - + conn.authenticate(authValue) return conn - except socket.error, exc: - if "Connection refused" in exc.args: - # most common case - tor control port isn't available - print "Connection refused. Is the ControlPort enabled?" - else: print "Failed to establish socket: %s" % exc - - if conn: conn.close() - return None except Exception, exc: - if conn: conn.close() - 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 @@ -147,6 +131,44 @@ def connect(controlAddr="127.0.0.1", controlPort=9051, passphrase=None): print exc return None
+def connectionComp(controlAddr="127.0.0.1", controlPort=9051): + """ + Provides an uninitiated torctl connection components for the control port, + returning a tuple of the form... + (torctl connection, authType, authValue) + + The authValue corresponds to the cookie path if using an authentication + cookie, otherwise this is the empty string. This raises an IOError in case + of failure. + + Arguments: + controlAddr - ip address belonging to the controller + controlPort - port belonging to the controller + """ + + conn = None + try: + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect((controlAddr, controlPort)) + conn = Connection(s) + authType, authValue = conn.get_auth_type(), "" + + if authType == AUTH_TYPE.COOKIE: + authValue = conn.get_auth_cookie_path() + + return (conn, authType, authValue) + except socket.error, exc: + if conn: conn.close() + + if "Connection refused" in exc.args: + # most common case - tor control port isn't available + raise IOError("Connection refused. Is the ControlPort enabled?") + + raise IOError("Failed to establish socket: %s" % exc) + except Exception, exc: + if conn: conn.close() + raise IOError(exc) + class TorCtlError(Exception): "Generic error raised by TorControl code." pass