Ejemplo n.º 1
0
        def _edit_selected_value():
            selected = self._scroller.selection(self._get_config_options())
            initial_value = selected.value() if selected.is_set() else ''
            new_value = nyx.controller.input_prompt(
                '%s Value (esc to cancel): ' % selected.name, initial_value)

            if new_value != initial_value:
                try:
                    if selected.value_type == 'Boolean':
                        # if the value's a boolean then allow for 'true' and 'false' inputs

                        if new_value.lower() == 'true':
                            new_value = '1'
                        elif new_value.lower() == 'false':
                            new_value = '0'
                    elif selected.value_type == 'LineList':
                        new_value = new_value.split(
                            ',')  # set_conf accepts list inputs

                    tor_controller().set_conf(selected.name, new_value)
                    self.redraw()
                except Exception as exc:
                    nyx.controller.show_message('%s (press any key)' % exc,
                                                HIGHLIGHT,
                                                max_wait=30)
Ejemplo n.º 2
0
def _draw_address_column(subwindow, x, y, line, attr):
  src = tor_controller().get_info('address', line.connection.local_address)
  src += ':%s' % line.connection.local_port if line.line_type == LineType.CONNECTION else ''

  if line.line_type == LineType.CIRCUIT_HEADER and line.circuit.status != 'BUILT':
    dst = 'Building...'
  else:
    dst = '<scrubbed>' if line.entry.is_private() else line.connection.remote_address
    dst += ':%s' % line.connection.remote_port

    if line.entry.get_type() == Category.EXIT:
      purpose = connection.port_usage(line.connection.remote_port)

      if purpose:
        dst += ' (%s)' % str_tools.crop(purpose, 26 - len(dst) - 3)
    elif not tor_controller().is_geoip_unavailable() and not line.entry.is_private():
      dst += ' (%s)' % (line.locale if line.locale else '??')

  if line.entry.get_type() in (Category.INBOUND, Category.SOCKS, Category.CONTROL):
    dst, src = src, dst

  if line.line_type == LineType.CIRCUIT:
    subwindow.addstr(x, y, dst, *attr)
  else:
    subwindow.addstr(x, y, '%-21s  -->  %-26s' % (src, dst), *attr)
Ejemplo n.º 3
0
def _draw_address_column(subwindow, x, y, line, attr):
    src = tor_controller().get_info('address', line.connection.local_address)

    if line.line_type == LineType.CONNECTION:
        src = '%s:%s' % (src, line.connection.local_port)

    if line.line_type == LineType.CIRCUIT_HEADER and line.circuit.status != 'BUILT':
        dst = 'Building...'
    else:
        dst = '<scrubbed>' if line.entry.is_private(
        ) else line.connection.remote_address
        dst += ':%s' % line.connection.remote_port

        if line.entry.get_type() == Category.EXIT:
            purpose = connection.port_usage(line.connection.remote_port)

            if purpose:
                dst += ' (%s)' % str_tools.crop(purpose, 26 - len(dst) - 3)
        elif not tor_controller().is_geoip_unavailable(
        ) and not line.entry.is_private():
            dst += ' (%s)' % (line.locale if line.locale else '??')

    src = '%-21s' % src
    dst = '%-21s' % dst if tor_controller().is_geoip_unavailable(
    ) else '%-26s' % dst

    if line.entry.get_type() in (Category.INBOUND, Category.SOCKS,
                                 Category.CONTROL):
        dst, src = src, dst

    if line.line_type == LineType.CIRCUIT:
        return subwindow.addstr(x, y, dst, *attr)
    else:
        return subwindow.addstr(x, y, '%s  -->  %s' % (src, dst), *attr)
Ejemplo n.º 4
0
  def __init__(self):
    nyx.panel.DaemonPanel.__init__(self, UPDATE_RATE)
    self._vals = Sampling.create()

    self._last_width = nyx.curses.screen_size().width
    self._reported_inactive = False

    self._message = None
    self._message_attr = []

    tor_controller().add_status_listener(self.reset_listener)
Ejemplo n.º 5
0
    def __init__(self):
        nyx.panel.DaemonPanel.__init__(self, UPDATE_RATE)
        self._vals = Sampling.create()

        self._last_width = nyx.curses.screen_size().width
        self._reported_inactive = False

        self._message = None
        self._message_attr = []

        tor_controller().add_status_listener(self.reset_listener)
Ejemplo n.º 6
0
  def __init__(self):
    nyx.panel.Panel.__init__(self)

    self._displayed_stat = None if CONFIG['features.graph.type'] == 'none' else CONFIG['features.graph.type']
    self._update_interval = CONFIG['features.graph.interval']
    self._bounds = CONFIG['features.graph.bound']
    self._graph_height = CONFIG['features.graph.height']

    self._accounting_stats = None
    self._accounting_stats_paused = None

    self._stats = {
      GraphStat.BANDWIDTH: BandwidthStats(),
      GraphStat.SYSTEM_RESOURCES: ResourceStats(),
    }

    self._stats_paused = None

    if CONFIG['features.panels.show.connection']:
      self._stats[GraphStat.CONNECTIONS] = ConnectionStats()
    elif self._displayed_stat == GraphStat.CONNECTIONS:
      log.warn("The connection graph is unavailble when you set 'features.panels.show.connection false'.")
      self._displayed_stat = GraphStat.BANDWIDTH

    controller = tor_controller()
    controller.add_event_listener(self._update_accounting, EventType.BW)
    controller.add_event_listener(self._update_stats, EventType.BW)
    controller.add_status_listener(lambda *args: self.redraw())
Ejemplo n.º 7
0
    def __init__(self, rate):
        super(ConnectionTracker, self).__init__(rate)

        self._connections = []
        self._start_times = {}  # connection => (unix_timestamp, is_legacy)
        self._custom_resolver = None
        self._is_first_run = True

        # Number of times in a row we've either failed with our current resolver or
        # concluded that our rate is too low.

        self._failure_count = 0
        self._rate_too_low_count = 0

        # If 'DisableDebuggerAttachment 0' is set we can do normal connection
        # resolution. Otherwise connection resolution by inference is the only game
        # in town.

        self._resolvers = [CustomResolver.INFERENCE
                           ] if stem.util.proc.is_available() else []

        if tor_controller().get_conf('DisableDebuggerAttachment', None) == '0':
            self._resolvers = self._resolvers + connection.system_resolvers()
        elif not self._resolvers:
            stem.util.log.notice(
                "Tor connection information is unavailable. This is fine, but if you would like to have it please see https://nyx.torproject.org/#no_connections"
            )

        stem.util.log.info('Operating System: %s, Connection Resolvers: %s' %
                           (os.uname()[0], ', '.join(self._resolvers)))
Ejemplo n.º 8
0
  def __init__(self, clone = None):
    GraphCategory.__init__(self, clone)

    if not clone:
      # fill in past bandwidth information

      controller = tor_controller()
      bw_entries, is_successful = controller.get_info('bw-event-cache', None), True

      if bw_entries:
        for entry in bw_entries.split():
          entry_comp = entry.split(',')

          if len(entry_comp) != 2 or not entry_comp[0].isdigit() or not entry_comp[1].isdigit():
            log.warn(msg('panel.graphing.bw_event_cache_malformed', response = bw_entries))
            is_successful = False
            break

          self.primary.update(int(entry_comp[0]))
          self.secondary.update(int(entry_comp[1]))

        if is_successful:
          log.info(msg('panel.graphing.prepopulation_successful', duration = str_tools.time_label(len(bw_entries.split()), is_long = True)))

      read_total = controller.get_info('traffic/read', None)
      write_total = controller.get_info('traffic/written', None)
      start_time = system.start_time(controller.get_pid(None))

      if read_total and write_total and start_time:
        self.primary.total = int(read_total)
        self.secondary.total = int(write_total)
        self.start_time = start_time
