Ejemplo n.º 1
0
 def __init__(self, processName, processPid = "", resolveRate = None, handle = None):
   """
   Initializes a new resolver daemon. When no longer needed it's suggested
   that this is stopped.
   
   Arguments:
     processName - name of the process being resolved
     processPid  - pid of the process being resolved
     resolveRate - time between resolving connections (in seconds, None if
                   chosen dynamically)
     handle      - name used to query this resolver, this is the processName
                   if undefined
   """
   
   threading.Thread.__init__(self)
   self.setDaemon(True)
   
   self.processName = processName
   self.processPid = processPid
   self.resolveRate = resolveRate
   self.handle = handle if handle else processName
   self.defaultRate = CONFIG["queries.connections.minRate"]
   self.lastLookup = -1
   self.overwriteResolver = None
   self.defaultResolver = Resolver.PROC
   
   osType = os.uname()[0]
   self.resolverOptions = getSystemResolvers(osType)
   
   log.log(CONFIG["log.connResolverOptions"], "Operating System: %s, Connection Resolvers: %s" % (osType, ", ".join(self.resolverOptions)))
   
   # sets the default resolver to be the first found in the system's PATH
   # (left as netstat if none are found)
   for resolver in self.resolverOptions:
     # Resolver strings correspond to their command with the exception of bsd
     # resolvers.
     resolverCmd = resolver.replace(" (bsd)", "")
     
     if resolver == Resolver.PROC or sysTools.isAvailable(resolverCmd):
       self.defaultResolver = resolver
       break
   
   self._connections = []        # connection cache (latest results)
   self._resolutionCounter = 0   # number of successful connection resolutions
   self._isPaused = False
   self._halt = False            # terminates thread if true
   self._cond = threading.Condition()  # used for pausing the thread
   self._subsiquentFailures = 0  # number of failed resolutions with the default in a row
   self._resolverBlacklist = []  # resolvers that have failed to resolve
   
   # Number of sequential times the threshold rate's been too low. This is to
   # avoid having stray spikes up the rate.
   self._rateThresholdBroken = 0
Ejemplo n.º 2
0
    def __init__(self, processName, processPid="", resolveRate=None):
        """
    Initializes a new resolver daemon. When no longer needed it's suggested
    that this is stopped.
    
    Arguments:
      processName - name of the process being resolved
      processPid  - pid of the process being resolved
      resolveRate - time between resolving connections (in seconds, None if
                    chosen dynamically)
    """

        threading.Thread.__init__(self)
        self.setDaemon(True)

        self.processName = processName
        self.processPid = processPid
        self.resolveRate = resolveRate
        self.defaultRate = CONFIG["queries.connections.minRate"]
        self.lastLookup = -1
        self.overwriteResolver = None
        self.defaultResolver = CMD_NETSTAT

        osType = os.uname()[0]
        self.resolverOptions = getSystemResolvers(osType)

        resolverLabels = ", ".join(
            [CMD_STR[option] for option in self.resolverOptions])
        log.log(
            CONFIG["log.connResolverOptions"],
            "Operating System: %s, Connection Resolvers: %s" %
            (osType, resolverLabels))

        # sets the default resolver to be the first found in the system's PATH
        # (left as netstat if none are found)
        for resolver in self.resolverOptions:
            if sysTools.isAvailable(CMD_STR[resolver]):
                self.defaultResolver = resolver
                break

        self._connections = []  # connection cache (latest results)
        self._isPaused = False
        self._halt = False  # terminates thread if true
        self._cond = threading.Condition()  # used for pausing the thread
        self._subsiquentFailures = 0  # number of failed resolutions with the default in a row
        self._resolverBlacklist = []  # resolvers that have failed to resolve

        # Number of sequential times the threshold rate's been too low. This is to
        # avoid having stray spikes up the rate.
        self._rateThresholdBroken = 0
