import shutil import getpass import platform import functools import curses import cli.popups import cli.controller from util import connections, enum, log, sysTools, torConfig, torTools, uiTools # template used to generate the torrc TORRC_TEMPLATE = "resources/torrcTemplate.txt" # basic configuration types we can run as RelayType = enum.Enum("RESUME", "RELAY", "EXIT", "BRIDGE", "CLIENT") # all options that can be configured Options = enum.Enum("DIVIDER", "CONTROL", "NICKNAME", "CONTACT", "NOTIFY", "BANDWIDTH", "LIMIT", "CLIENT", "LOWPORTS", "PORTFORWARD", "SYSTEM", "STARTUP", "RSHUTDOWN", "CSHUTDOWN", "NOTICE", "POLICY", "WEBSITES", "EMAIL", "IM", "MISC", "PLAINTEXT", "DISTRIBUTE", "BRIDGED", "BRIDGE1", "BRIDGE2", "BRIDGE3", "REUSE") RelayOptions = { RelayType.RELAY: (Options.NICKNAME, Options.CONTACT, Options.NOTIFY, Options.BANDWIDTH, Options.LIMIT, Options.CLIENT, Options.LOWPORTS, Options.PORTFORWARD, Options.STARTUP, Options.RSHUTDOWN, Options.SYSTEM), RelayType.EXIT: (Options.NICKNAME, Options.CONTACT, Options.NOTIFY, Options.BANDWIDTH,
""" Interface for entries in the connection panel. These consist of two parts: the entry itself (ie, Tor connection, client circuit, etc) and the lines it consists of in the listing. """ from util import enum # attributes we can list entries by ListingType = enum.Enum(("IP_ADDRESS", "IP Address"), "HOSTNAME", "FINGERPRINT", "NICKNAME") SortAttr = enum.Enum("CATEGORY", "UPTIME", "LISTING", "IP_ADDRESS", "PORT", "HOSTNAME", "FINGERPRINT", "NICKNAME", "COUNTRY") SORT_COLORS = { SortAttr.CATEGORY: "red", SortAttr.UPTIME: "yellow", SortAttr.LISTING: "green", SortAttr.IP_ADDRESS: "blue", SortAttr.PORT: "blue", SortAttr.HOSTNAME: "magenta", SortAttr.FINGERPRINT: "cyan", SortAttr.NICKNAME: "cyan", SortAttr.COUNTRY: "blue" } # maximum number of ports a system can have PORT_COUNT = 65536
which was written by Jay Loden, Dave Daeschler, Giampaolo Rodola' and is under the BSD license. """ import os import sys import time import socket import base64 from util import enum, log # cached system values SYS_START_TIME, SYS_PHYSICAL_MEMORY = None, None CLOCK_TICKS = os.sysconf(os.sysconf_names["SC_CLK_TCK"]) Stat = enum.Enum("COMMAND", "CPU_UTIME", "CPU_STIME", "START_TIME") CONFIG = {"queries.useProc": True, "log.procCallMade": log.DEBUG} def loadConfig(config): config.update(CONFIG) def isProcAvailable(): """ Provides true if configured to use proc resolution and it's available on the platform, false otherwise. """ return CONFIG["queries.useProc"] and os.uname()[0] == "Linux"
from util import connections, enum, hostnames, torConfig, torTools, uiTools COLOR_PROMPT = True # provides a colored interpretor prompt INFO_HOSTNAMES = False # hostname lookups in /info results # initial location /write will save to when no path is specified DEFAULT_WRITE_PATH = "/tmp/torInterpretor_output" INIT_MSG = """Arm %s Control Interpretor Enter \"/help\" for usage information and \"/quit\" to stop. """ % version.VERSION TERM_COLORS = ("BLACK", "RED", "GREEN", "YELLOW", "BLUE", "MAGENTA", "CYAN", "WHITE") Color = enum.Enum(*TERM_COLORS) BgColor = enum.Enum(*["BG_" + color for color in TERM_COLORS]) Attr = enum.Enum("BOLD", "UNDERLINE", "HILIGHT") FG_ENCODING = dict([(Color.values()[i], str(30 + i)) for i in range(8)]) BG_ENCODING = dict([(BgColor.values()[i], str(40 + i)) for i in range(8)]) ATTR_ENCODING = {Attr.BOLD: "1", Attr.UNDERLINE: "4", Attr.HILIGHT: "7"} PROMPT = (">>> ", (Attr.BOLD, Color.GREEN)) INPUT_FORMAT = (Color.CYAN, ) INPUT_INTERPRETOR_FORMAT = (Attr.BOLD, Color.MAGENTA) INPUT_CMD_FORMAT = (Attr.BOLD, Color.GREEN) INPUT_ARG_FORMAT = (Attr.BOLD, Color.CYAN) OUTPUT_FORMAT = (Color.BLUE, ) USAGE_FORMAT = (Color.CYAN, ) HELP_FORMAT = (Color.MAGENTA, )
"features.panels.show.config": True, "features.panels.show.torrc": True, "features.panels.show.interpretor": True, "features.redrawRate": 5, "features.refreshRate": 5, "features.confirmQuit": True, "features.graph.type": 1, "features.graph.bw.prepopulate": True, "wizard.default": {}, "log.startTime": log.INFO, "log.torEventTypeUnrecognized": log.NOTICE, "log.configEntryUndefined": log.NOTICE, "log.unknownTorPid": log.WARN } GraphStat = enum.Enum("BANDWIDTH", "CONNECTIONS", "SYSTEM_RESOURCES") # maps 'features.graph.type' config values to the initial types GRAPH_INIT_STATS = { 1: GraphStat.BANDWIDTH, 2: GraphStat.CONNECTIONS, 3: GraphStat.SYSTEM_RESOURCES } def getController(): """ Provides the arm controller instance. """ return ARM_CONTROLLER
import math import curses import threading import popups from util import conf, enum, panel, torConfig, torTools, uiTools DEFAULT_CONFIG = { "features.config.file.showScrollbars": True, "features.config.file.maxLinesPerEntry": 8 } # TODO: The armrc use case is incomplete. There should be equivilant reloading # and validation capabilities to the torrc. Config = enum.Enum("TORRC", "ARMRC") # configuration file types that can be displayed class TorrcPanel(panel.Panel): """ Renders the current torrc or armrc with syntax highlighting in a scrollable area. """ def __init__(self, stdscr, configType, config=None): panel.Panel.__init__(self, stdscr, "torrc", 0) self._config = dict(DEFAULT_CONFIG) if config: config.update(self._config, {"features.config.file.maxLinesPerEntry": 1})
import curses from util import connections, enum, torTools, uiTools from cli.connections import entries # Connection Categories: # Inbound Relay connection, coming to us. # Outbound Relay connection, leaving us. # Exit Outbound relay connection leaving the Tor network. # Hidden Connections to a hidden service we're providing. # Socks Socks connections for applications using Tor. # Circuit Circuits our tor client has created. # Directory Fetching tor consensus information. # Control Tor controller (arm, vidalia, etc). Category = enum.Enum("INBOUND", "OUTBOUND", "EXIT", "HIDDEN", "SOCKS", "CIRCUIT", "DIRECTORY", "CONTROL") CATEGORY_COLOR = { Category.INBOUND: "green", Category.OUTBOUND: "blue", Category.EXIT: "red", Category.HIDDEN: "magenta", Category.SOCKS: "yellow", Category.CIRCUIT: "cyan", Category.DIRECTORY: "magenta", Category.CONTROL: "red" } # static data for listing format # <src> --> <dst> <etc><padding> LABEL_FORMAT = "%s --> %s %s%s" LABEL_MIN_PADDING = 2 # min space between listing label and following data
from util import enum, panel, torTools, uiTools # time intervals at which graphs can be updated UPDATE_INTERVALS = [("each second", 1), ("5 seconds", 5), ("30 seconds", 30), ("minutely", 60), ("15 minute", 900), ("30 minute", 1800), ("hourly", 3600), ("daily", 86400)] DEFAULT_CONTENT_HEIGHT = 4 # space needed for labeling above and below the graph DEFAULT_COLOR_PRIMARY, DEFAULT_COLOR_SECONDARY = "green", "cyan" MIN_GRAPH_HEIGHT = 1 # enums for graph bounds: # Bounds.GLOBAL_MAX - global maximum (highest value ever seen) # Bounds.LOCAL_MAX - local maximum (highest value currently on the graph) # Bounds.TIGHT - local maximum and minimum Bounds = enum.Enum("GLOBAL_MAX", "LOCAL_MAX", "TIGHT") WIDE_LABELING_GRAPH_COL = 50 # minimum graph columns to use wide spacing for x-axis labels # used for setting defaults when initializing GraphStats and GraphPanel instances CONFIG = {"features.graph.height": 7, "features.graph.interval": 0, "features.graph.bound": 1, "features.graph.maxWidth": 150, "features.graph.showIntermediateBounds": True} def loadConfig(config): config.update(CONFIG, { "features.graph.height": MIN_GRAPH_HEIGHT, "features.graph.maxWidth": 1, "features.graph.interval": (0, len(UPDATE_INTERVALS) - 1),
""" Provides a dialog with client locale or exiting port counts. """ import curses import operator import cli.controller import cli.popups from util import connections, enum, log, uiTools CountType = enum.Enum("CLIENT_LOCALE", "EXIT_PORT") EXIT_USAGE_WIDTH = 15 def showCountDialog(countType, counts): """ Provides a dialog with bar graphs and percentages for the given set of counts. Pressing any key closes the dialog. Arguments: countType - type of counts being presented counts - mapping of labels to counts """ isNoStats = not counts noStatsMsg = "Usage stats aren't available yet, press any key..." if isNoStats: popup, width, height = cli.popups.init(3, len(noStatsMsg) + 4)
from cli.connections import countPopup, descriptorPopup, entries, connEntry, circEntry from util import connections, enum, panel, torTools, uiTools DEFAULT_CONFIG = { "features.connection.resolveApps": True, "features.connection.listingType": 0, "features.connection.refreshRate": 5, "features.connection.showIps": True } # height of the detail panel content, not counting top and bottom border DETAILS_HEIGHT = 7 # listing types Listing = enum.Enum(("IP_ADDRESS", "IP Address"), "HOSTNAME", "FINGERPRINT", "NICKNAME") DEFAULT_SORT_ORDER = (entries.SortAttr.CATEGORY, entries.SortAttr.LISTING, entries.SortAttr.UPTIME) class ConnectionPanel(panel.Panel, threading.Thread): """ Listing of connections tor is making, with information correlated against the current consensus and other data sources. """ def __init__(self, stdscr, config=None): panel.Panel.__init__(self, stdscr, "connections", 0) threading.Thread.__init__(self) self.setDaemon(True)
keeping a record of them. A limited space is provided for old events, keeping and trimming them on a per-runlevel basis (ie, too many DEBUG events will only result in entries from that runlevel being dropped). All functions are thread safe. """ import os import time from sys import maxint from threading import RLock from util import enum # Logging runlevels. These are *very* commonly used so including shorter # aliases (so they can be referenced as log.DEBUG, log.WARN, etc). Runlevel = enum.Enum(("DEBUG", "DEBUG"), ("INFO", "INFO"), ("NOTICE", "NOTICE"), ("WARN", "WARN"), ("ERR", "ERR")) DEBUG, INFO, NOTICE, WARN, ERR = Runlevel.values() # provides thread safety for logging operations LOG_LOCK = RLock() # chronologically ordered records of events for each runlevel, stored as tuples # consisting of: (time, message) _backlog = dict([(level, []) for level in Runlevel.values()]) # mapping of runlevels to the listeners interested in receiving events from it _listeners = dict([(level, []) for level in Runlevel.values()]) CONFIG = {"cache.armLog.size": 1000, "cache.armLog.trimSize": 200} DUMP_FILE = None
# value tuples for label conversions (bits / bytes / seconds, short label, long label) SIZE_UNITS_BITS = [(140737488355328.0, " Pb", " Petabit"), (137438953472.0, " Tb", " Terabit"), (134217728.0, " Gb", " Gigabit"), (131072.0, " Mb", " Megabit"), (128.0, " Kb", " Kilobit"), (0.125, " b", " Bit")] SIZE_UNITS_BYTES = [(1125899906842624.0, " PB", " Petabyte"), (1099511627776.0, " TB", " Terabyte"), (1073741824.0, " GB", " Gigabyte"), (1048576.0, " MB", " Megabyte"), (1024.0, " KB", " Kilobyte"), (1.0, " B", " Byte")] TIME_UNITS = [(86400.0, "d", " day"), (3600.0, "h", " hour"), (60.0, "m", " minute"), (1.0, "s", " second")] Ending = enum.Enum("ELLIPSE", "HYPHEN") SCROLL_KEYS = (curses.KEY_UP, curses.KEY_DOWN, curses.KEY_PPAGE, curses.KEY_NPAGE, curses.KEY_HOME, curses.KEY_END) CONFIG = { "features.colorInterface": True, "features.printUnicode": True, "log.cursesColorSupport": log.INFO, "log.configEntryTypeError": log.NOTICE } # Flag indicating if unicode is supported by curses. If None then this has yet # to be determined. IS_UNICODE_SUPPORTED = None def loadConfig(config):
from util import conf, enum, panel, sysTools, torConfig, torTools, uiTools DEFAULT_CONFIG = { "features.config.selectionDetails.height": 6, "features.config.prepopulateEditValues": True, "features.config.state.showPrivateOptions": False, "features.config.state.showVirtualOptions": False, "features.config.state.colWidth.option": 25, "features.config.state.colWidth.value": 15 } # TODO: The arm use cases are incomplete since they currently can't be # modified, have their descriptions fetched, or even get a complete listing # of what's available. State = enum.Enum("TOR", "ARM") # state to be presented # mappings of option categories to the color for their entries CATEGORY_COLOR = { torConfig.Category.GENERAL: "green", torConfig.Category.CLIENT: "blue", torConfig.Category.RELAY: "yellow", torConfig.Category.DIRECTORY: "magenta", torConfig.Category.AUTHORITY: "red", torConfig.Category.HIDDEN_SERVICE: "cyan", torConfig.Category.TESTING: "white", torConfig.Category.UNKNOWN: "white" } # attributes of a ConfigEntry Field = enum.Enum("CATEGORY", "OPTION", "VALUE", "TYPE", "ARG_USAGE",
"torrc.label.size.mb": [], "torrc.label.size.gb": [], "torrc.label.size.tb": [], "torrc.label.time.sec": [], "torrc.label.time.min": [], "torrc.label.time.hour": [], "torrc.label.time.day": [], "torrc.label.time.week": [], "log.torrc.readFailed": log.WARN, "log.configDescriptions.unrecognizedCategory": log.NOTICE, "log.torrc.validation.unnecessaryTorrcEntries": log.NOTICE, "log.torrc.validation.torStateDiffers": log.WARN } # enums and values for numeric torrc entries ValueType = enum.Enum("UNRECOGNIZED", "SIZE", "TIME") SIZE_MULT = { "b": 1, "kb": 1024, "mb": 1048576, "gb": 1073741824, "tb": 1099511627776 } TIME_MULT = {"sec": 1, "min": 60, "hour": 3600, "day": 86400, "week": 604800} # enums for issues found during torrc validation: # DUPLICATE - entry is ignored due to being a duplicate # MISMATCH - the value doesn't match tor's current state # MISSING - value differs from its default but is missing from the torrc # IS_DEFAULT - the configuration option matches tor's default ValidationError = enum.Enum("DUPLICATE", "MISMATCH", "MISSING", "IS_DEFAULT")