Ejemplo n.º 9
0
Archivo: log.py Proyecto: sammyshj/nyx
def listen_for_events(listener, events):
  """
  Configures tor to notify a function of these event types. If tor is
  configured to notify this listener then the old listener is replaced.

  :param function listener: listener to be notified
  :param list events: event types to attempt to set

  :returns: **list** of event types we're successfully now listening to
  """

  events = set(events)  # drops duplicates
  nyx_events = events.intersection(set(NYX_RUNLEVELS))
  tor_events = events.difference(nyx_events)

  controller = nyx.tor_controller()
  controller.remove_event_listener(listener)

  for event_type in list(tor_events):
    try:
      controller.add_event_listener(listener, event_type)
    except stem.ProtocolError:
      warn('panel.log.unsupported_event', event = event_type)
      tor_events.remove(event_type)

  return sorted(tor_events.union(nyx_events))
Ejemplo n.º 10
0
Archivo: log.py Proyecto: patacca/nyx
def listen_for_events(listener, events):
  """
  Configures tor to notify a function of these event types. If tor is
  configured to notify this listener then the old listener is replaced.

  :param function listener: listener to be notified
  :param list events: event types to attempt to set

  :returns: **list** of event types we're successfully now listening to
  """

  import nyx.arguments
  events = set(events)  # drops duplicates

  # accounts for runlevel naming difference

  tor_events = events.intersection(set(nyx.arguments.TOR_EVENT_TYPES.values()))
  nyx_events = events.intersection(set(NYX_RUNLEVELS))

  # adds events unrecognized by nyx if we're listening to the 'UNKNOWN' type

  if 'UNKNOWN' in events:
    tor_events.update(set(nyx.arguments.missing_event_types()))

  controller = nyx.tor_controller()
  controller.remove_event_listener(listener)

  for event_type in list(tor_events):
    try:
      controller.add_event_listener(listener, event_type)
    except stem.ProtocolError:
      tor_events.remove(event_type)

  return sorted(tor_events.union(nyx_events))
Ejemplo n.º 11
0
    def bandwidth_event(self, event):
        inbound_count, outbound_count = 0, 0

        controller = tor_controller()
        or_ports = controller.get_ports(Listener.OR, [])
        dir_ports = controller.get_ports(Listener.DIR, [])
        control_ports = controller.get_ports(Listener.CONTROL, [])

        for entry in nyx.tracker.get_connection_tracker().get_value():
            if entry.local_port in or_ports or entry.local_port in dir_ports:
                inbound_count += 1
            elif entry.local_port in control_ports:
                pass  # control connection
            else:
                outbound_count += 1

        self.primary.update(inbound_count)
        self.secondary.update(outbound_count)

        self._primary_header_stats = [
            str(self.primary.latest_value),
            ', avg: %i' % self.primary.average()
        ]
        self._secondary_header_stats = [
            str(self.secondary.latest_value),
            ', avg: %i' % self.secondary.average()
        ]
Ejemplo n.º 12
0
    def __init__(self):
        self._my_router_status_entry = None
        self._my_router_status_entry_time = 0

        # Stem's get_network_statuses() is slow, and overkill for what we need
        # here. Just parsing the raw GETINFO response to cut startup time down.
        #
        # Only fetching this if our cache is at least an hour old (and hence a new
        # consensus available).

        cache_age = time.time() - nyx.cache().relays_updated_at()
        controller = tor_controller()

        if cache_age < 3600:
            stem.util.log.info('Cache is only %s old, no need to refresh it.' %
                               str_tools.time_label(cache_age, is_long=True))
        else:
            stem.util.log.info(
                'Cache is %s old, refreshing relay information.' %
                str_tools.time_label(cache_age, is_long=True))
            ns_response = controller.get_info('ns/all', None)

            if ns_response:
                self._update(ns_response)

        controller.add_event_listener(
            lambda event: self._update(event.consensus_content),
            stem.control.EventType.NEWCONSENSUS)
Ejemplo n.º 13
0
  def _draw_details(self, selected, width, is_scrollbar_visible):
    """
    Shows detailed information about the selected connection.
    """

    attr = (CONFIG['attr.connection.category_color'].get(selected.entry.get_type(), WHITE), BOLD)

    if selected.line_type == LineType.CIRCUIT_HEADER and selected.circuit.status != 'BUILT':
      self.addstr(1, 2, 'Building Circuit...', *attr)
    else:
      address = '<scrubbed>' if selected.entry.is_private() else selected.connection.remote_address
      self.addstr(1, 2, 'address: %s:%s' % (address, selected.connection.remote_port), *attr)
      self.addstr(2, 2, 'locale: %s' % ('??' if selected.entry.is_private() else (selected.locale if selected.locale else '??')), *attr)

      matches = nyx.tracker.get_consensus_tracker().get_relay_fingerprints(selected.connection.remote_address)

      if not matches:
        self.addstr(3, 2, 'No consensus data found', *attr)
      elif len(matches) == 1 or selected.connection.remote_port in matches:
        controller = tor_controller()
        fingerprint = matches.values()[0] if len(matches) == 1 else matches[selected.connection.remote_port]
        router_status_entry = controller.get_network_status(fingerprint, None)

        self.addstr(2, 15, 'fingerprint: %s' % fingerprint, *attr)

        if router_status_entry:
          dir_port_label = 'dirport: %s' % router_status_entry.dir_port if router_status_entry.dir_port else ''
          self.addstr(3, 2, 'nickname: %-25s orport: %-10s %s' % (router_status_entry.nickname, router_status_entry.or_port, dir_port_label), *attr)
          self.addstr(4, 2, 'published: %s' % router_status_entry.published.strftime("%H:%M %m/%d/%Y"), *attr)
          self.addstr(5, 2, 'flags: %s' % ', '.join(router_status_entry.flags), *attr)

          server_descriptor = controller.get_server_descriptor(fingerprint, None)

          if server_descriptor:
            policy_label = server_descriptor.exit_policy.summary() if server_descriptor.exit_policy else 'unknown'
            self.addstr(6, 2, 'exit policy: %s' % policy_label, *attr)
            self.addstr(4, 38, 'os: %-14s version: %s' % (server_descriptor.operating_system, server_descriptor.tor_version), *attr)

            if server_descriptor.contact:
              self.addstr(7, 2, 'contact: %s' % server_descriptor.contact, *attr)
      else:
        self.addstr(3, 2, 'Multiple matches, possible fingerprints are:', *attr)

        for i, port in enumerate(sorted(matches.keys())):
          is_last_line, remaining_relays = i == 3, len(matches) - i

          if not is_last_line or remaining_relays == 1:
            self.addstr(4 + i, 2, '%i. or port: %-5s fingerprint: %s' % (i + 1, port, matches[port]), *attr)
          else:
            self.addstr(4 + i, 2, '... %i more' % remaining_relays, *attr)

          if is_last_line:
            break

    # draw the border, with a 'T' pipe if connecting with the scrollbar

    self.draw_box(0, 0, width, DETAILS_HEIGHT + 2)

    if is_scrollbar_visible:
      self.addch(DETAILS_HEIGHT + 1, 1, curses.ACS_TTEE)