Ejemplo n.º 3
0
 def __init__(self, processName, processPid = "", resolveRate = None):
   """
   Initializes a new resolver daemon. When no longer needed it's suggested
   that this is stopped.
   
   Arguments:
     processName - name of the process being resolved
     processPid  - pid of the process being resolved
     resolveRate - time between resolving connections (in seconds, None if
                   chosen dynamically)
   """
   
   threading.Thread.__init__(self)
   self.setDaemon(True)
   
   self.processName = processName
   self.processPid = processPid
   self.resolveRate = resolveRate
   self.defaultRate = CONFIG["queries.connections.minRate"]
   self.lastLookup = -1
   self.overwriteResolver = None
   self.defaultResolver = CMD_NETSTAT
   
   osType = os.uname()[0]
   self.resolverOptions = getSystemResolvers(osType)
   
   resolverLabels = ", ".join([CMD_STR[option] for option in self.resolverOptions])
   log.log(CONFIG["log.connResolverOptions"], "Operating System: %s, Connection Resolvers: %s" % (osType, resolverLabels))
   
   # sets the default resolver to be the first found in the system's PATH
   # (left as netstat if none are found)
   for resolver in self.resolverOptions:
     if sysTools.isAvailable(CMD_STR[resolver]):
       self.defaultResolver = resolver
       break
   
   self._connections = []        # connection cache (latest results)
   self._isPaused = False
   self._halt = False            # terminates thread if true
   self._cond = threading.Condition()  # used for pausing the thread
   self._subsiquentFailures = 0  # number of failed resolutions with the default in a row
   self._resolverBlacklist = []  # resolvers that have failed to resolve
   
   # Number of sequential times the threshold rate's been too low. This is to
   # avoid having stray spikes up the rate.
   self._rateThresholdBroken = 0
Ejemplo n.º 4
0
def showWizard():
    """
  Provides a series of prompts, allowing the user to spawn a customized tor
  instance.
  """

    if not sysTools.isAvailable("tor"):
        msg = "Unable to run the setup wizard. Is tor installed?"
        log.log(log.WARN, msg)
        return

    # gets tor's version
    torVersion = None
    try:
        versionQuery = sysTools.call("tor --version")

        for line in versionQuery:
            if line.startswith("Tor version "):
                torVersion = torTools.parseVersion(line.split(" ")[2])
                break
    except IOError, exc:
        log.log(log.INFO, "'tor --version' query failed: %s" % exc)
Ejemplo n.º 5
0
def showWizard():
  """
  Provides a series of prompts, allowing the user to spawn a customized tor
  instance.
  """
  
  if not sysTools.isAvailable("tor"):
    msg = "Unable to run the setup wizard. Is tor installed?"
    log.log(log.WARN, msg)
    return
  
  # gets tor's version
  torVersion = None
  try:
    versionQuery = sysTools.call("tor --version")
    
    for line in versionQuery:
      if line.startswith("Tor version "):
        torVersion = torTools.parseVersion(line.split(" ")[2])
        break
  except IOError, exc:
    log.log(log.INFO, "'tor --version' query failed: %s" % exc)
Ejemplo n.º 6
0
    controller = cli.controller.getController()
    manager = controller.getTorManager()
    relaySelection = RelayType.RESUME if manager.isTorrcAvailable(
    ) else RelayType.RELAY

    # excludes options that are either disabled or for a future tor version
    disabledOpt = list(CONFIG["wizard.disabled"])

    for opt, optVersion in VERSION_REQUIREMENTS.items():
        if not torVersion or not torTools.isVersion(
                torVersion, torTools.parseVersion(optVersion)):
            disabledOpt.append(opt)

    # the port forwarding option would only work if tor-fw-helper is in the path
    if not Options.PORTFORWARD in disabledOpt:
        if not sysTools.isAvailable("tor-fw-helper"):
            disabledOpt.append(Options.PORTFORWARD)

    # If we haven't run 'resources/torrcOverride/override.py --init' or lack
    # permissions then we aren't able to deal with the system wide tor instance.
    # Also drop the option if we aren't installed since override.py won't be at
    # the expected path.
    if not os.path.exists(os.path.dirname(
            SYSTEM_DROP_PATH)) or not os.path.exists(OVERRIDE_SCRIPT):
        disabledOpt.append(Options.SYSTEM)

    # TODO: The STARTUP option is currently disabled in the 'settings.cfg', and I
    # don't currently have plans to implement it (it would be a big pita, and the
    # tor deb already handles it). *If* it is implemented then I'd limit support
    # for the option to Debian and Ubuntu to start with, via the following...
