Author: atagar Date: 2011-01-02 03:38:32 +0000 (Sun, 02 Jan 2011) New Revision: 24019
Modified: arm/trunk/src/starter.py arm/trunk/src/util/procTools.py arm/trunk/src/util/sysTools.py arm/trunk/src/util/torConfig.py Log: Hack to fix relative COOKIEFILE paths This is to improve usability with tbb instances, and will be removed when https://trac.torproject.org/projects/tor/ticket/1101 is resolved. Modified: arm/trunk/src/starter.py =================================================================== --- arm/trunk/src/starter.py 2011-01-02 02:34:20 UTC (rev 24018) +++ arm/trunk/src/starter.py 2011-01-02 03:38:32 UTC (rev 24019) @@ -10,6 +10,7 @@ import sys import time import getopt +import socket import version import interface.controller @@ -280,7 +281,36 @@ TorCtl.INCORRECT_PASSWORD_MSG = "Controller password found in '%s' was incorrect" % configPath authPassword = config.get("startup.controlPassword", CONFIG["startup.controlPassword"]) conn = TorCtl.TorCtl.connect(controlAddr, controlPort, authPassword) - if conn == None: sys.exit(1) + if conn == None: + # 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 + # + # Until this is fixed including a hack to expand the relative path in + # these cases, setting conn to the established connection if successful + # and leaving it undefined otherwise. Even if successful this prints the + # error message saying that the auth cookie couldn't be found + # (unfortunately this is unavoidable without either changing TorCtl or + # making this a much bigger hack). + + try: + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect((controlAddr, controlPort)) + tmpConn = TorCtl.TorCtl.Connection(s) + + if tmpConn.get_auth_type() == TorCtl.TorCtl.AUTH_TYPE.COOKIE: + cookiePath = tmpConn.get_auth_cookie_path() + torPid = util.torTools.getPid(controlPort) + + if torPid and cookiePath[0] != "/": + # previous attempt to connect failed due to having a relative path - fix it + tmpConn._cookiePath = util.sysTools.expandRelativePath(cookiePath, torPid) + tmpConn.authenticate(cookiePath) + conn = tmpConn # success! + except: pass + + if conn == None: sys.exit(1) # removing references to the controller password so the memory can be freed # (unfortunately python does allow for direct access to the memory so this Modified: arm/trunk/src/util/procTools.py =================================================================== --- arm/trunk/src/util/procTools.py 2011-01-02 02:34:20 UTC (rev 24018) +++ arm/trunk/src/util/procTools.py 2011-01-02 03:38:32 UTC (rev 24019) @@ -82,7 +82,7 @@ return SYS_PHYSICAL_MEMORY -def getCwd(pid): +def getPwd(pid): """ Provides the current working directory for the given process. Modified: arm/trunk/src/util/sysTools.py =================================================================== --- arm/trunk/src/util/sysTools.py 2011-01-02 02:34:20 UTC (rev 24018) +++ arm/trunk/src/util/sysTools.py 2011-01-02 03:38:32 UTC (rev 24019) @@ -17,6 +17,7 @@ CALL_CACHE_LOCK = threading.RLock() # governs concurrent modifications of CALL_CACHE PROCESS_NAME_CACHE = {} # mapping of pids to their process names +PWD_CACHE = {} # mapping of pids to their present working directory RESOURCE_TRACKERS = {} # mapping of pids to their resource tracker instances # Runtimes for system calls, used to estimate cpu usage. Entries are tuples of @@ -138,6 +139,61 @@ PROCESS_NAME_CACHE[pid] = processName return processName +def getPwd(pid): + """ + Provices the working directory of the given process. This raises an IOError + if it can't be determined. + + Arguments: + pid - pid of the process + """ + + if not pid: raise IOError("we couldn't get the pid") + elif pid in PWD_CACHE: return PWD_CACHE[pid] + + # try fetching via the proc contents if available + if procTools.isProcAvailable(): + try: + pwd = procTools.getPwd(pid) + PWD_CACHE[pid] = pwd + return pwd + except IOError: pass # fall back to pwdx + + try: + # pwdx results are of the form: + # 3799: /home/atagar + # 5839: No such process + results = sysTools.call("pwdx %s" % pid) + if not results: + raise IOError("pwdx didn't return any results") + elif results[0].endswith("No such process"): + raise IOError("pwdx reported no process for pid " + pid) + elif len(results) != 1 or results.count(" ") != 1: + raise IOError("we got unexpected output from pwdx") + else: + pwd = results[0][results[0].find(" ") + 1:] + PWD_CACHE[pid] = pwd + return pwd + except IOError, exc: + raise IOError("the pwdx call failed: " + str(exc)) + +def expandRelativePath(path, ownerPid): + """ + Expands relative paths to be an absolute path with reference to a given + process. This raises an IOError if the process pwd is required and can't be + resolved. + + Arguments: + path - path to be expanded + ownerPid - pid of the process to which the path belongs + """ + + if not path or path[0] == "/": return path + else: + if path.startswith("./"): path = path[2:] + processPwd = getPwd(ownerPid) + return "%s/%s" % (processPwd, path) + def call(command, cacheAge=0, suppressExc=False, quiet=True): """ Convenience function for performing system calls, providing: Modified: arm/trunk/src/util/torConfig.py =================================================================== --- arm/trunk/src/util/torConfig.py 2011-01-02 02:34:20 UTC (rev 24018) +++ arm/trunk/src/util/torConfig.py 2011-01-02 03:38:32 UTC (rev 24019) @@ -288,32 +288,13 @@ conn = torTools.getConn() configLocation = conn.getInfo("config-file") + torPid, torPrefix = conn.getMyPid(), conn.getPathPrefix() if not configLocation: raise IOError("unable to query the torrc location") - # checks if this is a relative path, needing the tor pwd to be appended - if configLocation[0] != "/": - torPid = conn.getMyPid() - failureMsg = "querying tor's pwd failed because %s" - if not torPid: raise IOError(failureMsg % "we couldn't get the pid") - - try: - # pwdx results are of the form: - # 3799: /home/atagar - # 5839: No such process - results = sysTools.call("pwdx %s" % torPid) - if not results: - raise IOError(failureMsg % "pwdx didn't return any results") - elif results[0].endswith("No such process"): - raise IOError(failureMsg % ("pwdx reported no process for pid " + torPid)) - elif len(results) != 1 or results.count(" ") != 1: - raise IOError(failureMsg % "we got unexpected output from pwdx") - else: - pwdPath = results[0][results[0].find(" ") + 1:] - configLocation = "%s/%s" % (pwdPath, configLocation) - except IOError, exc: - raise IOError(failureMsg % ("the pwdx call failed: " + str(exc))) - - return conn.getPathPrefix() + configLocation + try: + return torPrefix + sysTools.expandRelativePath(configLocation, torPid) + except IOError, exc: + raise IOError("querying tor's pwd failed because %s" % exc) def getMultilineParameters(): """