Ejemplo n.º 14
0
  def draw(self, width, height):
    controller = tor_controller()
    entries = self._entries

    lines = list(itertools.chain.from_iterable([entry.get_lines() for entry in entries]))
    is_showing_details = self._show_details and lines
    details_offset = DETAILS_HEIGHT + 1 if is_showing_details else 0
    selected, scroll = self._scroller.selection(lines, height - details_offset - 1)

    if self.is_paused():
      current_time = self.get_pause_time()
    elif not controller.is_alive():
      current_time = controller.connection_time()
    else:
      current_time = time.time()

    is_scrollbar_visible = len(lines) > height - details_offset - 1
    scroll_offset = 2 if is_scrollbar_visible else 0

    self._draw_title(entries, self._show_details)

    if is_showing_details:
      self._draw_details(selected, width, is_scrollbar_visible)

    if is_scrollbar_visible:
      self.add_scroll_bar(scroll, scroll + height - details_offset - 1, len(lines), 1 + details_offset)

    for line_number in range(scroll, len(lines)):
      y = line_number + details_offset + 1 - scroll
      self._draw_line(scroll_offset, y, lines[line_number], lines[line_number] == selected, width - scroll_offset, current_time)

      if y >= height:
        break
Ejemplo n.º 15
0
    def __init__(self, rate):
        super(ConnectionTracker, self).__init__(rate)

        self._connections = []
        self._start_times = {}  # connection => (unix_timestamp, is_legacy)
        self._custom_resolver = None
        self._is_first_run = True

        # Number of times in a row we've either failed with our current resolver or
        # concluded that our rate is too low.

        self._failure_count = 0
        self._rate_too_low_count = 0

        # If 'DisableDebuggerAttachment 0' is set we can do normal connection
        # resolution. Otherwise connection resolution by inference is the only game
        # in town.

        self._resolvers = []

        if tor_controller().get_conf('DisableDebuggerAttachment', None) == '0':
            self._resolvers = connection.system_resolvers()

        if stem.util.proc.is_available():
            self._resolvers = [CustomResolver.INFERENCE] + self._resolvers

        stem.util.log.info('Operating System: %s, Connection Resolvers: %s' %
                           (os.uname()[0], ', '.join(self._resolvers)))
Ejemplo n.º 16
0
  def get_type(self):
    controller = tor_controller()

    if self._connection.local_port in controller.get_ports(Listener.OR, []):
      return Category.INBOUND
    elif self._connection.local_port in controller.get_ports(Listener.DIR, []):
      return Category.INBOUND
    elif self._connection.local_port in controller.get_ports(Listener.SOCKS, []):
      return Category.SOCKS
    elif self._connection.local_port in controller.get_ports(Listener.CONTROL, []):
      return Category.CONTROL

    if LAST_RETRIEVED_HS_CONF:
      for hs_config in LAST_RETRIEVED_HS_CONF.values():
        if self._connection.remote_port == hs_config['HiddenServicePort']:
          return Category.HIDDEN

    fingerprint = nyx.tracker.get_consensus_tracker().get_relay_fingerprints(self._connection.remote_address).get(self._connection.remote_port)

    if fingerprint and LAST_RETRIEVED_CIRCUITS:
      for circ in LAST_RETRIEVED_CIRCUITS:
        if circ.path and len(circ.path) == 1 and circ.path[0][0] == fingerprint and circ.status == 'BUILT':
          return Category.DIRECTORY  # one-hop circuit to retrieve directory information
    else:
      # not a known relay, might be an exit connection

      exit_policy = controller.get_exit_policy(None)

      if exit_policy and exit_policy.can_exit_to(self._connection.remote_address, self._connection.remote_port):
        return Category.EXIT

    return Category.OUTBOUND
Ejemplo n.º 17
0
  def _get_type(self):
    controller = tor_controller()

    if self._connection.local_port in controller.get_ports(Listener.OR, []):
      return Category.INBOUND
    elif self._connection.local_port in controller.get_ports(Listener.DIR, []):
      return Category.INBOUND
    elif self._connection.local_port in controller.get_ports(Listener.SOCKS, []):
      return Category.SOCKS
    elif self._connection.local_port in controller.get_ports(Listener.CONTROL, []):
      return Category.CONTROL

    if LAST_RETRIEVED_HS_CONF:
      for hs_config in LAST_RETRIEVED_HS_CONF.values():
        if self._connection.remote_port == hs_config['HiddenServicePort']:
          return Category.HIDDEN

    fingerprint = nyx.tracker.get_consensus_tracker().get_relay_fingerprints(self._connection.remote_address).get(self._connection.remote_port)
    exit_policy = controller.get_exit_policy(None)

    if fingerprint and LAST_RETRIEVED_CIRCUITS:
      for circ in LAST_RETRIEVED_CIRCUITS:
        if circ.path and len(circ.path) == 1 and circ.path[0][0] == fingerprint and circ.status == 'BUILT':
          return Category.DIRECTORY  # one-hop circuit to retrieve directory information
    elif not fingerprint and exit_policy and exit_policy.can_exit_to(self._connection.remote_address, self._connection.remote_port):
      return Category.EXIT

    return Category.OUTBOUND
Ejemplo n.º 18
0
def listen_for_events(listener, events):
    """
  Configures tor to notify a function of these event types. If tor is
  configured to notify this listener then the old listener is replaced.

  :param function listener: listener to be notified
  :param list events: event types to attempt to set

  :returns: **list** of event types we're successfully now listening to
  """

    events = set(events)  # drops duplicates
    nyx_events = events.intersection(set(NYX_RUNLEVELS))
    tor_events = events.difference(nyx_events)

    controller = nyx.tor_controller()
    controller.remove_event_listener(listener)

    for event_type in list(tor_events):
        try:
            controller.add_event_listener(listener, event_type)
        except stem.ProtocolError:
            stem.util.log.warn("%s isn't an event tor supports" % event_type)
            tor_events.remove(event_type)

    return sorted(tor_events.union(nyx_events))
Ejemplo n.º 19
0
def _bandwidth_title_stats():
  controller = tor_controller()

  stats = []
  bw_rate = controller.get_effective_rate(None)
  bw_burst = controller.get_effective_rate(None, burst = True)

  if bw_rate and bw_burst:
    bw_rate_label = _size_label(bw_rate)
    bw_burst_label = _size_label(bw_burst)

    # if both are using rounded values then strip off the '.0' decimal

    if '.0' in bw_rate_label and '.0' in bw_burst_label:
      bw_rate_label = bw_rate_label.replace('.0', '')
      bw_burst_label = bw_burst_label.replace('.0', '')

    stats.append('limit: %s/s' % bw_rate_label)
    stats.append('burst: %s/s' % bw_burst_label)

  my_server_descriptor = controller.get_server_descriptor(default = None)
  observed_bw = getattr(my_server_descriptor, 'observed_bandwidth', None)

  if observed_bw:
    stats.append('observed: %s/s' % _size_label(observed_bw))

  return stats