Ejemplo n.º 7
0
 
 # remembers the last selection made on the type prompt page
 controller = cli.controller.getController()
 manager = controller.getTorManager()
 relaySelection = RelayType.RESUME if manager.isTorrcAvailable() else RelayType.RELAY
 
 # excludes options that are either disabled or for a future tor version
 disabledOpt = list(CONFIG["wizard.disabled"])
 
 for opt, optVersion in VERSION_REQUIREMENTS.items():
   if not torVersion or not torTools.isVersion(torVersion, torTools.parseVersion(optVersion)):
     disabledOpt.append(opt)
 
 # the port forwarding option would only work if tor-fw-helper is in the path
 if not Options.PORTFORWARD in disabledOpt:
   if not sysTools.isAvailable("tor-fw-helper"):
     disabledOpt.append(Options.PORTFORWARD)
 
 # If we haven't run 'resources/torrcOverride/override.py --init' or lack
 # permissions then we aren't able to deal with the system wide tor instance.
 # Also drop the option if we aren't installed since override.py won't be at
 # the expected path.
 if not os.path.exists(os.path.dirname(SYSTEM_DROP_PATH)) or not os.path.exists(OVERRIDE_SCRIPT):
   disabledOpt.append(Options.SYSTEM)
 
 # TODO: The STARTUP option is currently disabled in the 'settings.cfg', and I
 # don't currently have plans to implement it (it would be a big pita, and the
 # tor deb already handles it). *If* it is implemented then I'd limit support
 # for the option to Debian and Ubuntu to start with, via the following...
 
 # Running at startup is currently only supported for Debian and Ubuntu.
Ejemplo n.º 8
0
 def __init__(self, torPid):
   self.fdFile, self.fdConn, self.fdMisc = [], [], []
   self.fdLimit = 0
   self.errorMsg = ""
   self.scroll = 0
   
   try:
     ulimitCall = None
     
     # retrieves list of open files, options are:
     # n = no dns lookups, p = by pid, -F = show fields (L = login name, n = opened files)
     # TODO: better rewrite to take advantage of sysTools
     
     if not sysTools.isAvailable("lsof"): raise Exception("error: lsof is unavailable")
     results = sysTools.call("lsof -np %s -F Ln" % torPid)
     
     # if we didn't get any results then tor's probably closed (keep defaults)
     if len(results) == 0: return
     
     torUser = results[1][1:]
     results = results[2:] # skip first couple lines (pid listing and user)
     
     # splits descriptors into buckets according to their type
     descriptors = [entry[1:].strip() for entry in results] # strips off first character (always an 'n')
     
     # checks if read failed due to permission issues
     isPermissionDenied = True
     for desc in descriptors:
       if "Permission denied" not in desc:
         isPermissionDenied = False
         break
     
     if isPermissionDenied:
       raise Exception("lsof error: Permission denied")
     
     for desc in descriptors:
       if os.path.exists(desc): self.fdFile.append(desc)
       elif desc[0] != "/" and ":" in desc: self.fdConn.append(desc)
       else: self.fdMisc.append(desc)
     
     self.fdFile.sort()
     self.fdConn.sort()
     self.fdMisc.sort()
     
     # This is guessing the open file limit. Unfortunately there's no way
     # (other than "/usr/proc/bin/pfiles pid | grep rlimit" under Solaris) to
     # get the file descriptor limit for an arbitrary process. What we need is
     # for the tor process to provide the return value of the "getrlimit"
     # function via a GET_INFO call.
     if torUser.strip() == "debian-tor":
       # probably loaded via /etc/init.d/tor which changes descriptor limit
       self.fdLimit = 8192
     else:
       # uses ulimit to estimate (-H is for hard limit, which is what tor uses)
       ulimitCall = os.popen("ulimit -Hn 2> /dev/null")
       results = ulimitCall.readlines()
       if len(results) == 0: raise Exception("error: ulimit is unavailable")
       self.fdLimit = int(results[0])
       
       # can't use sysTools for this call because ulimit isn't in the path...
       # so how the **** am I to detect if it's available!
       #if not sysTools.isAvailable("ulimit"): raise Exception("error: ulimit is unavailable")
       #results = sysTools.call("ulimit -Hn")
       #if len(results) == 0: raise Exception("error: ulimit call failed")
       #self.fdLimit = int(results[0])
   except Exception, exc:
     # problem arose in calling or parsing lsof or ulimit calls
     self.errorMsg = str(exc)
