[tor-commits] r24526: {arm} Identifying connections we're providing a hidden service on (in arm/trunk/src: interface/connections util)
Damian Johnson
atagar1 at gmail.com
Fri Apr 1 16:18:16 UTC 2011
Author: atagar
Date: 2011-04-01 16:18:15 +0000 (Fri, 01 Apr 2011)
New Revision: 24526
Modified:
arm/trunk/src/interface/connections/connEntry.py
arm/trunk/src/interface/connections/connPanel.py
arm/trunk/src/util/connections.py
arm/trunk/src/util/enum.py
arm/trunk/src/util/torTools.py
Log:
Identifying connections we're providing a hidden service on and application it's attached to. This was tested by running a local HS via thttpd and using tor2web to download files from it.
Modified: arm/trunk/src/interface/connections/connEntry.py
===================================================================
--- arm/trunk/src/interface/connections/connEntry.py 2011-04-01 04:46:33 UTC (rev 24525)
+++ arm/trunk/src/interface/connections/connEntry.py 2011-04-01 16:18:15 UTC (rev 24526)
@@ -18,11 +18,11 @@
# Directory Fetching tor consensus information.
# Control Tor controller (arm, vidalia, etc).
-Category = enum.Enum("INBOUND", "OUTBOUND", "EXIT", "CIRCUIT", "DIRECTORY", "SOCKS", "CONTROL")
+Category = enum.Enum("INBOUND", "OUTBOUND", "EXIT", "CIRCUIT", "DIRECTORY", "SOCKS", "HIDDEN", "CONTROL")
CATEGORY_COLOR = {Category.INBOUND: "green", Category.OUTBOUND: "blue",
Category.EXIT: "red", Category.CIRCUIT: "cyan",
- Category.SOCKS: "yellow", Category.DIRECTORY: "magenta",
- Category.CONTROL: "red"}
+ Category.DIRECTORY: "magenta", Category.SOCKS: "yellow",
+ Category.HIDDEN: "magenta", Category.CONTROL: "red"}
# static data for listing format
# <src> --> <dst> <etc><padding>
@@ -199,7 +199,7 @@
self._possibleClient = True
self._possibleDirectory = True
- # attributes for SOCKS and CONTROL connections
+ # attributes for SOCKS, HIDDEN, and CONTROL connections
self.appName = None
self.appPid = None
self.isAppResolving = False
@@ -209,6 +209,7 @@
myDirPort = conn.getOption("DirPort")
mySocksPort = conn.getOption("SocksPort", "9050")
myCtlPort = conn.getOption("ControlPort")
+ myHiddenServicePorts = conn.getHiddenServicePorts()
# the ORListenAddress can overwrite the ORPort
listenAddr = conn.getOption("ORListenAddress")
@@ -220,6 +221,8 @@
self.local.isORPort = True
elif lPort == mySocksPort:
self.baseType = Category.SOCKS
+ elif fPort in myHiddenServicePorts:
+ self.baseType = Category.HIDDEN
elif lPort == myCtlPort:
self.baseType = Category.CONTROL
else:
@@ -288,7 +291,7 @@
True if our display uses application information that hasn't yet been resolved.
"""
- return self.appName == None and self.getType() in (Category.SOCKS, Category.CONTROL)
+ return self.appName == None and self.getType() in (Category.SOCKS, Category.HIDDEN, Category.CONTROL)
def _getListingEntry(self, width, currentTime, listingType):
entryType = self.getType()
@@ -428,7 +431,7 @@
"""
# for applications show the command/pid
- if self.getType() in (Category.SOCKS, Category.CONTROL):
+ if self.getType() in (Category.SOCKS, Category.HIDDEN, Category.CONTROL):
displayLabel = ""
if self.appName:
@@ -538,13 +541,23 @@
# the source and destination addresses are both private, but that might
# not be perfectly reliable either.
- isExpansionType = not myType in (Category.SOCKS, Category.CONTROL)
+ isExpansionType = not myType in (Category.SOCKS, Category.HIDDEN, Category.CONTROL)
if isExpansionType: srcAddress = myExternalIpAddr + localPort
else: srcAddress = self.local.getIpAddr() + localPort
- src = "%-21s" % srcAddress # ip:port = max of 21 characters
- dst = "%-26s" % dstAddress # ip:port (xx) = max of 26 characters
+ if myType in (Category.SOCKS, Category.CONTROL):
+ # These categories are reordered later so the it's dst -> src rather
+ # than src -> dst. They are local connections so the dst lacks locale
+ # information, so swapping their respective widths to match column
+ # alignments.
+
+ src = "%-26s" % srcAddress
+ dst = "%-21s" % dstAddress
+ else:
+ src = "%-21s" % srcAddress # ip:port = max of 21 characters
+ dst = "%-26s" % dstAddress # ip:port (xx) = max of 26 characters
+
usedSpace += len(src) + len(dst) # base data requires 47 characters
# Showing the fingerprint (which has the width of 42) has priority over
Modified: arm/trunk/src/interface/connections/connPanel.py
===================================================================
--- arm/trunk/src/interface/connections/connPanel.py 2011-04-01 04:46:33 UTC (rev 24525)
+++ arm/trunk/src/interface/connections/connPanel.py 2011-04-01 16:18:15 UTC (rev 24526)
@@ -64,14 +64,14 @@
# it changes.
self._lastResourceFetch = -1
- # resolver for the command/pid associated with SOCKS and CONTROL connections
+ # resolver for the command/pid associated with SOCKS, HIDDEN, and CONTROL connections
self._appResolver = connections.AppResolver("arm")
# rate limits appResolver queries to once per update
self.appResolveSinceUpdate = False
self._update() # populates initial entries
- self._resolveApps(False) # resolves initial SOCKS and CONTROL applications
+ self._resolveApps(False) # resolves initial applications
# mark the initially exitsing connection uptimes as being estimates
for entry in self._entries:
@@ -203,7 +203,7 @@
for lineNum in range(scrollLoc, len(self._entryLines)):
entryLine = self._entryLines[lineNum]
- # if this is an unresolved SOCKS or CONTROL entry then queue up
+ # if this is an unresolved SOCKS, HIDDEN, or CONTROL entry then queue up
# resolution for the applicaitions they belong to
if isinstance(entryLine, connEntry.ConnectionLine) and entryLine.isUnresolvedApp():
self._resolveApps()
@@ -325,8 +325,8 @@
def _resolveApps(self, flagQuery = True):
"""
- Triggers an asynchronous query for all unresolved SOCKS and CONTROL
- entries.
+ Triggers an asynchronous query for all unresolved SOCKS, HIDDEN, and
+ CONTROL entries.
Arguments:
flagQuery - sets a flag to prevent further call from being respected
@@ -334,42 +334,46 @@
"""
if self.appResolveSinceUpdate or not self._config["features.connection.resolveApps"]: return
+ unresolvedLines = [l for l in self._entryLines if isinstance(l, connEntry.ConnectionLine) and l.isUnresolvedApp()]
- # fetch the unresolved SOCKS and CONTROL lines
- unresolvedLines = []
+ # get the ports used for unresolved applications
+ appPorts = []
- for line in self._entryLines:
- if isinstance(line, connEntry.ConnectionLine) and line.isUnresolvedApp():
- unresolvedLines.append(line)
+ for line in unresolvedLines:
+ appConn = line.local if line.getType() == connEntry.Category.HIDDEN else line.foreign
+ appPorts.append(appConn.getPort())
# Queue up resolution for the unresolved ports (skips if it's still working
# on the last query).
- if not self._appResolver.isResolving:
- self._appResolver.resolve([line.foreign.getPort() for line in unresolvedLines])
+ if appPorts and not self._appResolver.isResolving:
+ self._appResolver.resolve(appPorts)
+ # Fetches results. If the query finishes quickly then this is what we just
+ # asked for, otherwise these belong to an earlier resolution.
+ #
# The application resolver might have given up querying (for instance, if
# the lsof lookups aren't working on this platform or lacks permissions).
# The isAppResolving flag lets the unresolved entries indicate if there's
# a lookup in progress for them or not.
- for line in unresolvedLines:
- line.isAppResolving = self._appResolver.isResolving
-
- # Fetches results. If the query finishes quickly then this is what we just
- # asked for, otherwise these belong to the last resolution.
appResults = self._appResolver.getResults(0.2)
for line in unresolvedLines:
- linePort = line.foreign.getPort()
+ isLocal = line.getType() == connEntry.Category.HIDDEN
+ linePort = line.local.getPort() if isLocal else line.foreign.getPort()
if linePort in appResults:
# sets application attributes if there's a result with this as the
# inbound port
for inboundPort, outboundPort, cmd, pid in appResults[linePort]:
- if linePort == inboundPort:
+ appPort = outboundPort if isLocal else inboundPort
+
+ if linePort == appPort:
line.appName = cmd
line.appPid = pid
line.isAppResolving = False
+ else:
+ line.isAppResolving = self._appResolver.isResolving
if flagQuery:
self.appResolveSinceUpdate = True
Modified: arm/trunk/src/util/connections.py
===================================================================
--- arm/trunk/src/util/connections.py 2011-04-01 04:46:33 UTC (rev 24525)
+++ arm/trunk/src/util/connections.py 2011-04-01 16:18:15 UTC (rev 24526)
@@ -659,7 +659,7 @@
else: lsofArgs.append("-i tcp:%s" % port)
if lsofArgs:
- lsofResults = sysTools.call("lsof -n " + " ".join(lsofArgs))
+ lsofResults = sysTools.call("lsof -nP " + " ".join(lsofArgs))
else: lsofResults = None
if not lsofResults and self.failureCount != -1:
Modified: arm/trunk/src/util/enum.py
===================================================================
--- arm/trunk/src/util/enum.py 2011-04-01 04:46:33 UTC (rev 24525)
+++ arm/trunk/src/util/enum.py 2011-04-01 16:18:15 UTC (rev 24526)
@@ -32,7 +32,8 @@
words = []
for entry in label.split("_"):
- if len(entry) == 1: words.append(entry.upper())
+ if len(entry) == 0: words.append("")
+ elif len(entry) == 1: words.append(entry.upper())
else: words.append(entry[0].upper() + entry[1:].lower())
return " ".join(words)
Modified: arm/trunk/src/util/torTools.py
===================================================================
--- arm/trunk/src/util/torTools.py 2011-04-01 04:46:33 UTC (rev 24525)
+++ arm/trunk/src/util/torTools.py 2011-04-01 16:18:15 UTC (rev 24526)
@@ -55,7 +55,7 @@
"config/names", "info/names", "features/names", "events/names",
"nsEntry", "descEntry", "address", "bwRate", "bwBurst",
"bwObserved", "bwMeasured", "flags", "parsedVersion", "pid",
- "pathPrefix", "startTime", "authorities", "circuits")
+ "pathPrefix", "startTime", "authorities", "circuits", "hsPorts")
# Tor has a couple messages (in or/router.c) for when our ip address changes:
# "Our IP Address has changed from <previous> to <current>; rebuilding
@@ -649,6 +649,16 @@
return self._getRelayAttr("circuits", default)
+ def getHiddenServicePorts(self, default = []):
+ """
+ Provides the target ports hidden services are configured to use.
+
+ Arguments:
+ default - value provided back if unable to query the hidden service ports
+ """
+
+ return self._getRelayAttr("hsPorts", default)
+
def getMyNetworkStatus(self, default = None):
"""
Provides the network status entry for this relay if available. This is
@@ -1691,6 +1701,31 @@
path = tuple([hopEntry[1:41] for hopEntry in lineComp[2].split(",")])
result.append((int(lineComp[0]), lineComp[1], lineComp[3][8:], path))
+ elif key == "hsPorts":
+ result = []
+ hsOptions = self.getOptionMap("HiddenServiceOptions")
+
+ if hsOptions and "HiddenServicePort" in hsOptions:
+ for hsEntry in hsOptions["HiddenServicePort"]:
+ # hidden service port entries are of the form:
+ # VIRTPORT [TARGET]
+ # with the TARGET being an IP, port, or IP:Port. If the target port
+ # isn't defined then uses the VIRTPORT.
+
+ hsPort = None
+
+ if " " in hsEntry:
+ # parses the target, checking if it's a port or IP:Port combination
+ hsTarget = hsEntry.split(" ")[1]
+
+ if ":" in hsTarget:
+ hsPort = hsTarget.split(":")[1] # target is the IP:Port
+ elif hsTarget.isdigit():
+ hsPort = hsTarget # target is just the port
+ else: hsPort = hsEntry # just has the virtual port
+
+ if hsPort.isdigit():
+ result.append(hsPort)
# cache value
if result != None: self._cachedParam[key] = result
More information about the tor-commits
mailing list