Ejemplo n.º 20
0
  def __init__(self, clone = None):
    GraphCategory.__init__(self, clone)
    self._title_last_updated = None

    if not clone:
      # fill in past bandwidth information

      controller = tor_controller()
      bw_entries, is_successful = controller.get_info('bw-event-cache', None), True

      if bw_entries:
        for entry in bw_entries.split():
          entry_comp = entry.split(',')

          if len(entry_comp) != 2 or not entry_comp[0].isdigit() or not entry_comp[1].isdigit():
            log.warn("Tor's 'GETINFO bw-event-cache' provided malformed output: %s" % bw_entries)
            is_successful = False
            break

          self.primary.update(int(entry_comp[0]))
          self.secondary.update(int(entry_comp[1]))

        if is_successful:
          log.info('Bandwidth graph has information for the last %s' % str_tools.time_label(len(bw_entries.split()), is_long = True))

      read_total = controller.get_info('traffic/read', None)
      write_total = controller.get_info('traffic/written', None)
      start_time = system.start_time(controller.get_pid(None))

      if read_total and write_total and start_time:
        self.primary.total = int(read_total)
        self.secondary.total = int(write_total)
        self.start_time = start_time
Ejemplo n.º 21
0
  def __init__(self):
    nyx.panel.Panel.__init__(self)

    self._displayed_stat = None if CONFIG['graph_stat'] == 'none' else CONFIG['graph_stat']
    self._update_interval = CONFIG['graph_interval']
    self._bounds_type = CONFIG['graph_bound']
    self._graph_height = CONFIG['graph_height']

    self._accounting_stats = None
    self._accounting_stats_paused = None

    self._stats = {
      GraphStat.BANDWIDTH: BandwidthStats(),
      GraphStat.SYSTEM_RESOURCES: ResourceStats(),
    }

    self._stats_lock = threading.RLock()
    self._stats_paused = None

    if CONFIG['show_connections']:
      self._stats[GraphStat.CONNECTIONS] = ConnectionStats()
    elif self._displayed_stat == GraphStat.CONNECTIONS:
      log.warn("The connection graph is unavailble when you set 'show_connections false'.")
      self._displayed_stat = GraphStat.BANDWIDTH

    controller = tor_controller()
    controller.add_event_listener(self._update_accounting, EventType.BW)
    controller.add_event_listener(self._update_stats, EventType.BW)
    controller.add_status_listener(lambda *args: self.redraw())
Ejemplo n.º 22
0
def make_actions_menu():
  """
  Submenu consisting of...
    Close Menu
    New Identity
    Reset Tor
    Pause / Unpause
    Exit
  """

  control = nyx.controller.get_controller()
  controller = tor_controller()
  header_panel = control.header_panel()
  actions_menu = Submenu('Actions')
  actions_menu.add(MenuItem('Close Menu', None))
  actions_menu.add(MenuItem('New Identity', header_panel.send_newnym))
  actions_menu.add(MenuItem('Reset Tor', functools.partial(controller.signal, stem.Signal.RELOAD)))

  if control.is_paused():
    label, arg = 'Unpause', False
  else:
    label, arg = 'Pause', True

  actions_menu.add(MenuItem(label, functools.partial(control.set_paused, arg)))
  actions_menu.add(MenuItem('Exit', control.quit))

  return actions_menu
Ejemplo n.º 23
0
    def _show_write_dialog(self):
        """
    Confirmation dialog for saving tor's configuration.
    """

        controller = tor_controller()
        torrc = controller.get_info('config-text', None)

        if nyx.popups.confirm_save_torrc(torrc):
            try:
                controller.save_conf()
                show_message('Saved configuration to %s' %
                             controller.get_info('config-file', '<unknown>'),
                             HIGHLIGHT,
                             max_wait=2)
            except stem.OperationFailed as exc:
                show_message('Unable to save configuration ([%s] %s)' %
                             (exc.code, exc.message),
                             HIGHLIGHT,
                             max_wait=2)
            except stem.ControllerError as exc:
                show_message('Unable to save configuration (%s)' % exc,
                             HIGHLIGHT,
                             max_wait=2)

        self.redraw()
Ejemplo n.º 24
0
  def is_set(self):
    """
    Checks if the configuration option has a custom value.

    :returns: **True** if the option has a custom value, **False** otherwise
    """

    return tor_controller().is_set(self.name, False)
Ejemplo n.º 25
0
    def is_set(self):
        """
    Checks if the configuration option has a custom value.

    :returns: **True** if the option has a custom value, **False** otherwise
    """

        return tor_controller().is_set(self.name, False)
Ejemplo n.º 26
0
    def __init__(self):
        nyx.panel.Panel.__init__(self)

        self._contents = []
        self._scroller = nyx.curses.CursorScroller()
        self._sort_order = CONFIG['features.config.order']
        self._show_all = False  # show all options, or just the important ones

        cached_manual_path = os.path.join(DATA_DIR, 'manual')

        if os.path.exists(cached_manual_path):
            manual = stem.manual.Manual.from_cache(cached_manual_path)
        else:
            try:
                manual = stem.manual.Manual.from_man()

                try:
                    manual.save(cached_manual_path)
                except IOError as exc:
                    log.debug(
                        "Unable to cache manual information to '%s'. This is fine, but means starting Nyx takes a little longer than usual: "
                        % (cached_manual_path, exc))
            except IOError as exc:
                log.debug(
                    "Unable to use 'man tor' to get information about config options (%s), using bundled information instead"
                    % exc)
                manual = stem.manual.Manual.from_cache()

        try:
            for line in tor_controller().get_info('config/names').splitlines():
                # Lines of the form "<option> <type>[ <documentation>]". Documentation
                # was apparently only in old tor versions like 0.2.1.25.

                if ' ' not in line:
                    continue

                line_comp = line.split()
                name, value_type = line_comp[0], line_comp[1]

                # skips private and virtual entries if not configured to show them

                if name.startswith('__') and not CONFIG[
                        'features.config.state.showPrivateOptions']:
                    continue
                elif value_type == 'Virtual' and not CONFIG[
                        'features.config.state.showVirtualOptions']:
                    continue

                self._contents.append(ConfigEntry(name, value_type, manual))

            self._contents = sorted(
                self._contents,
                key=lambda entry:
                [entry.sort_value(field) for field in self._sort_order])
        except stem.ControllerError as exc:
            log.warn(
                'Unable to determine the configuration options tor supports: %s'
                % exc)
Ejemplo n.º 27
0
  def __init__(self):
    nyx.panel.DaemonPanel.__init__(self, UPDATE_RATE)

    logged_events = CONFIG['startup.events'].split(',')
    tor_events = tor_controller().get_info('events/names', '').split()
    invalid_events = filter(lambda event: not event.startswith('NYX_') and event not in tor_events, logged_events)

    if invalid_events:
      logged_events = ['NOTICE', 'WARN', 'ERR', 'NYX_NOTICE', 'NYX_WARNING', 'NYX_ERROR']
      log.warn("Your --log argument had the following events tor doesn't recognize: %s" % ', '.join(invalid_events))

    self._event_log = nyx.log.LogGroup(CONFIG['cache.log_panel.size'], group_by_day = True)
    self._event_log_paused = None
    self._event_types = nyx.log.listen_for_events(self._register_tor_event, logged_events)
    self._log_file = nyx.log.LogFileOutput(CONFIG['features.logFile'])
    self._filter = nyx.log.LogFilters(initial_filters = CONFIG['features.log.regex'])
    self._show_duplicates = CONFIG['features.log.showDuplicateEntries']

    self._scroller = nyx.curses.Scroller()
    self._has_new_event = False
    self._last_day = nyx.log.day_count(time.time())

    # fetches past tor events from log file, if available

    if CONFIG['features.log.prepopulate']:
      log_location = nyx.log.log_file_path(tor_controller())

      if log_location:
        try:
          for entry in reversed(list(nyx.log.read_tor_log(log_location, CONFIG['features.log.prepopulateReadLimit']))):
            if entry.type in self._event_types:
              self._event_log.add(entry)
        except IOError as exc:
          log.info('Unable to read log located at %s: %s' % (log_location, exc))
        except ValueError as exc:
          log.info(str(exc))

    self._last_content_height = len(self._event_log)  # height of the rendered content when last drawn

    # merge NYX_LOGGER into us, and listen for its future events

    for event in NYX_LOGGER:
      self._register_nyx_event(event)

    NYX_LOGGER.emit = self._register_nyx_event