Ejemplo n.º 9
0
    def __init__(self, torPid):
        self.fdFile, self.fdConn, self.fdMisc = [], [], []
        self.fdLimit = 0
        self.errorMsg = ""
        self.scroll = 0

        try:
            ulimitCall = None

            # retrieves list of open files, options are:
            # n = no dns lookups, p = by pid, -F = show fields (L = login name, n = opened files)
            # TODO: better rewrite to take advantage of sysTools

            if not sysTools.isAvailable("lsof"):
                raise Exception("error: lsof is unavailable")
            results = sysTools.call("lsof -np %s -F Ln" % torPid)

            # if we didn't get any results then tor's probably closed (keep defaults)
            if len(results) == 0: return

            torUser = results[1][1:]
            results = results[
                2:]  # skip first couple lines (pid listing and user)

            # splits descriptors into buckets according to their type
            descriptors = [entry[1:].strip() for entry in results
                           ]  # strips off first character (always an 'n')

            # checks if read failed due to permission issues
            isPermissionDenied = True
            for desc in descriptors:
                if "Permission denied" not in desc:
                    isPermissionDenied = False
                    break

            if isPermissionDenied:
                raise Exception("lsof error: Permission denied")

            for desc in descriptors:
                if os.path.exists(desc): self.fdFile.append(desc)
                elif desc[0] != "/" and ":" in desc: self.fdConn.append(desc)
                else: self.fdMisc.append(desc)

            self.fdFile.sort()
            self.fdConn.sort()
            self.fdMisc.sort()

            # This is guessing the open file limit. Unfortunately there's no way
            # (other than "/usr/proc/bin/pfiles pid | grep rlimit" under Solaris) to
            # get the file descriptor limit for an arbitrary process. What we need is
            # for the tor process to provide the return value of the "getrlimit"
            # function via a GET_INFO call.
            if torUser.strip() == "debian-tor":
                # probably loaded via /etc/init.d/tor which changes descriptor limit
                self.fdLimit = 8192
            else:
                # uses ulimit to estimate (-H is for hard limit, which is what tor uses)
                ulimitCall = os.popen("ulimit -Hn 2> /dev/null")
                results = ulimitCall.readlines()
                if len(results) == 0:
                    raise Exception("error: ulimit is unavailable")
                self.fdLimit = int(results[0])

                # can't use sysTools for this call because ulimit isn't in the path...
                # so how the **** am I to detect if it's available!
                #if not sysTools.isAvailable("ulimit"): raise Exception("error: ulimit is unavailable")
                #results = sysTools.call("ulimit -Hn")
                #if len(results) == 0: raise Exception("error: ulimit call failed")
                #self.fdLimit = int(results[0])
        except Exception, exc:
            # problem arose in calling or parsing lsof or ulimit calls
            self.errorMsg = str(exc)
Ejemplo n.º 10
0
 def reload(self, issueSighup = False):
   """
   This resets tor (sending a RELOAD signal to the control port) causing tor's
   internal state to be reset and the torrc reloaded. This can either be done
   by...
     - the controller via a RELOAD signal (default and suggested)
         conn.send_signal("RELOAD")
     - system reload signal (hup)
         pkill -sighup tor
   
   The later isn't really useful unless there's some reason the RELOAD signal
   won't do the trick. Both methods raise an IOError in case of failure.
   
   Arguments:
     issueSighup - issues a sighup rather than a controller RELOAD signal
   """
   
   self.connLock.acquire()
   
   raisedException = None
   if self.isAlive():
     if not issueSighup:
       try:
         self.conn.send_signal("RELOAD")
         self._cachedParam = dict([(arg, "") for arg in CACHE_ARGS])
         self._cachedConf = {}
       except Exception, exc:
         # new torrc parameters caused an error (tor's likely shut down)
         # BUG: this doesn't work - torrc errors still cause TorCtl to crash... :(
         # http://bugs.noreply.org/flyspray/index.php?do=details&id=1329
         raisedException = IOError(str(exc))
     else:
       try:
         # Redirects stderr to stdout so we can check error status (output
         # should be empty if successful). Example error:
         # pkill: 5592 - Operation not permitted
         #
         # note that this may provide multiple errors, even if successful,
         # hence this:
         #   - only provide an error if Tor fails to log a sighup
         #   - provide the error message associated with the tor pid (others
         #     would be a red herring)
         if not sysTools.isAvailable("pkill"):
           raise IOError("pkill command is unavailable")
         
         self._isReset = False
         pkillCall = os.popen("pkill -sighup ^tor$ 2> /dev/stdout")
         pkillOutput = pkillCall.readlines()
         pkillCall.close()
         
         # Give the sighupTracker a moment to detect the sighup signal. This
         # is, of course, a possible concurrency bug. However I'm not sure
         # of a better method for blocking on this...
         waitStart = time.time()
         while time.time() - waitStart < 1:
           time.sleep(0.1)
           if self._isReset: break
         
         if not self._isReset:
           errorLine, torPid = "", self.getMyPid()
           if torPid:
             for line in pkillOutput:
               if line.startswith("pkill: %s - " % torPid):
                 errorLine = line
                 break
           
           if errorLine: raise IOError(" ".join(errorLine.split()[3:]))
           else: raise IOError("failed silently")
         
         self._cachedParam = dict([(arg, "") for arg in CACHE_ARGS])
         self._cachedConf = {}
       except IOError, exc:
         raisedException = exc