Ejemplo n.º 28
0
  def _update(self):
    """
    Fetches the newest resolved connections.
    """

    global LAST_RETRIEVED_CIRCUITS, LAST_RETRIEVED_HS_CONF

    controller = tor_controller()
    LAST_RETRIEVED_CIRCUITS = controller.get_circuits([])
    LAST_RETRIEVED_HS_CONF = controller.get_hidden_service_conf({})

    conn_resolver = nyx.tracker.get_connection_tracker()
    current_resolution_count = conn_resolver.run_counter()

    if not conn_resolver.is_alive():
      return  # if we're not fetching connections then this is a no-op
    elif current_resolution_count == self._last_resource_fetch:
      return  # no new connections to process

    new_entries = [Entry.from_connection(conn) for conn in conn_resolver.get_value()]

    for circ in LAST_RETRIEVED_CIRCUITS:
      # Skips established single-hop circuits (these are for directory
      # fetches, not client circuits)

      if not (circ.status == 'BUILT' and len(circ.path) == 1):
        new_entries.append(Entry.from_circuit(circ))

    # update stats for client and exit connections

    for entry in new_entries:
      line = entry.get_lines()[0]

      if entry.is_private() and line.connection not in self._counted_connections:
        if entry.get_type() == Category.INBOUND and line.locale:
          self._client_locale_usage[line.locale] = self._client_locale_usage.get(line.locale, 0) + 1
        elif entry.get_type() == Category.EXIT:
          self._exit_port_usage[line.connection.remote_port] = self._exit_port_usage.get(line.connection.remote_port, 0) + 1

        self._counted_connections.add(line.connection)

    self._entries = sorted(new_entries, key = lambda entry: [entry.sort_value(attr) for attr in self._sort_order])
    self._last_resource_fetch = current_resolution_count

    if CONFIG['features.connection.resolveApps']:
      local_ports, remote_ports = [], []

      for entry in new_entries:
        line = entry.get_lines()[0]

        if entry.get_type() in (Category.SOCKS, Category.CONTROL):
          local_ports.append(line.connection.remote_port)
        elif entry.get_type() == Category.HIDDEN:
          remote_ports.append(line.connection.local_port)

      nyx.tracker.get_port_usage_tracker().query(local_ports, remote_ports)
Ejemplo n.º 29
0
def _draw_details(subwindow, selected):
  """
  Shows detailed information about the selected connection.
  """

  attr = (CONFIG['attr.connection.category_color'].get(selected.entry.get_type(), WHITE), BOLD)

  if selected.line_type == LineType.CIRCUIT_HEADER and selected.circuit.status != 'BUILT':
    subwindow.addstr(2, 1, 'Building Circuit...', *attr)
  else:
    address = '<scrubbed>' if selected.entry.is_private() else selected.connection.remote_address
    subwindow.addstr(2, 1, 'address: %s:%s' % (address, selected.connection.remote_port), *attr)
    subwindow.addstr(2, 2, 'locale: %s' % (selected.locale if selected.locale and not selected.entry.is_private() else '??'), *attr)

    matches = nyx.tracker.get_consensus_tracker().get_relay_fingerprints(selected.connection.remote_address)

    if not matches:
      subwindow.addstr(2, 3, 'No consensus data found', *attr)
    elif len(matches) == 1 or selected.connection.remote_port in matches:
      controller = tor_controller()
      fingerprint = list(matches.values())[0] if len(matches) == 1 else matches[selected.connection.remote_port]
      router_status_entry = controller.get_network_status(fingerprint, None)

      subwindow.addstr(15, 2, 'fingerprint: %s' % fingerprint, *attr)

      if router_status_entry:
        dir_port_label = 'dirport: %s' % router_status_entry.dir_port if router_status_entry.dir_port else ''
        subwindow.addstr(2, 3, 'nickname: %-25s orport: %-10s %s' % (router_status_entry.nickname, router_status_entry.or_port, dir_port_label), *attr)
        subwindow.addstr(2, 4, 'published: %s' % router_status_entry.published.strftime("%H:%M %m/%d/%Y"), *attr)
        subwindow.addstr(2, 5, 'flags: %s' % ', '.join(router_status_entry.flags), *attr)

        server_descriptor = controller.get_server_descriptor(fingerprint, None)

        if server_descriptor:
          policy_label = server_descriptor.exit_policy.summary() if server_descriptor.exit_policy else 'unknown'
          subwindow.addstr(2, 6, 'exit policy: %s' % policy_label, *attr)
          subwindow.addstr(38, 4, 'os: %-14s version: %s' % (server_descriptor.operating_system, server_descriptor.tor_version), *attr)

          if server_descriptor.contact:
            subwindow.addstr(2, 7, 'contact: %s' % server_descriptor.contact, *attr)
    else:
      subwindow.addstr(2, 3, 'Multiple matches, possible fingerprints are:', *attr)

      for i, port in enumerate(sorted(matches.keys())):
        is_last_line, remaining_relays = i == 3, len(matches) - i

        if not is_last_line or remaining_relays == 1:
          subwindow.addstr(2, 4 + i, '%i. or port: %-5s fingerprint: %s' % (i + 1, port, matches[port]), *attr)
        else:
          subwindow.addstr(2, 4 + i, '... %i more' % remaining_relays, *attr)

        if is_last_line:
          break

  subwindow.box(0, 0, subwindow.width, DETAILS_HEIGHT + 2)
Ejemplo n.º 30
0
    def line(fingerprint, line_type):
      address, port, nickname = '0.0.0.0', 0, None
      consensus_tracker = nyx.tracker.get_consensus_tracker()

      if fingerprint is not None:
        address, port = consensus_tracker.get_relay_address(fingerprint, ('192.168.0.1', 0))
        nickname = consensus_tracker.get_relay_nickname(fingerprint)

      locale = tor_controller().get_info('ip-to-country/%s' % address, None)
      connection = nyx.tracker.Connection(datetime_to_unix(self._circuit.created), False, '127.0.0.1', 0, address, port, 'tcp', False)
      return Line(self, line_type, connection, self._circuit, fingerprint, nickname, locale)
Ejemplo n.º 31
0
  def get_lines(self):
    fingerprint, nickname, locale = None, None, None

    if self.get_type() in (Category.OUTBOUND, Category.CIRCUIT, Category.DIRECTORY, Category.EXIT):
      fingerprint = nyx.tracker.get_consensus_tracker().get_relay_fingerprints(self._connection.remote_address).get(self._connection.remote_port)

      if fingerprint:
        nickname = nyx.tracker.get_consensus_tracker().get_relay_nickname(fingerprint)
        locale = tor_controller().get_info('ip-to-country/%s' % self._connection.remote_address, None)

    return [Line(self, LineType.CONNECTION, self._connection, None, fingerprint, nickname, locale)]
Ejemplo n.º 32
0
  def _get_lines(self):
    fingerprint, nickname = None, None

    if self.get_type() in (Category.OUTBOUND, Category.CIRCUIT, Category.DIRECTORY, Category.EXIT):
      fingerprint = nyx.tracker.get_consensus_tracker().get_relay_fingerprints(self._connection.remote_address).get(self._connection.remote_port)

      if fingerprint:
        nickname = nyx.tracker.get_consensus_tracker().get_relay_nickname(fingerprint)

    locale = tor_controller().get_info('ip-to-country/%s' % self._connection.remote_address, None)
    return [Line(self, LineType.CONNECTION, self._connection, None, fingerprint, nickname, locale)]
Ejemplo n.º 33
0
    def line(fingerprint, line_type):
      address, port, nickname, locale = '0.0.0.0', 0, None, None
      consensus_tracker = nyx.tracker.get_consensus_tracker()

      if fingerprint is not None:
        address, port = consensus_tracker.get_relay_address(fingerprint, ('192.168.0.1', 0))
        nickname = consensus_tracker.get_relay_nickname(fingerprint)
        locale = tor_controller().get_info('ip-to-country/%s' % address, None)

      connection = nyx.tracker.Connection(datetime_to_unix(self._circuit.created), False, '127.0.0.1', 0, address, port, 'tcp', False)
      return Line(self, line_type, connection, self._circuit, fingerprint, nickname, locale)
Ejemplo n.º 34
0
    def _edit_selected_value():
      selected = self._scroller.selection(self._get_config_options())
      initial_value = selected.value() if selected.is_set() else ''
      new_value = nyx.controller.input_prompt('%s Value (esc to cancel): ' % selected.name, initial_value)

      if new_value != initial_value:
        try:
          if selected.value_type == 'Boolean':
            # if the value's a boolean then allow for 'true' and 'false' inputs

            if new_value.lower() == 'true':
              new_value = '1'
            elif new_value.lower() == 'false':
              new_value = '0'
          elif selected.value_type == 'LineList':
            new_value = new_value.split(',')  # set_conf accepts list inputs

          tor_controller().set_conf(selected.name, new_value)
          self.redraw()
        except Exception as exc:
          nyx.controller.show_message('%s (press any key)' % exc, HIGHLIGHT, max_wait = 30)
Ejemplo n.º 35
0
    def bandwidth_event(self, event):
        self.primary.update(event.read)
        self.secondary.update(event.written)

        self._primary_header_stats = [
            '%-14s' % ('%s/sec' % _size_label(self.primary.latest_value)),
            '- avg: %s/sec' % _size_label(self.primary.total /
                                          (time.time() - self.start_time)),
            ', total: %s' % _size_label(self.primary.total),
        ]

        self._secondary_header_stats = [
            '%-14s' % ('%s/sec' % _size_label(self.secondary.latest_value)),
            '- avg: %s/sec' % _size_label(self.secondary.total /
                                          (time.time() - self.start_time)),
            ', total: %s' % _size_label(self.secondary.total),
        ]

        controller = tor_controller()

        stats = []
        bw_rate = controller.get_effective_rate(None)
        bw_burst = controller.get_effective_rate(None, burst=True)

        if bw_rate and bw_burst:
            bw_rate_label = _size_label(bw_rate)
            bw_burst_label = _size_label(bw_burst)

            # if both are using rounded values then strip off the '.0' decimal

            if '.0' in bw_rate_label and '.0' in bw_burst_label:
                bw_rate_label = bw_rate_label.split('.', 1)[0]
                bw_burst_label = bw_burst_label.split('.', 1)[0]

            stats.append('limit: %s/s' % bw_rate_label)
            stats.append('burst: %s/s' % bw_burst_label)

        my_router_status_entry = controller.get_network_status(default=None)
        measured_bw = getattr(my_router_status_entry, 'bandwidth', None)

        if measured_bw:
            stats.append('measured: %s/s' % _size_label(measured_bw))
        else:
            my_server_descriptor = controller.get_server_descriptor(
                default=None)
            observed_bw = getattr(my_server_descriptor, 'observed_bandwidth',
                                  None)

            if observed_bw:
                stats.append('observed: %s/s' % _size_label(observed_bw))

        self._title_stats = stats
Ejemplo n.º 36
0
  def _update_accounting(self, event):
    if not CONFIG['show_accounting']:
      self._accounting_stats = None
    elif not self._accounting_stats or time.time() - self._accounting_stats.retrieved >= ACCOUNTING_RATE:
      old_accounting_stats = self._accounting_stats
      self._accounting_stats = tor_controller().get_accounting_stats(None)

      if not nyx_interface().is_paused():
        # if we either added or removed accounting info then redraw the whole
        # screen to account for resizing

        if bool(old_accounting_stats) != bool(self._accounting_stats):
          nyx_interface().redraw()
Ejemplo n.º 37
0
  def _update_accounting(self, event):
    if not CONFIG['features.graph.bw.accounting.show']:
      self._accounting_stats = None
    elif not self._accounting_stats or time.time() - self._accounting_stats.retrieved >= ACCOUNTING_RATE:
      nyx_controller = nyx.controller.get_controller()
      old_accounting_stats = self._accounting_stats
      self._accounting_stats = tor_controller().get_accounting_stats(None)

      if not nyx_controller.is_paused():
        # if we either added or removed accounting info then redraw the whole
        # screen to account for resizing

        if bool(old_accounting_stats) != bool(self._accounting_stats):
          nyx.controller.get_controller().redraw()
Ejemplo n.º 38
0
    def __init__(self):
        nyx.panel.Panel.__init__(self)

        self._is_input_mode = False
        self._x_offset = 0
        self._scroller = nyx.curses.Scroller()
        self._lines = []
        self._user_inputs = []  # previous user inputs

        controller = tor_controller()
        self._autocompleter = stem.interpreter.autocomplete.Autocompleter(
            controller)
        self._interpreter = stem.interpreter.commands.ControlInterpreter(
            controller)
Ejemplo n.º 39
0
def _draw_accounting_stats(subwindow, y, accounting):
  if tor_controller().is_alive():
    hibernate_color = CONFIG['attr.hibernate_color'].get(accounting.status, RED)

    x = subwindow.addstr(0, y, 'Accounting (', BOLD)
    x = subwindow.addstr(x, y, accounting.status, BOLD, hibernate_color)
    x = subwindow.addstr(x, y, ')', BOLD)

    subwindow.addstr(35, y, 'Time to reset: %s' % str_tools.short_time_label(accounting.time_until_reset))

    subwindow.addstr(2, y + 1, '%s / %s' % (_size_label(accounting.read_bytes), _size_label(accounting.read_limit)), PRIMARY_COLOR)
    subwindow.addstr(37, y + 1, '%s / %s' % (_size_label(accounting.written_bytes), _size_label(accounting.write_limit)), SECONDARY_COLOR)
  else:
    subwindow.addstr(0, y, 'Accounting:', BOLD)
    subwindow.addstr(12, y, 'Connection Closed...')
Ejemplo n.º 40
0
    def __init__(self):
        panel.Panel.__init__(self)

        self._scroller = nyx.curses.Scroller()
        self._show_line_numbers = True  # shows left aligned line numbers
        self._show_comments = True  # shows comments and extra whitespace
        self._last_content_height = 0

        self._torrc_location = None
        self._torrc_content = None
        self._torrc_load_error = None

        controller = tor_controller()
        controller.add_status_listener(self._reset_listener)
        self._reset_listener(controller, State.RESET, None)
Ejemplo n.º 41
0
Archivo: torrc.py Proyecto: patacca/nyx
  def __init__(self):
    panel.Panel.__init__(self, 'torrc')

    self._scroller = nyx.curses.Scroller()
    self._show_line_numbers = True  # shows left aligned line numbers
    self._show_comments = True  # shows comments and extra whitespace
    self._last_content_height = 0

    self._torrc_location = None
    self._torrc_content = None
    self._torrc_load_error = None

    controller = tor_controller()
    controller.add_status_listener(self.reset_listener)
    self.reset_listener(controller, State.RESET, None)
Ejemplo n.º 42
0
def _draw_accounting_stats(subwindow, y, accounting):
  if tor_controller().is_alive():
    hibernate_color = CONFIG['attr.hibernate_color'].get(accounting.status, RED)

    x = subwindow.addstr(0, y, 'Accounting (', BOLD)
    x = subwindow.addstr(x, y, accounting.status, BOLD, hibernate_color)
    x = subwindow.addstr(x, y, ')', BOLD)

    subwindow.addstr(35, y, 'Time to reset: %s' % str_tools.short_time_label(accounting.time_until_reset))

    subwindow.addstr(2, y + 1, '%s / %s' % (_size_label(accounting.read_bytes), _size_label(accounting.read_limit)), PRIMARY_COLOR)
    subwindow.addstr(37, y + 1, '%s / %s' % (_size_label(accounting.written_bytes), _size_label(accounting.write_limit)), SECONDARY_COLOR)
  else:
    subwindow.addstr(0, y, 'Accounting:', BOLD)
    subwindow.addstr(12, y, 'Connection Closed...')
Ejemplo n.º 43
0
  def bandwidth_event(self, event):
    self.primary.update(event.read)
    self.secondary.update(event.written)

    self._primary_header_stats = [
      '%-14s' % ('%s/sec' % _size_label(self.primary.latest_value)),
      '- avg: %s/sec' % _size_label(self.primary.total / (time.time() - self.start_time)),
      ', total: %s' % _size_label(self.primary.total),
    ]

    self._secondary_header_stats = [
      '%-14s' % ('%s/sec' % _size_label(self.secondary.latest_value)),
      '- avg: %s/sec' % _size_label(self.secondary.total / (time.time() - self.start_time)),
      ', total: %s' % _size_label(self.secondary.total),
    ]

    controller = tor_controller()

    stats = []
    bw_rate = controller.get_effective_rate(None)
    bw_burst = controller.get_effective_rate(None, burst = True)

    if bw_rate and bw_burst:
      bw_rate_label = _size_label(bw_rate)
      bw_burst_label = _size_label(bw_burst)

      # if both are using rounded values then strip off the '.0' decimal

      if '.0' in bw_rate_label and '.0' in bw_burst_label:
        bw_rate_label = bw_rate_label.split('.', 1)[0]
        bw_burst_label = bw_burst_label.split('.', 1)[0]

      stats.append('limit: %s/s' % bw_rate_label)
      stats.append('burst: %s/s' % bw_burst_label)

    my_router_status_entry = controller.get_network_status(default = None)
    measured_bw = getattr(my_router_status_entry, 'bandwidth', None)

    if measured_bw:
      stats.append('measured: %s/s' % _size_label(measured_bw))
    else:
      my_server_descriptor = controller.get_server_descriptor(default = None)
      observed_bw = getattr(my_server_descriptor, 'observed_bandwidth', None)

      if observed_bw:
        stats.append('observed: %s/s' % _size_label(observed_bw))

    self._title_stats = stats
Ejemplo n.º 44
0
  def is_private(self):
    if not CONFIG['features.connection.showIps']:
      return True

    if self.get_type() == Category.INBOUND:
      controller = tor_controller()

      if controller.is_user_traffic_allowed().inbound:
        return len(nyx.tracker.get_consensus_tracker().get_relay_fingerprints(self._connection.remote_address)) == 0
    elif self.get_type() == Category.EXIT:
      # DNS connections exiting us aren't private (since they're hitting our
      # resolvers). Everything else is.

      return not (self._connection.remote_port == 53 and self._connection.protocol == 'udp')

    return False  # for everything else this isn't a concern
Ejemplo n.º 45
0
    def my_router_status_entry(self):
        """
    Provides the router status entry of ourselves. Descriptors are published
    hourly, and results are cached for five minutes.

    :returns: :class:`~stem.descriptor.router_status_entry.RouterStatusEntryV3`
      for ourselves, **None** if it cannot be retrieved
    """

        if self._my_router_status_entry is None or (
                time.time() - self._my_router_status_entry_time) > 300:
            self._my_router_status_entry = tor_controller().get_network_status(
                default=None)
            self._my_router_status_entry_time = time.time()

        return self._my_router_status_entry
Ejemplo n.º 46
0
  def show_write_dialog(self):
    """
    Confirmation dialog for saving tor's configuration.
    """

    controller = tor_controller()
    torrc = controller.get_info('config-text', None)

    if nyx.popups.confirm_save_torrc(torrc):
      try:
        controller.save_conf()
        nyx.controller.show_message('Saved configuration to %s' % controller.get_info('config-file', '<unknown>'), HIGHLIGHT, max_wait = 2)
      except IOError as exc:
        nyx.controller.show_message('Unable to save configuration (%s)' % exc.strerror, HIGHLIGHT, max_wait = 2)

    self.redraw()
Ejemplo n.º 47
0
  def __init__(self):
    nyx.panel.Panel.__init__(self)

    self._contents = []
    self._scroller = nyx.curses.CursorScroller()
    self._sort_order = CONFIG['features.config.order']
    self._show_all = False  # show all options, or just the important ones

    cached_manual_path = os.path.join(DATA_DIR, 'manual')

    if os.path.exists(cached_manual_path):
      manual = stem.manual.Manual.from_cache(cached_manual_path)
    else:
      try:
        manual = stem.manual.Manual.from_man()

        try:
          manual.save(cached_manual_path)
        except IOError as exc:
          log.debug("Unable to cache manual information to '%s'. This is fine, but means starting Nyx takes a little longer than usual: " % (cached_manual_path, exc))
      except IOError as exc:
        log.debug("Unable to use 'man tor' to get information about config options (%s), using bundled information instead" % exc)
        manual = stem.manual.Manual.from_cache()

    try:
      for line in tor_controller().get_info('config/names').splitlines():
        # Lines of the form "<option> <type>[ <documentation>]". Documentation
        # was apparently only in old tor versions like 0.2.1.25.

        if ' ' not in line:
          continue

        line_comp = line.split()
        name, value_type = line_comp[0], line_comp[1]

        # skips private and virtual entries if not configured to show them

        if name.startswith('__') and not CONFIG['features.config.state.showPrivateOptions']:
          continue
        elif value_type == 'Virtual' and not CONFIG['features.config.state.showVirtualOptions']:
          continue

        self._contents.append(ConfigEntry(name, value_type, manual))

      self._contents = sorted(self._contents, key = lambda entry: [entry.sort_value(field) for field in self._sort_order])
    except stem.ControllerError as exc:
      log.warn('Unable to determine the configuration options tor supports: %s' % exc)
Ejemplo n.º 48
0
def missing_event_types():
  """
  Provides the event types the current tor connection supports but nyx
  doesn't. This provides an empty list if no event types are missing or the
  GETINFO query fails.

  :returns: **list** of missing event types
  """

  response = tor_controller().get_info('events/names', None)

  if response is None:
    return []  # GETINFO query failed

  tor_event_types = response.split(' ')
  recognized_types = TOR_EVENT_TYPES.values()
  return list(filter(lambda x: x not in recognized_types, tor_event_types))
Ejemplo n.º 49
0
  def send_newnym(self):
    """
    Requests a new identity and provides a visual queue.
    """

    controller = tor_controller()

    if not controller.is_newnym_available():
      return

    controller.signal(stem.Signal.NEWNYM)

    # If we're wide then the newnym label in this panel will give an
    # indication that the signal was sent. Otherwise use a msg.

    if not self.is_wide():
      self.show_message('Requesting a new identity', HIGHLIGHT, max_wait = 1)
Ejemplo n.º 50
0
    def _draw(self, subwindow):
        controller = tor_controller()
        interface = nyx_interface()
        entries = self._entries

        lines = list(
            itertools.chain.from_iterable(
                [entry.get_lines() for entry in entries]))
        is_showing_details = self._show_details and lines
        details_offset = DETAILS_HEIGHT + 1 if is_showing_details else 0
        selected, scroll = self._scroller.selection(
            lines, subwindow.height - details_offset - 1)

        if interface.is_paused():
            current_time = self._pause_time
        elif not controller.is_alive():
            current_time = controller.connection_time()
        else:
            current_time = time.time()

        is_scrollbar_visible = len(
            lines) > subwindow.height - details_offset - 1
        scroll_offset = 2 if is_scrollbar_visible else 0

        _draw_title(subwindow, entries, self._show_details)

        if is_showing_details:
            _draw_details(subwindow, selected)

            # draw a 'T' pipe if connecting with the scrollbar

            if is_scrollbar_visible:
                subwindow._addch(1, DETAILS_HEIGHT + 1, curses.ACS_TTEE)

        if is_scrollbar_visible:
            subwindow.scrollbar(1 + details_offset, scroll, len(lines))

        for line_number in range(scroll, len(lines)):
            y = line_number + details_offset + 1 - scroll
            _draw_line(subwindow, scroll_offset, y, lines[line_number],
                       lines[line_number] == selected,
                       subwindow.width - scroll_offset, current_time)

            if y >= subwindow.height:
                break
Ejemplo n.º 51
0
  def get_relay_nickname(self, fingerprint):
    """
    Provides the nickname associated with the given relay.

    :param str fingerprint: relay to look up

    :returns: **str** with the nickname ("Unnamed" if unset), and **None** if
      no such relay exists
    """

    controller = tor_controller()

    if not fingerprint:
      return None
    elif fingerprint == controller.get_info('fingerprint', None):
      return controller.get_conf('Nickname', 'Unnamed')
    else:
      return self._nickname_cache.get(fingerprint)
Ejemplo n.º 52
0
    def get_relay_nickname(self, fingerprint):
        """
    Provides the nickname associated with the given relay.

    :param str fingerprint: relay to look up

    :returns: **str** with the nickname ("Unnamed" if unset), and **None** if
      no such relay exists
    """

        controller = tor_controller()

        if not fingerprint:
            return None
        elif fingerprint == controller.get_info('fingerprint', None):
            return controller.get_conf('Nickname', 'Unnamed')
        else:
            return nyx.cache().relay_nickname(fingerprint)
Ejemplo n.º 53
0
    def __init__(self, rate):
        super(Daemon, self).__init__()
        self.setDaemon(True)

        self._process_lock = threading.RLock()
        self._process_pid = None
        self._process_name = None

        self._rate = rate
        self._last_ran = -1  # time when we last ran
        self._run_counter = 0  # counter for the number of successful runs

        self._is_paused = False
        self._halt = False  # terminates thread if true

        controller = tor_controller()
        controller.add_status_listener(self._tor_status_listener)
        self._tor_status_listener(controller, stem.control.State.INIT, None)
Ejemplo n.º 54
0
  def value(self):
    """
    Provides the value of this configuration option.

    :returns: **str** representation of the current config value
    """

    values = tor_controller().get_conf(self.name, [], True)

    if not values:
      return '<none>'
    elif self.value_type == 'Boolean' and values[0] in ('0', '1'):
      return 'False' if values[0] == '0' else 'True'
    elif self.value_type == 'DataSize' and values[0].isdigit():
      return str_tools.size_label(int(values[0]))
    elif self.value_type == 'TimeInterval' and values[0].isdigit():
      return str_tools.time_label(int(values[0]), is_long = True)
    else:
      return ', '.join(values)
Ejemplo n.º 55
0
  def __init__(self, rate):
    super(Daemon, self).__init__()
    self.setDaemon(True)

    self._process_lock = threading.RLock()
    self._process_pid = None
    self._process_name = None

    self._rate = rate
    self._last_ran = -1  # time when we last ran
    self._run_counter = 0  # counter for the number of successful runs

    self._is_paused = False
    self._pause_condition = threading.Condition()
    self._halt = False  # terminates thread if true

    controller = tor_controller()
    controller.add_status_listener(self._tor_status_listener)
    self._tor_status_listener(controller, stem.control.State.INIT, None)
Ejemplo n.º 56
0
    def send_newnym(self):
        """
    Requests a new identity and provides a visual queue.
    """

        controller = tor_controller()

        if not controller.is_newnym_available():
            return

        controller.signal(stem.Signal.NEWNYM)

        # If we're wide then the newnym label in this panel will give an
        # indication that the signal was sent. Otherwise use a msg.

        if not self.is_wide():
            self.show_message('Requesting a new identity',
                              HIGHLIGHT,
                              max_wait=1)
Ejemplo n.º 57
0
  def get_relay_fingerprints(self, address):
    """
    Provides the relays running at a given location.

    :param str address: address to be checked

    :returns: **dict** of ORPorts to their fingerprint
    """

    controller = tor_controller()

    if address == controller.get_info('address', None):
      fingerprint = controller.get_info('fingerprint', None)
      ports = controller.get_ports(stem.control.Listener.OR, None)

      if fingerprint and ports:
        return dict([(port, fingerprint) for port in ports])

    return dict([(port, fp) for (port, fp) in self._fingerprint_cache.get(address, [])])
Ejemplo n.º 58
0
  def get_relay_address(self, fingerprint, default):
    """
    Provides the (address, port) tuple where a relay is running.

    :param str fingerprint: fingerprint to be checked

    :returns: **tuple** with a **str** address and **int** port
    """

    controller = tor_controller()

    if fingerprint == controller.get_info('fingerprint', None):
      my_address = controller.get_info('address', None)
      my_or_ports = controller.get_ports(stem.control.Listener.OR, [])

      if my_address and len(my_or_ports) == 1:
        return (my_address, my_or_ports[0])

    return self._address_cache.get(fingerprint, default)