tor-commits
Threads by month
- ----- 2025 -----
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
January 2013
- 19 participants
- 1125 discussions
commit a0e5706c6bff400ca0fe28d705a5160315b4e52f
Author: David Fifield <david(a)bamsoftware.com>
Date: Sat Dec 29 05:42:44 2012 -0800
Fix a doc reference.
---
facilitator/README | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/facilitator/README b/facilitator/README
index d3c5593..8c0ac29 100644
--- a/facilitator/README
+++ b/facilitator/README
@@ -1,3 +1,3 @@
This directory contains files needed to run a flash proxy facilitator.
Normal users don't need any of these files. For instructions on setting
-up a facilitator, see doc/faciliator.txt.
+up a facilitator, see doc/facilitator-howto.txt.
1
0

04 Jan '13
commit 49de7bf689ee989997a1edbf2414a7bdbc2164f9
Author: David Fifield <david(a)bamsoftware.com>
Date: Thu Jan 3 21:01:39 2013 -0800
Bump poll interval from 10 s to 60 s.
With recent CCC-related attention we have a lot more proxies (about 150
currently), so no need to poll so fast.
---
proxy/flashproxy.js | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/proxy/flashproxy.js b/proxy/flashproxy.js
index 19f1c08..8418a5d 100644
--- a/proxy/flashproxy.js
+++ b/proxy/flashproxy.js
@@ -59,7 +59,7 @@ var DEFAULT_FACILITATOR_URL = "https://tor-facilitator.bamsoftware.com/";
var DEFAULT_MAX_NUM_PROXY_PAIRS = 10;
-var DEFAULT_FACILITATOR_POLL_INTERVAL = 10.0;
+var DEFAULT_FACILITATOR_POLL_INTERVAL = 60.0;
var MIN_FACILITATOR_POLL_INTERVAL = 1.0;
/* Bytes per second. Set to undefined to disable limit. */
1
0

[atlas/master] Added instructions for how to run a local Atlas server
by art@torproject.org 03 Jan '13
by art@torproject.org 03 Jan '13
03 Jan '13
commit f0eed4f4d4a55dde690844df4985bddef781b127
Author: Peter Evjan <peter.evjan(a)gmail.com>
Date: Tue Jan 1 18:06:49 2013 +1100
Added instructions for how to run a local Atlas server
---
Readme.rst | 17 +++++++++++++++++
1 files changed, 17 insertions(+), 0 deletions(-)
diff --git a/Readme.rst b/Readme.rst
index c5cac71..bb31355 100644
--- a/Readme.rst
+++ b/Readme.rst
@@ -5,3 +5,20 @@ Tor Status is a web application to discover Tor relays and bridges. It provides
information on how relays are configured along with graphics about their past.
+Running it
+----------
+
+You need to have Python and Tornado installed to run the web server locally. The easiest
+way of installing Tornado is:
+
+::
+
+ sudo easy_install tornado
+
+Once that is done, you can run the server with the following command:
+
+::
+
+ python run.py
+
+After which, the Atlas site will be available on http://localhost:8888/index.html
\ No newline at end of file
1
0
commit ec1078ccc39af8d154ef2f70781f1a3787be6789
Author: Damian Johnson <atagar(a)torproject.org>
Date: Thu Jan 3 09:42:39 2013 -0800
Whitelist support for shell commands
Shell commands have at times been the bane of my existance. They live outside
the PATH (causing our is_available() to fail), and now it turns out that
subprocess.Popen() fails to find them too. In retrospect both make sense but at
first both are worthy of some head scratching.
Adding a whitelist we can add shell commands to so they'll behave as we expect.
---
stem/util/system.py | 30 ++++++++++++++++++++++--------
1 files changed, 22 insertions(+), 8 deletions(-)
diff --git a/stem/util/system.py b/stem/util/system.py
index 0b4427e..080b080 100644
--- a/stem/util/system.py
+++ b/stem/util/system.py
@@ -31,11 +31,18 @@ import stem.util.proc
from stem import UNDEFINED, CircStatus
from stem.util import log
-# Mapping of commands to if they're available or not. This isn't always
-# reliable, failing for some special commands. For these the cache is
-# prepopulated to skip lookups.
+# Mapping of commands to if they're available or not.
-CMD_AVAILABLE_CACHE = {"ulimit": True}
+CMD_AVAILABLE_CACHE = {}
+
+# An incomplete listing of commands provided by the shell. Expand this as
+# needed. Some noteworthy things about shell commands...
+#
+# * They're not in the path so is_available() will fail.
+# * subprocess.Popen() without the 'shell = True' argument will fail with...
+# OSError: [Errno 2] No such file or directory
+
+SHELL_COMMANDS = ['ulimit']
IS_RUNNING_PS_LINUX = "ps -A co command"
IS_RUNNING_PS_BSD = "ps -ao ucomm="
@@ -86,8 +93,9 @@ def is_available(command, cached=True):
than one command is present (for instance "ls -a | grep foo") then this
just checks the first.
- Note that many builtin common commands (like cd and ulimit) aren't in the
- PATH so this lookup will fail for them.
+ Note that shell (like cd and ulimit) aren't in the PATH so this lookup will
+ try to assume that it's available. This only happends for recognized shell
+ commands (those in SHELL_COMMANDS).
:param str command: command to search for
:param bool cached: makes use of available cached results if **True**
@@ -98,7 +106,11 @@ def is_available(command, cached=True):
if " " in command: command = command.split(" ")[0]
- if cached and command in CMD_AVAILABLE_CACHE:
+ if command in SHELL_COMMANDS:
+ # we can't actually look it up, so hope the shell really provides it...
+
+ return True
+ elif cached and command in CMD_AVAILABLE_CACHE:
return CMD_AVAILABLE_CACHE[command]
else:
cmd_exists = False
@@ -568,8 +580,10 @@ def call(command, default = UNDEFINED):
"""
try:
+ is_shell_command = command.split(" ")[0] in SHELL_COMMANDS
+
start_time = time.time()
- stdout, stderr = subprocess.Popen(command.split(), stdout = subprocess.PIPE, stderr = subprocess.PIPE).communicate()
+ stdout, stderr = subprocess.Popen(command.split(), stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = is_shell_command).communicate()
stdout, stderr = stdout.strip(), stderr.strip()
runtime = time.time() - start_time
1
0
commit 8dbea0fa0c35d9118a7104b35af5088d96ee1db9
Author: Damian Johnson <atagar(a)torproject.org>
Date: Thu Jan 3 09:54:00 2013 -0800
Using stem's system util
Stem has some (not all) of our system utilities. The most interesting one is
the call() function. Stem provides a subprocess based implementation that's
pretty simple, while ours was os.popen() based and a tangled mess of hundreds
of lines.
The reason for that mess was that I wanted to support caching and piped
arguments (like "ps -aux | grep tor"). However, we only used the caching at
one spot in the *entire* codebase, and the piping on reflection was a bad idea.
This is code - we can filter our own results without relying on grep and egrep.
This required a few changes to the connection util (the heaviest user of grep)
and has a couple points of regression...
* The bandwidthStats panel no longer gets cached ps results - we need to figure
out a cleaner method for deduplicating those system calls.
* We used the runtimes of our system calls to partly calculate arm's cpu usage.
This was a bit of a hack but I'm not sure of a better way of including those
invocations in our usage. This will require some more thought.
---
armrc.sample | 1 -
src/cli/graphing/bandwidthStats.py | 10 +-
src/cli/logPanel.py | 4 +-
src/util/connections.py | 74 +++++++----
src/util/hostnames.py | 6 +-
src/util/sysTools.py | 254 +-----------------------------------
src/util/torConfig.py | 7 +-
src/util/torTools.py | 65 ++++------
src/util/uiTools.py | 12 +-
9 files changed, 99 insertions(+), 334 deletions(-)
diff --git a/armrc.sample b/armrc.sample
index 5299de4..b5aa31b 100644
--- a/armrc.sample
+++ b/armrc.sample
@@ -274,7 +274,6 @@ queries.hostnames.poolSize 5
queries.hostnames.useSocketModule false
# Caching parameters
-cache.sysCalls.size 600
cache.hostnames.size 700000
cache.hostnames.trimSize 200000
cache.logPanel.size 1000
diff --git a/src/cli/graphing/bandwidthStats.py b/src/cli/graphing/bandwidthStats.py
index 8a75fff..dd0c293 100644
--- a/src/cli/graphing/bandwidthStats.py
+++ b/src/cli/graphing/bandwidthStats.py
@@ -9,9 +9,9 @@ import curses
import cli.controller
from cli.graphing import graphPanel
-from util import sysTools, torTools, uiTools
+from util import torTools, uiTools
-from stem.util import conf, log, str_tools
+from stem.util import conf, log, str_tools, system
def conf_handler(key, value):
if key == "features.graph.bw.accounting.rate":
@@ -120,13 +120,15 @@ class BandwidthStats(graphPanel.GraphStats):
if orPort == "0": return
# gets the uptime (using the same parameters as the header panel to take
- # advantage of caching
+ # advantage of caching)
+ # TODO: stem dropped system caching support so we'll need to think of
+ # something else
uptime = None
queryPid = conn.getMyPid()
if queryPid:
queryParam = ["%cpu", "rss", "%mem", "etime"]
queryCmd = "ps -p %s -o %s" % (queryPid, ",".join(queryParam))
- psCall = sysTools.call(queryCmd, 3600, True)
+ psCall = system.call(queryCmd, None)
if psCall and len(psCall) == 2:
stats = psCall[1].strip().split()
diff --git a/src/cli/logPanel.py b/src/cli/logPanel.py
index 820f295..ecb3109 100644
--- a/src/cli/logPanel.py
+++ b/src/cli/logPanel.py
@@ -13,7 +13,7 @@ import threading
import stem
from stem.response import events
-from stem.util import conf, log
+from stem.util import conf, log, system
import popups
from version import VERSION
@@ -246,7 +246,7 @@ def getLogFileEntries(runlevels, readLimit = None, addLimit = None):
lines = []
try:
if readLimit:
- lines = sysTools.call("tail -n %i %s" % (readLimit, loggingLocation))
+ lines = system.call("tail -n %i %s" % (readLimit, loggingLocation))
if not lines: raise IOError()
else:
logFile = open(loggingLocation, "r")
diff --git a/src/util/connections.py b/src/util/connections.py
index d633c03..aa2aa2e 100644
--- a/src/util/connections.py
+++ b/src/util/connections.py
@@ -17,13 +17,12 @@ options that perform even better (thanks to Fabian Keil and Hans Schnehl):
- procstat procstat -f <pid> | grep TCP | grep -v 0.0.0.0:0
"""
+import re
import os
import time
import threading
-from util import sysTools
-
-from stem.util import conf, enum, log, proc
+from stem.util import conf, enum, log, proc, system
# enums for connection resolution utilities
Resolver = enum.Enum(("PROC", "proc"),
@@ -46,13 +45,13 @@ RECREATE_HALTED_RESOLVERS = False
# tcp 0 0 127.0.0.1:9051 127.0.0.1:53308 ESTABLISHED 9912/tor
# *note: bsd uses a different variant ('-t' => '-p tcp', but worse an
# equivilant -p doesn't exist so this can't function)
-RUN_NETSTAT = "netstat -np | grep \"ESTABLISHED %s/%s\""
+RUN_NETSTAT = "netstat -np"
# n = numeric ports, p = include process, t = tcp sockets, u = udp sockets
# output:
# ESTAB 0 0 127.0.0.1:9051 127.0.0.1:53308 users:(("tor",9912,20))
# *note: under freebsd this command belongs to a spreadsheet program
-RUN_SS = "ss -nptu | grep \"ESTAB.*\\\"%s\\\",%s\""
+RUN_SS = "ss -nptu"
# n = prevent dns lookups, P = show port numbers (not names), i = ip only,
# -w = no warnings
@@ -62,15 +61,15 @@ RUN_SS = "ss -nptu | grep \"ESTAB.*\\\"%s\\\",%s\""
# oddly, using the -p flag via:
# lsof lsof -nPi -p <pid> | grep "^<process>.*(ESTABLISHED)"
# is much slower (11-28% in tests I ran)
-RUN_LSOF = "lsof -wnPi | egrep \"^%s *%s.*((UDP.*)|(\\(ESTABLISHED\\)))\""
+RUN_LSOF = "lsof -wnPi"
# output:
# atagar tor 3475 tcp4 127.0.0.1:9051 127.0.0.1:38942 ESTABLISHED
# *note: this isn't available by default under ubuntu
-RUN_SOCKSTAT = "sockstat | egrep \"%s *%s.*ESTABLISHED\""
+RUN_SOCKSTAT = "sockstat"
-RUN_BSD_SOCKSTAT = "sockstat -4c | grep '%s *%s'"
-RUN_BSD_PROCSTAT = "procstat -f %s | grep TCP | grep -v 0.0.0.0:0"
+RUN_BSD_SOCKSTAT = "sockstat -4c"
+RUN_BSD_PROCSTAT = "procstat -f %s"
RESOLVERS = [] # connection resolvers available via the singleton constructor
RESOLVER_FAILURE_TOLERANCE = 3 # number of subsequent failures before moving on to another resolver
@@ -176,9 +175,9 @@ def getPortUsage(port):
def getResolverCommand(resolutionCmd, processName, processPid = ""):
"""
- Provides the command that would be processed for the given resolver type.
- This raises a ValueError if either the resolutionCmd isn't recognized or a
- pid was requited but not provided.
+ Provides the command and line filter that would be processed for the given
+ resolver type. This raises a ValueError if either the resolutionCmd isn't
+ recognized or a pid was requited but not provided.
Arguments:
resolutionCmd - command to use in resolving the address
@@ -194,13 +193,39 @@ def getResolverCommand(resolutionCmd, processName, processPid = ""):
# if the pid was undefined then match any in that field
processPid = "[0-9]*"
- if resolutionCmd == Resolver.PROC: return ""
- elif resolutionCmd == Resolver.NETSTAT: return RUN_NETSTAT % (processPid, processName)
- elif resolutionCmd == Resolver.SS: return RUN_SS % (processName, processPid)
- elif resolutionCmd == Resolver.LSOF: return RUN_LSOF % (processName, processPid)
- elif resolutionCmd == Resolver.SOCKSTAT: return RUN_SOCKSTAT % (processName, processPid)
- elif resolutionCmd == Resolver.BSD_SOCKSTAT: return RUN_BSD_SOCKSTAT % (processName, processPid)
- elif resolutionCmd == Resolver.BSD_PROCSTAT: return RUN_BSD_PROCSTAT % processPid
+ no_op_filter = lambda line: True
+
+ if resolutionCmd == Resolver.PROC: return ("", no_op_filter)
+ elif resolutionCmd == Resolver.NETSTAT:
+ return (
+ RUN_NETSTAT,
+ lambda line: "ESTABLISHED %s/%s" % (processPid, processName) in line
+ )
+ elif resolutionCmd == Resolver.SS:
+ return (
+ RUN_SS,
+ lambda line: ("ESTAB" in line) and ("\"%s\",%s" % (processName, processPid) in line)
+ )
+ elif resolutionCmd == Resolver.LSOF:
+ return (
+ RUN_LSOF,
+ lambda line: re.match("^%s *%s.*((UDP.*)|(\(ESTABLISHED\)))" % (processName, processPid))
+ )
+ elif resolutionCmd == Resolver.SOCKSTAT:
+ return (
+ RUN_SOCKSTAT,
+ lambda line: re.match("%s *%s.*ESTABLISHED" % (processName, processPid))
+ )
+ elif resolutionCmd == Resolver.BSD_SOCKSTAT:
+ return (
+ RUN_BSD_SOCKSTAT,
+ lambda line: re.match("%s *%s" % (processName, processPid))
+ )
+ elif resolutionCmd == Resolver.BSD_PROCSTAT:
+ return (
+ RUN_BSD_PROCSTAT % processPid,
+ lambda line: "TCP" in line and "0.0.0.0:0" not in line
+ )
else: raise ValueError("Unrecognized resolution type: %s" % resolutionCmd)
def getConnections(resolutionCmd, processName, processPid = ""):
@@ -232,8 +257,9 @@ def getConnections(resolutionCmd, processName, processPid = ""):
else:
# Queries a resolution utility (netstat, lsof, etc). This raises an
# IOError if the command fails or isn't available.
- cmd = getResolverCommand(resolutionCmd, processName, processPid)
- results = sysTools.call(cmd)
+ cmd, cmd_filter = getResolverCommand(resolutionCmd, processName, processPid)
+ results = system.call(cmd)
+ results = filter(cmd_filter, results)
if not results: raise IOError("No results found using: %s" % cmd)
@@ -422,7 +448,7 @@ class ConnectionResolver(threading.Thread):
# resolvers.
resolverCmd = resolver.replace(" (bsd)", "")
- if resolver == Resolver.PROC or sysTools.isAvailable(resolverCmd):
+ if resolver == Resolver.PROC or system.is_available(resolverCmd):
self.defaultResolver = resolver
break
@@ -501,7 +527,7 @@ class ConnectionResolver(threading.Thread):
except (ValueError, IOError), exc:
# this logs in a couple of cases:
# - special failures noted by getConnections (most cases are already
- # logged via sysTools)
+ # logged via system)
# - note fail-overs for default resolution methods
if str(exc).startswith("No results found using:"):
log.info(exc)
@@ -690,7 +716,7 @@ class AppResolver:
else: lsofArgs.append("-i tcp:%s" % port)
if lsofArgs:
- lsofResults = sysTools.call("lsof -nP " + " ".join(lsofArgs))
+ lsofResults = system.call("lsof -nP " + " ".join(lsofArgs))
else: lsofResults = None
if not lsofResults and self.failureCount != -1:
diff --git a/src/util/hostnames.py b/src/util/hostnames.py
index d360461..a58eb94 100644
--- a/src/util/hostnames.py
+++ b/src/util/hostnames.py
@@ -32,9 +32,7 @@ import itertools
import Queue
import distutils.sysconfig
-from util import sysTools
-
-from stem.util import conf, log
+from stem.util import conf, log, system
RESOLVER = None # hostname resolver (service is stopped if None)
RESOLVER_LOCK = threading.RLock() # regulates assignment to the RESOLVER
@@ -233,7 +231,7 @@ def _resolveViaHost(ipAddr):
ipAddr - ip address to be resolved
"""
- hostname = sysTools.call("host %s" % ipAddr)[0].split()[-1:][0]
+ hostname = system.call("host %s" % ipAddr)[0].split()[-1:][0]
if hostname == "reached":
# got message: ";; connection timed out; no servers could be reached"
diff --git a/src/util/sysTools.py b/src/util/sysTools.py
index 8078c1c..af38ced 100644
--- a/src/util/sysTools.py
+++ b/src/util/sysTools.py
@@ -6,20 +6,9 @@ import os
import time
import threading
-from stem.util import conf, log, proc, str_tools
-
-# Mapping of commands to if they're available or not. This isn't always
-# reliable, failing for some special commands. For these the cache is
-# prepopulated to skip lookups.
-CMD_AVAILABLE_CACHE = {"ulimit": True}
-
-# cached system call results, mapping the command issued to the (time, results) tuple
-CALL_CACHE = {}
-IS_FAILURES_CACHED = True # caches both successful and failed results if true
-CALL_CACHE_LOCK = threading.RLock() # governs concurrent modifications of CALL_CACHE
+from stem.util import conf, log, proc, str_tools, system
PROCESS_NAME_CACHE = {} # mapping of pids to their process names
-PWD_CACHE = {} # mapping of pids to their present working directory
RESOURCE_TRACKERS = {} # mapping of pids to their resource tracker instances
# Runtimes for system calls, used to estimate cpu usage. Entries are tuples of
@@ -30,9 +19,11 @@ SAMPLING_PERIOD = 5 # time of the sampling period
CONFIG = conf.config_dict("arm", {
"queries.resourceUsage.rate": 5,
- "cache.sysCalls.size": 600,
})
+# TODO: This was a bit of a hack, and one that won't work now that we lack our
+# call() method to populate RUNTIMES.
+
def getSysCpuUsage():
"""
Provides an estimate of the cpu usage for system calls made through this
@@ -50,35 +41,6 @@ def getSysCpuUsage():
runtimeSum = sum([entry[1] for entry in RUNTIMES])
return runtimeSum / SAMPLING_PERIOD
-def isAvailable(command, cached=True):
- """
- Checks the current PATH to see if a command is available or not. If a full
- call is provided then this just checks the first command (for instance
- "ls -a | grep foo" is truncated to "ls"). This returns True if an accessible
- executable by the name is found and False otherwise.
-
- Arguments:
- command - command for which to search
- cached - this makes use of available cached results if true, otherwise
- they're overwritten
- """
-
- if " " in command: command = command.split(" ")[0]
-
- if cached and command in CMD_AVAILABLE_CACHE:
- return CMD_AVAILABLE_CACHE[command]
- else:
- cmdExists = False
- for path in os.environ["PATH"].split(os.pathsep):
- cmdPath = os.path.join(path, command)
-
- if os.path.exists(cmdPath) and os.access(cmdPath, os.X_OK):
- cmdExists = True
- break
-
- CMD_AVAILABLE_CACHE[command] = cmdExists
- return cmdExists
-
def getFileErrorMsg(exc):
"""
Strips off the error number prefix for file related IOError messages. For
@@ -129,7 +91,7 @@ def getProcessName(pid, default = None, cacheFailure = True):
# the ps call formats results as:
# COMMAND
# tor
- psCall = call("ps -p %s -o command" % pid)
+ psCall = system.call("ps -p %s -o command" % pid)
if psCall and len(psCall) >= 2 and not " " in psCall[1]:
processName, raisedExc = psCall[1].strip(), None
@@ -148,210 +110,6 @@ def getProcessName(pid, default = None, cacheFailure = True):
PROCESS_NAME_CACHE[pid] = processName
return processName
-def getPwd(pid):
- """
- Provices the working directory of the given process. This raises an IOError
- if it can't be determined.
-
- Arguments:
- pid - pid of the process
- """
-
- if not pid: raise IOError("we couldn't get the pid")
- elif pid in PWD_CACHE: return PWD_CACHE[pid]
-
- # try fetching via the proc contents if available
- if proc.is_available():
- try:
- pwd = proc.get_cwd(pid)
- PWD_CACHE[pid] = pwd
- return pwd
- except IOError: pass # fall back to pwdx
- elif os.uname()[0] in ("Darwin", "FreeBSD", "OpenBSD"):
- # BSD neither useres the above proc info nor does it have pwdx. Use lsof to
- # determine this instead:
- # https://trac.torproject.org/projects/tor/ticket/4236
- #
- # ~$ lsof -a -p 75717 -d cwd -Fn
- # p75717
- # n/Users/atagar/tor/src/or
-
- try:
- results = call("lsof -a -p %s -d cwd -Fn" % pid)
-
- if results and len(results) == 2 and results[1].startswith("n/"):
- pwd = results[1][1:].strip()
- PWD_CACHE[pid] = pwd
- return pwd
- except IOError, exc: pass
-
- try:
- # pwdx results are of the form:
- # 3799: /home/atagar
- # 5839: No such process
- results = call("pwdx %s" % pid)
- if not results:
- raise IOError("pwdx didn't return any results")
- elif results[0].endswith("No such process"):
- raise IOError("pwdx reported no process for pid " + pid)
- elif len(results) != 1 or results[0].count(" ") != 1:
- raise IOError("we got unexpected output from pwdx")
- else:
- pwd = results[0][results[0].find(" ") + 1:].strip()
- PWD_CACHE[pid] = pwd
- return pwd
- except IOError, exc:
- raise IOError("the pwdx call failed: " + str(exc))
-
-def expandRelativePath(path, ownerPid):
- """
- Expands relative paths to be an absolute path with reference to a given
- process. This raises an IOError if the process pwd is required and can't be
- resolved.
-
- Arguments:
- path - path to be expanded
- ownerPid - pid of the process to which the path belongs
- """
-
- if not path or path[0] == "/": return path
- else:
- if path.startswith("./"): path = path[2:]
- processPwd = getPwd(ownerPid)
- return "%s/%s" % (processPwd, path)
-
-def call(command, cacheAge=0, suppressExc=False, quiet=True):
- """
- Convenience function for performing system calls, providing:
- - suppression of any writing to stdout, both directing stderr to /dev/null
- and checking for the existence of commands before executing them
- - logging of results (command issued, runtime, success/failure, etc)
- - optional exception suppression and caching (the max age for cached results
- is a minute)
-
- Arguments:
- command - command to be issued
- cacheAge - uses cached results rather than issuing a new request if last
- fetched within this number of seconds (if zero then all
- caching functionality is skipped)
- suppressExc - provides None in cases of failure if True, otherwise IOErrors
- are raised
- quiet - if True, "2> /dev/null" is appended to all commands
- """
-
- # caching functionality (fetching and trimming)
- if cacheAge > 0:
- global CALL_CACHE
-
- # keeps consistency that we never use entries over a minute old (these
- # results are 'dirty' and might be trimmed at any time)
- cacheAge = min(cacheAge, 60)
- cacheSize = CONFIG["cache.sysCalls.size"]
-
- # if the cache is especially large then trim old entries
- if len(CALL_CACHE) > cacheSize:
- CALL_CACHE_LOCK.acquire()
-
- # checks that we haven't trimmed while waiting
- if len(CALL_CACHE) > cacheSize:
- # constructs a new cache with only entries less than a minute old
- newCache, currentTime = {}, time.time()
-
- for cachedCommand, cachedResult in CALL_CACHE.items():
- if currentTime - cachedResult[0] < 60:
- newCache[cachedCommand] = cachedResult
-
- # if the cache is almost as big as the trim size then we risk doing this
- # frequently, so grow it and log
- if len(newCache) > (0.75 * cacheSize):
- cacheSize = len(newCache) * 2
- CONFIG["cache.sysCalls.size"] = cacheSize
-
- log.info("growing system call cache to %i entries" % cacheSize)
-
- CALL_CACHE = newCache
- CALL_CACHE_LOCK.release()
-
- # checks if we can make use of cached results
- if command in CALL_CACHE and time.time() - CALL_CACHE[command][0] < cacheAge:
- cachedResults = CALL_CACHE[command][1]
- cacheAge = time.time() - CALL_CACHE[command][0]
-
- if isinstance(cachedResults, IOError):
- if IS_FAILURES_CACHED:
- log.trace(CONFIG["log.sysCallCached"], "system call (cached failure): %s (age: %0.1f, error: %s)" % (command, cacheAge, cachedResults))
-
- if suppressExc: return None
- else: raise cachedResults
- else:
- # flag was toggled after a failure was cached - reissue call, ignoring the cache
- return call(command, 0, suppressExc, quiet)
- else:
- log.trace(CONFIG["log.sysCallCached"], "system call (cached): %s (age: %0.1f)" % (command, cacheAge))
-
- return cachedResults
-
- startTime = time.time()
- commandCall, results, errorExc = None, None, None
-
- # Gets all the commands involved, taking piping into consideration. If the
- # pipe is quoted (ie, echo "an | example") then it's ignored.
-
- commandComp = []
- for component in command.split("|"):
- if not commandComp or component.count("\"") % 2 == 0:
- commandComp.append(component)
- else:
- # pipe is within quotes
- commandComp[-1] += "|" + component
-
- # preprocessing for the commands to prevent anything going to stdout
- for i in range(len(commandComp)):
- subcommand = commandComp[i].strip()
-
- if not isAvailable(subcommand): errorExc = IOError("'%s' is unavailable" % subcommand.split(" ")[0])
- if quiet: commandComp[i] = "%s 2> /dev/null" % subcommand
-
- # processes the system call
- if not errorExc:
- try:
- commandCall = os.popen(" | ".join(commandComp))
- results = commandCall.readlines()
- except IOError, exc:
- errorExc = exc
-
- # make sure sys call is closed
- if commandCall: commandCall.close()
-
- if errorExc:
- # log failure and either provide None or re-raise exception
- log.info("system call (failed): %s (error: %s)" % (command, str(errorExc)))
-
- if cacheAge > 0 and IS_FAILURES_CACHED:
- CALL_CACHE_LOCK.acquire()
- CALL_CACHE[command] = (time.time(), errorExc)
- CALL_CACHE_LOCK.release()
-
- if suppressExc: return None
- else: raise errorExc
- else:
- # log call information and if we're caching then save the results
- currentTime = time.time()
- runtime = currentTime - startTime
- log.debug("system call: %s (runtime: %0.2f)" % (command, runtime))
-
- # append the runtime, and remove any outside of the sampling period
- RUNTIMES.append((currentTime, runtime))
- while RUNTIMES and currentTime - RUNTIMES[0][0] > SAMPLING_PERIOD:
- RUNTIMES.pop(0)
-
- if cacheAge > 0:
- CALL_CACHE_LOCK.acquire()
- CALL_CACHE[command] = (time.time(), results)
- CALL_CACHE_LOCK.release()
-
- return results
-
def getResourceTracker(pid, noSpawn = False):
"""
Provides a running singleton ResourceTracker instance for the given pid.
@@ -489,7 +247,7 @@ class ResourceTracker(threading.Thread):
# TIME ELAPSED RSS %MEM
# 0:04.40 37:57 18772 0.9
- psCall = call("ps -p %s -o cputime,etime,rss,%%mem" % self.processPid)
+ psCall = system.call("ps -p %s -o cputime,etime,rss,%%mem" % self.processPid)
isSuccessful = False
if psCall and len(psCall) >= 2:
diff --git a/src/util/torConfig.py b/src/util/torConfig.py
index 57a9d05..a26cced 100644
--- a/src/util/torConfig.py
+++ b/src/util/torConfig.py
@@ -11,7 +11,7 @@ import stem.version
from util import sysTools, torTools, uiTools
-from stem.util import conf, enum, log, str_tools
+from stem.util import conf, enum, log, str_tools, system
def conf_handler(key, value):
if key == "config.important":
@@ -176,7 +176,7 @@ def loadOptionDescriptions(loadPath = None, checkVersion = True):
CONFIG_DESCRIPTIONS.clear()
raise IOError("input file format is invalid")
else:
- manCallResults = sysTools.call("man tor")
+ manCallResults = system.call("man tor")
if not manCallResults:
raise IOError("man page not found")
@@ -347,7 +347,8 @@ def getConfigLocation():
if not configLocation: raise IOError("unable to query the torrc location")
try:
- return torPrefix + sysTools.expandRelativePath(configLocation, torPid)
+ torCwd = system.get_cwd(torPid)
+ return torPrefix + system.expand_path(configLocation, torCwd)
except IOError, exc:
raise IOError("querying tor's pwd failed because %s" % exc)
diff --git a/src/util/torTools.py b/src/util/torTools.py
index 73121c5..d82e7cd 100644
--- a/src/util/torTools.py
+++ b/src/util/torTools.py
@@ -7,7 +7,6 @@ import os
import pwd
import time
import math
-import socket
import thread
import threading
import Queue
@@ -16,9 +15,9 @@ import stem
import stem.control
import stem.descriptor
-from util import connections, sysTools
+from util import connections
-from stem.util import conf, enum, log, proc, str_tools
+from stem.util import conf, enum, log, proc, str_tools, system
# enums for tor's controller state:
# INIT - attached to a new controller
@@ -111,7 +110,7 @@ def getPid(controlPort=9051, pidFilePath=None):
# - tor is running under a different name
# - there are multiple instances of tor
try:
- results = sysTools.call("pgrep -x tor")
+ results = system.call("pgrep -x tor")
if len(results) == 1 and len(results[0].split()) == 1:
pid = results[0].strip()
if pid.isdigit(): return pid
@@ -121,7 +120,7 @@ def getPid(controlPort=9051, pidFilePath=None):
# - tor's running under a different name
# - there's multiple instances of tor
try:
- results = sysTools.call("pidof tor")
+ results = system.call("pidof tor")
if len(results) == 1 and len(results[0].split()) == 1:
pid = results[0].strip()
if pid.isdigit(): return pid
@@ -130,7 +129,8 @@ def getPid(controlPort=9051, pidFilePath=None):
# attempts to resolve using netstat, failing if:
# - tor's being run as a different user due to permissions
try:
- results = sysTools.call("netstat -npl | grep 127.0.0.1:%i" % controlPort)
+ results = system.call("netstat -npl")
+ results = filter(lambda line: "127.0.0.1:%i" % controlPort in line, results)
if len(results) == 1:
results = results[0].split()[6] # process field (ex. "7184/tor")
@@ -142,7 +142,7 @@ def getPid(controlPort=9051, pidFilePath=None):
# - tor's running under a different name
# - there's multiple instances of tor
try:
- results = sysTools.call("ps -o pid -C tor")
+ results = system.call("ps -o pid -C tor")
if len(results) == 2:
pid = results[1].strip()
if pid.isdigit(): return pid
@@ -157,7 +157,9 @@ def getPid(controlPort=9051, pidFilePath=None):
# TODO: the later two issues could be solved by filtering for the control
# port IP address instead of the process name.
try:
- results = sysTools.call("sockstat -4l -P tcp -p %i | grep tor" % controlPort)
+ results = system.call("sockstat -4l -P tcp -p %i" % controlPort)
+ results = filter(lambda line: "tor" in line, results)
+
if len(results) == 1 and len(results[0].split()) == 7:
pid = results[0].split()[2]
if pid.isdigit(): return pid
@@ -169,7 +171,9 @@ def getPid(controlPort=9051, pidFilePath=None):
# - there's multiple instances of tor
try:
- results = sysTools.call("ps axc | egrep \" tor$\"")
+ results = system.call("ps axc")
+ results = filter(lambda line: line.endswith(" tor"), results)
+
if len(results) == 1 and len(results[0].split()) > 0:
pid = results[0].split()[0]
if pid.isdigit(): return pid
@@ -183,7 +187,8 @@ def getPid(controlPort=9051, pidFilePath=None):
# same control port on different addresses.
try:
- results = sysTools.call("lsof -wnPi | egrep \"^tor.*:%i\"" % controlPort)
+ results = system.call("lsof -wnPi")
+ results = filter(lambda line: line.startswith("tor.*:%i" % controlPort), results)
# This can result in multiple entries with the same pid (from the query
# itself). Checking all lines to see if they're in agreement about the pid.
@@ -203,29 +208,6 @@ def getPid(controlPort=9051, pidFilePath=None):
return None
-def getBsdJailId():
- """
- Get the FreeBSD jail id for the monitored Tor process.
- """
-
- # Output when called from a FreeBSD jail or when Tor isn't jailed:
- # JID
- # 0
- #
- # Otherwise it's something like:
- # JID
- # 1
-
- torPid = getConn().getMyPid()
- psOutput = sysTools.call("ps -p %s -o jid" % torPid)
-
- if len(psOutput) == 2 and len(psOutput[1].split()) == 1:
- jid = psOutput[1].strip()
- if jid.isdigit(): return int(jid)
-
- log.warn("Failed to figure out the FreeBSD jail id. Assuming 0.")
- return 0
-
def isTorRunning():
"""
Simple check for if a tor process is running. If this can't be determined
@@ -250,9 +232,9 @@ def isTorRunning():
if os.uname()[0] in ("Darwin", "FreeBSD", "OpenBSD"):
primaryResolver, secondaryResolver = secondaryResolver, primaryResolver
- commandResults = sysTools.call(primaryResolver)
+ commandResults = system.call(primaryResolver)
if not commandResults:
- commandResults = sysTools.call(secondaryResolver)
+ commandResults = system.call(secondaryResolver)
if commandResults:
for cmd in commandResults:
@@ -1261,7 +1243,7 @@ class Controller:
# - 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"):
+ if not system.is_available("pkill"):
raise IOError("pkill command is unavailable")
self._isReset = False
@@ -1649,7 +1631,7 @@ class Controller:
# fall back to querying via ps
if not result:
- psResults = sysTools.call("ps -o user %s" % myPid)
+ psResults = system.call("ps -o user %s" % myPid)
if psResults and len(psResults) >= 2: result = psResults[1].strip()
elif key == "fdLimit":
# provides -1 if the query fails
@@ -1669,7 +1651,7 @@ class Controller:
result = (8192, True)
else:
# uses ulimit to estimate (-H is for hard limit, which is what tor uses)
- ulimitResults = sysTools.call("ulimit -Hn")
+ ulimitResults = system.call("ulimit -Hn")
if ulimitResults:
ulimit = ulimitResults[0].strip()
@@ -1681,12 +1663,13 @@ class Controller:
# adjusts the prefix path to account for jails under FreeBSD (many
# thanks to Fabian Keil!)
if not prefixPath and os.uname()[0] == "FreeBSD":
- jid = getBsdJailId()
+ torPid = getConn().getMyPid()
+ jid = system.get_bsd_jail_id()
if jid != 0:
# Output should be something like:
# JID IP Address Hostname Path
# 1 10.0.0.2 tor-jail /usr/jails/tor-jail
- jlsOutput = sysTools.call("jls -j %s" % jid)
+ jlsOutput = system.call("jls -j %s" % jid)
if len(jlsOutput) == 2 and len(jlsOutput[1].split()) == 4:
prefixPath = jlsOutput[1].split()[3]
@@ -1717,7 +1700,7 @@ class Controller:
if not result:
# if we're either not using proc or it fails then try using ps
try:
- psCall = sysTools.call("ps -p %s -o etime" % myPid)
+ psCall = system.call("ps -p %s -o etime" % myPid)
if psCall and len(psCall) >= 2:
etimeEntry = psCall[1].strip()
diff --git a/src/util/uiTools.py b/src/util/uiTools.py
index d93af73..2aac55a 100644
--- a/src/util/uiTools.py
+++ b/src/util/uiTools.py
@@ -11,7 +11,7 @@ import curses
from curses.ascii import isprint
-from stem.util import conf, enum, log
+from stem.util import conf, enum, log, system
# colors curses can handle
COLOR_LIST = {"red": curses.COLOR_RED, "green": curses.COLOR_GREEN,
@@ -102,8 +102,6 @@ def isUnicodeAvailable():
global IS_UNICODE_SUPPORTED
if IS_UNICODE_SUPPORTED == None:
- import sysTools
-
if CONFIG["features.printUnicode"]:
# Checks if our LANG variable is unicode. This is what will be respected
# when printing multi-byte characters after calling...
@@ -485,10 +483,10 @@ def _isWideCharactersAvailable():
# /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 111.1.6)
libDependencyLines = None
- if sysTools.isAvailable("ldd"):
- libDependencyLines = sysTools.call("ldd %s" % cursesLib)
- elif sysTools.isAvailable("otool"):
- libDependencyLines = sysTools.call("otool -L %s" % cursesLib)
+ if system.is_available("ldd"):
+ libDependencyLines = system.call("ldd %s" % cursesLib)
+ elif system.is_available("otool"):
+ libDependencyLines = system.call("otool -L %s" % cursesLib)
if libDependencyLines:
for line in libDependencyLines:
1
0

03 Jan '13
commit dffc8e359bcfeb00813a3afde6aa2328f6a6a476
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Thu Jan 3 12:45:50 2013 -0500
Whoops; make that unit test actually pass :/
---
src/test/test_crypto.c | 11 +++++++----
1 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c
index 9c69f31..67d2b83 100644
--- a/src/test/test_crypto.c
+++ b/src/test/test_crypto.c
@@ -1016,6 +1016,7 @@ test_crypto_curve25519_persist(void *arg)
char *content = NULL;
const char *cp;
struct stat st;
+ size_t taglen;
(void)arg;
@@ -1034,9 +1035,11 @@ test_crypto_curve25519_persist(void *arg)
content = read_file_to_str(fname, RFTS_BIN, &st);
tt_assert(content);
- tt_assert(!strcmpstart(content, "== c25519v1: testing =="));
- cp = content + strlen("== c25519v1: testing ==");
- tt_int_op(st.st_size, ==, 64 + strlen("== c25519v1: testing =="));
+ taglen = strlen("== c25519v1: testing ==");
+ tt_int_op(st.st_size, ==, 32+CURVE25519_PUBKEY_LEN+CURVE25519_SECKEY_LEN);
+ tt_assert(fast_memeq(content, "== c25519v1: testing ==", taglen));
+ tt_assert(tor_mem_is_zero(content+taglen, 32-taglen));
+ cp = content + 32;
test_memeq(keypair.seckey.secret_key,
cp,
CURVE25519_SECKEY_LEN);
@@ -1050,7 +1053,7 @@ test_crypto_curve25519_persist(void *arg)
tt_int_op(-1, ==, curve25519_keypair_read_from_file(&keypair2, &tag, fname));
- content[64] ^= 0xff;
+ content[69] ^= 0xff;
tt_int_op(0, ==, write_bytes_to_file(fname, content, st.st_size, 1));
tt_int_op(-1, ==, curve25519_keypair_read_from_file(&keypair2, &tag, fname));
1
0

[tor/master] Add a unit test for the curve25519 keypair persistence functions
by nickm@torproject.org 03 Jan '13
by nickm@torproject.org 03 Jan '13
03 Jan '13
commit 27ac306deb19cd45496cff839c6caccb9e81d37c
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Thu Jan 3 12:38:44 2013 -0500
Add a unit test for the curve25519 keypair persistence functions
---
src/test/test_crypto.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 55 insertions(+), 0 deletions(-)
diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c
index 1cd09e2..9c69f31 100644
--- a/src/test/test_crypto.c
+++ b/src/test/test_crypto.c
@@ -9,6 +9,7 @@
#include "or.h"
#include "test.h"
#include "aes.h"
+#include "util.h"
#ifdef CURVE25519_ENABLED
#include "crypto_curve25519.h"
#endif
@@ -1005,6 +1006,59 @@ test_crypto_curve25519_wrappers(void *arg)
done:
;
}
+
+static void
+test_crypto_curve25519_persist(void *arg)
+{
+ curve25519_keypair_t keypair, keypair2;
+ char *fname = tor_strdup(get_fname("curve25519_keypair"));
+ char *tag = NULL;
+ char *content = NULL;
+ const char *cp;
+ struct stat st;
+
+ (void)arg;
+
+ tt_int_op(0,==,curve25519_keypair_generate(&keypair, 0));
+
+ tt_int_op(0,==,curve25519_keypair_write_to_file(&keypair, fname, "testing"));
+ tt_int_op(0,==,curve25519_keypair_read_from_file(&keypair2, &tag, fname));
+ tt_str_op(tag,==,"testing");
+
+ test_memeq(keypair.pubkey.public_key,
+ keypair2.pubkey.public_key,
+ CURVE25519_PUBKEY_LEN);
+ test_memeq(keypair.seckey.secret_key,
+ keypair2.seckey.secret_key,
+ CURVE25519_SECKEY_LEN);
+
+ content = read_file_to_str(fname, RFTS_BIN, &st);
+ tt_assert(content);
+ tt_assert(!strcmpstart(content, "== c25519v1: testing =="));
+ cp = content + strlen("== c25519v1: testing ==");
+ tt_int_op(st.st_size, ==, 64 + strlen("== c25519v1: testing =="));
+ test_memeq(keypair.seckey.secret_key,
+ cp,
+ CURVE25519_SECKEY_LEN);
+ cp += CURVE25519_SECKEY_LEN;
+ test_memeq(keypair.pubkey.public_key,
+ cp,
+ CURVE25519_SECKEY_LEN);
+
+ tor_free(fname);
+ fname = tor_strdup(get_fname("bogus_keypair"));
+
+ tt_int_op(-1, ==, curve25519_keypair_read_from_file(&keypair2, &tag, fname));
+
+ content[64] ^= 0xff;
+ tt_int_op(0, ==, write_bytes_to_file(fname, content, st.st_size, 1));
+ tt_int_op(-1, ==, curve25519_keypair_read_from_file(&keypair2, &tag, fname));
+
+ done:
+ tor_free(fname);
+ tor_free(content);
+}
+
#endif
static void *
@@ -1043,6 +1097,7 @@ struct testcase_t crypto_tests[] = {
#ifdef CURVE25519_ENABLED
{ "curve25519_impl", test_crypto_curve25519_impl, 0, NULL, NULL },
{ "curve25519_wrappers", test_crypto_curve25519_wrappers, 0, NULL, NULL },
+ { "curve25519_persist", test_crypto_curve25519_persist, 0, NULL, NULL },
#endif
END_OF_TESTCASES
};
1
0

[tor/master] Refactor the CREATE_FAST handshake code to match the others.
by nickm@torproject.org 03 Jan '13
by nickm@torproject.org 03 Jan '13
03 Jan '13
commit 5fa1c7484cba293e6467acbca06a4143ce9da68d
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Tue Dec 4 16:51:31 2012 -0500
Refactor the CREATE_FAST handshake code to match the others.
---
src/or/circuitbuild.c | 11 +++++++----
src/or/circuitlist.c | 2 ++
src/or/onion_fast.c | 26 ++++++++++++++++++++++++--
src/or/onion_fast.h | 16 ++++++++++++++--
src/or/or.h | 3 ++-
5 files changed, 49 insertions(+), 9 deletions(-)
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 33a1351..b6cf125 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -645,11 +645,14 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
* new OR: we can be speedy and use CREATE_FAST to save an RSA operation
* and a DH operation. */
cell_type = CELL_CREATE_FAST;
+
memset(payload, 0, sizeof(payload));
- crypto_rand((char*) circ->cpath->fast_handshake_state,
- sizeof(circ->cpath->fast_handshake_state));
- memcpy(payload, circ->cpath->fast_handshake_state,
- sizeof(circ->cpath->fast_handshake_state));
+ if (fast_onionskin_create(&circ->cpath->fast_handshake_state,
+ (uint8_t *)payload) < 0) {
+ log_warn(LD_CIRC,"onion_skin_create FAST (first hop) failed.");
+ return - END_CIRC_REASON_INTERNAL;
+ }
+
note_request("cell: create fast", 1);
}
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index abb8395..2c17fd2 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -23,6 +23,7 @@
#include "networkstatus.h"
#include "nodelist.h"
#include "onion.h"
+#include "onion_fast.h"
#include "relay.h"
#include "rendclient.h"
#include "rendcommon.h"
@@ -744,6 +745,7 @@ circuit_free_cpath_node(crypt_path_t *victim)
crypto_digest_free(victim->f_digest);
crypto_digest_free(victim->b_digest);
crypto_dh_free(victim->dh_handshake_state);
+ fast_handshake_state_free(victim->fast_handshake_state);
extend_info_free(victim->extend_info);
memwipe(victim, 0xBB, sizeof(crypt_path_t)); /* poison memory */
diff --git a/src/or/onion_fast.c b/src/or/onion_fast.c
index 8d09de7..f33b048 100644
--- a/src/or/onion_fast.c
+++ b/src/or/onion_fast.c
@@ -12,6 +12,28 @@
#include "or.h"
#include "onion_fast.h"
+/**DOCDOC*/
+void
+fast_handshake_state_free(fast_handshake_state_t *victim)
+{
+ if (! victim)
+ return;
+ memwipe(victim, 0, sizeof(fast_handshake_state_t));
+ tor_free(victim);
+}
+
+/** DOCDOC */
+int
+fast_onionskin_create(fast_handshake_state_t **handshake_state_out,
+ uint8_t *handshake_out)
+{
+ fast_handshake_state_t *s;
+ *handshake_state_out = s =tor_malloc(sizeof(fast_handshake_state_t));
+ crypto_rand((char*)s->state, sizeof(s->state));
+ memcpy(handshake_out, s->state, DIGEST_LEN);
+ return 0;
+}
+
/** Implement the server side of the CREATE_FAST abbreviated handshake. The
* client has provided DIGEST_LEN key bytes in <b>key_in</b> ("x"). We
* generate a reply of DIGEST_LEN*2 bytes in <b>key_out</b>, consisting of a
@@ -63,7 +85,7 @@ fast_server_handshake(const uint8_t *key_in, /* DIGEST_LEN bytes */
* and protected by TLS).
*/
int
-fast_client_handshake(const uint8_t *handshake_state,/*DIGEST_LEN bytes*/
+fast_client_handshake(const fast_handshake_state_t *handshake_state,
const uint8_t *handshake_reply_out,/*DIGEST_LEN*2 bytes*/
uint8_t *key_out,
size_t key_out_len)
@@ -73,7 +95,7 @@ fast_client_handshake(const uint8_t *handshake_state,/*DIGEST_LEN bytes*/
size_t out_len;
int r = -1;
- memcpy(tmp, handshake_state, DIGEST_LEN);
+ memcpy(tmp, handshake_state->state, DIGEST_LEN);
memcpy(tmp+DIGEST_LEN, handshake_reply_out, DIGEST_LEN);
out_len = key_out_len+DIGEST_LEN;
out = tor_malloc(out_len);
diff --git a/src/or/onion_fast.h b/src/or/onion_fast.h
index 5c9d59e..2d652cc 100644
--- a/src/or/onion_fast.h
+++ b/src/or/onion_fast.h
@@ -12,12 +12,24 @@
#ifndef TOR_ONION_FAST_H
#define TOR_ONION_FAST_H
-int fast_server_handshake(const uint8_t *key_in,
+#define CREATE_FAST_LEN DIGEST_LEN
+#define CREATED_FAST_LEN DIGEST_LEN*2
+
+typedef struct fast_handshake_state_t {
+ uint8_t state[DIGEST_LEN];
+} fast_handshake_state_t;
+
+void fast_handshake_state_free(fast_handshake_state_t *victim);
+
+int fast_onionskin_create(fast_handshake_state_t **handshake_state_out,
+ uint8_t *handshake_out);
+
+int fast_server_handshake(const uint8_t *message_in,
uint8_t *handshake_reply_out,
uint8_t *key_out,
size_t key_out_len);
-int fast_client_handshake(const uint8_t *handshake_state,
+int fast_client_handshake(const fast_handshake_state_t *handshake_state,
const uint8_t *handshake_reply_out,
uint8_t *key_out,
size_t key_out_len);
diff --git a/src/or/or.h b/src/or/or.h
index 219336b..6fada77 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2524,6 +2524,7 @@ typedef enum {
#define CRYPT_PATH_MAGIC 0x70127012u
+struct fast_handshake_state_t;
/** Holds accounting information for a single step in the layered encryption
* performed by a circuit. Used only at the client edge of a circuit. */
typedef struct crypt_path_t {
@@ -2550,7 +2551,7 @@ typedef struct crypt_path_t {
* authentication, secrecy, and integrity we need, and we're already
* distinguishable from an OR.
*/
- uint8_t fast_handshake_state[DIGEST_LEN];
+ struct fast_handshake_state_t *fast_handshake_state;
/** Negotiated key material shared with the OR at this step. */
char handshake_digest[DIGEST_LEN];/* KH in tor-spec.txt */
1
0

[tor/master] Don't check create cells too much when we're relaying them
by nickm@torproject.org 03 Jan '13
by nickm@torproject.org 03 Jan '13
03 Jan '13
commit 5c68a1efaa9511baf2a2af0a49946e0a2de9e246
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Thu Dec 6 00:21:24 2012 -0500
Don't check create cells too much when we're relaying them
We want to sanity-check our own create cells carefully, and other
people's loosely.
---
src/or/circuitbuild.c | 21 ++++++++++++---------
src/or/onion.c | 21 +++++++++++++++++----
src/or/onion.h | 1 +
src/test/test_cell_formats.c | 3 ++-
4 files changed, 32 insertions(+), 14 deletions(-)
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 43ad9f4..b7ab47f 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -55,7 +55,8 @@ static channel_t * channel_connect_for_circuit(const tor_addr_t *addr,
uint16_t port,
const char *id_digest);
static int circuit_deliver_create_cell(circuit_t *circ,
- const create_cell_t *create_cell);
+ const create_cell_t *create_cell,
+ int relayed);
static int onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit);
static crypt_path_t *onion_next_hop_in_cpath(crypt_path_t *cpath);
static int onion_extend_cpath(origin_circuit_t *circ);
@@ -474,7 +475,7 @@ circuit_n_chan_done(channel_t *chan, int status)
} else {
/* pull the create cell out of circ->n_chan_create_cell, and send it */
tor_assert(circ->n_chan_create_cell);
- if (circuit_deliver_create_cell(circ, circ->n_chan_create_cell)<0) {
+ if (circuit_deliver_create_cell(circ, circ->n_chan_create_cell, 1)<0) {
circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT);
continue;
}
@@ -491,14 +492,16 @@ circuit_n_chan_done(channel_t *chan, int status)
* for the outgoing
* circuit <b>circ</b>, and deliver a cell of type <b>cell_type</b>
* (either CELL_CREATE or CELL_CREATE_FAST) with payload <b>payload</b>
- * to this circuit. DOCDOC payload_len
+ * to this circuit. DOCDOC new arguments
* Return -1 if we failed to find a suitable circid, else return 0.
*/
static int
-circuit_deliver_create_cell(circuit_t *circ, const create_cell_t *create_cell)
+circuit_deliver_create_cell(circuit_t *circ, const create_cell_t *create_cell,
+ int relayed)
{
cell_t cell;
circid_t id;
+ int r;
tor_assert(circ);
tor_assert(circ->n_chan);
@@ -516,7 +519,9 @@ circuit_deliver_create_cell(circuit_t *circ, const create_cell_t *create_cell)
circuit_set_n_circid_chan(circ, id, circ->n_chan);
memset(&cell, 0, sizeof(cell_t));
- if (create_cell_format(&cell, create_cell) < 0) {
+ r = relayed ? create_cell_format_relayed(&cell, create_cell)
+ : create_cell_format(&cell, create_cell);
+ if (r < 0) {
log_warn(LD_CIRC,"Couldn't format create cell");
return -1;
}
@@ -657,7 +662,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
}
cc.handshake_len = len;
- if (circuit_deliver_create_cell(TO_CIRCUIT(circ), &cc) < 0)
+ if (circuit_deliver_create_cell(TO_CIRCUIT(circ), &cc, 0) < 0)
return - END_CIRC_REASON_RESOURCELIMIT;
circ->cpath->state = CPATH_STATE_AWAITING_KEYS;
@@ -901,8 +906,6 @@ circuit_extend(cell_t *cell, circuit_t *circ)
&ec.orport_ipv4.addr,
ec.orport_ipv4.port);
- /* XXXX Make sure we can eventually deliver create cell with weird
- * content */
circ->n_chan_create_cell = tor_memdup(&ec.create_cell,
sizeof(ec.create_cell));
@@ -933,7 +936,7 @@ circuit_extend(cell_t *cell, circuit_t *circ)
"n_chan is %s",
channel_get_canonical_remote_descr(n_chan));
- if (circuit_deliver_create_cell(circ, &ec.create_cell) < 0)
+ if (circuit_deliver_create_cell(circ, &ec.create_cell, 1) < 0)
return -1;
return 0;
}
diff --git a/src/or/onion.c b/src/or/onion.c
index 753ddcf..b42a66c 100644
--- a/src/or/onion.c
+++ b/src/or/onion.c
@@ -808,13 +808,14 @@ extended_cell_parse(extended_cell_t *cell_out,
/** Fill <b>cell_out</b> with a correctly formatted version of the
* CREATE{,_FAST,2} cell in <b>cell_in</b>. Return 0 on success, -1 on
- * failure. */
-int
-create_cell_format(cell_t *cell_out, const create_cell_t *cell_in)
+ * failure. This is a cell we didn't originate if <b>relayed</b> is true. */
+static int
+create_cell_format_impl(cell_t *cell_out, const create_cell_t *cell_in,
+ int relayed)
{
uint8_t *p;
size_t space;
- if (check_create_cell(cell_in, 0) < 0)
+ if (check_create_cell(cell_in, relayed) < 0)
return -1;
memset(cell_out->payload, 0, sizeof(cell_out->payload));
@@ -848,6 +849,18 @@ create_cell_format(cell_t *cell_out, const create_cell_t *cell_in)
return 0;
}
+int
+create_cell_format(cell_t *cell_out, const create_cell_t *cell_in)
+{
+ return create_cell_format_impl(cell_out, cell_in, 0);
+}
+
+int
+create_cell_format_relayed(cell_t *cell_out, const create_cell_t *cell_in)
+{
+ return create_cell_format_impl(cell_out, cell_in, 1);
+}
+
/** Fill <b>cell_out</b> with a correctly formatted version of the
* CREATED{,_FAST,2} cell in <b>cell_in</b>. Return 0 on success, -1 on
* failure. */
diff --git a/src/or/onion.h b/src/or/onion.h
index 36cb761..e408139 100644
--- a/src/or/onion.h
+++ b/src/or/onion.h
@@ -106,6 +106,7 @@ int extended_cell_parse(extended_cell_t *cell_out, uint8_t command,
const uint8_t *payload_in, size_t payload_len);
int create_cell_format(cell_t *cell_out, const create_cell_t *cell_in);
+int create_cell_format_relayed(cell_t *cell_out, const create_cell_t *cell_in);
int created_cell_format(cell_t *cell_out, const created_cell_t *cell_in);
int extend_cell_format(uint8_t *command_out, uint16_t *len_out,
uint8_t *payload_out, const extend_cell_t *cell_in);
diff --git a/src/test/test_cell_formats.c b/src/test/test_cell_formats.c
index bdbc555..932124c 100644
--- a/src/test/test_cell_formats.c
+++ b/src/test/test_cell_formats.c
@@ -651,7 +651,7 @@ test_cfmt_extend_cells(void *arg)
tt_int_op(p2_cmd, ==, RELAY_COMMAND_EXTEND);
tt_int_op(p2_len, ==, 26+TAP_ONIONSKIN_CHALLENGE_LEN);
test_memeq(p2, p, RELAY_PAYLOAD_SIZE);
- tt_int_op(0, ==, create_cell_format(&cell, cc));
+ tt_int_op(0, ==, create_cell_format_relayed(&cell, cc));
/* Now let's do a minimal ntor EXTEND2 cell. */
memset(&ec, 0xff, sizeof(ec));
@@ -721,6 +721,7 @@ test_cfmt_extend_cells(void *arg)
/* Now the handshake prologue */
"01050063");
test_memeq(p2+1+8+22+4, b, 99+20);
+ tt_int_op(0, ==, create_cell_format_relayed(&cell, cc));
/* == Now try parsing some junk */
1
0

03 Jan '13
commit f58d4dfcd61aec7ea1900873ca08ecc31d7a7ef7
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Tue Dec 4 21:27:07 2012 -0500
Massive refactoring of the various handshake types
The three handshake types are now accessed from a unified interface;
their state is abstracted from the rest of the cpath state, and so on.
---
src/or/circuitbuild.c | 122 ++++++++++++++-----------
src/or/circuitbuild.h | 3 +-
src/or/circuitlist.c | 7 +-
src/or/command.c | 10 +-
src/or/cpuworker.c | 40 ++++----
src/or/onion.c | 243 ++++++++++++++++++++++++++++++++++++++++++++++++-
src/or/onion.h | 33 +++++++
src/or/onion_ntor.h | 2 +
src/or/onion_tap.c | 26 +++--
src/or/onion_tap.h | 11 ++-
src/or/or.h | 40 ++++++---
src/or/rendclient.c | 14 ++--
src/or/rendservice.c | 8 +-
src/or/router.c | 7 ++
src/or/router.h | 1 +
src/test/bench.c | 16 ++--
src/test/test.c | 14 ++--
17 files changed, 462 insertions(+), 135 deletions(-)
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index b6cf125..8393ba1 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -27,6 +27,7 @@
#include "main.h"
#include "networkstatus.h"
#include "nodelist.h"
+#include "onion.h"
#include "onion_tap.h"
#include "onion_fast.h"
#include "policies.h"
@@ -54,7 +55,9 @@ static channel_t * channel_connect_for_circuit(const tor_addr_t *addr,
uint16_t port,
const char *id_digest);
static int circuit_deliver_create_cell(circuit_t *circ,
- uint8_t cell_type, const char *payload);
+ uint8_t cell_type,
+ const uint8_t *payload,
+ size_t payload_len);
static int onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit);
static crypt_path_t *onion_next_hop_in_cpath(crypt_path_t *cpath);
static int onion_extend_cpath(origin_circuit_t *circ);
@@ -474,7 +477,8 @@ circuit_n_chan_done(channel_t *chan, int status)
/* pull the create cell out of circ->onionskin, and send it */
tor_assert(circ->n_chan_onionskin);
if (circuit_deliver_create_cell(circ,CELL_CREATE,
- circ->n_chan_onionskin)<0) {
+ (const uint8_t*)circ->n_chan_onionskin,
+ circ->n_chan_onionskin_len)<0) {
circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT);
continue;
}
@@ -491,12 +495,12 @@ circuit_n_chan_done(channel_t *chan, int status)
* for the outgoing
* circuit <b>circ</b>, and deliver a cell of type <b>cell_type</b>
* (either CELL_CREATE or CELL_CREATE_FAST) with payload <b>payload</b>
- * to this circuit.
+ * to this circuit. DOCDOC payload_len
* Return -1 if we failed to find a suitable circid, else return 0.
*/
static int
circuit_deliver_create_cell(circuit_t *circ, uint8_t cell_type,
- const char *payload)
+ const uint8_t *payload, size_t payload_len)
{
cell_t cell;
circid_t id;
@@ -518,7 +522,7 @@ circuit_deliver_create_cell(circuit_t *circ, uint8_t cell_type,
cell.command = cell_type;
cell.circ_id = circ->n_circ_id;
- memcpy(cell.payload, payload, ONIONSKIN_CHALLENGE_LEN);
+ memcpy(cell.payload, payload, payload_len);
append_cell_to_circuit_queue(circ, circ->n_chan, &cell,
CELL_DIRECTION_OUT, 0);
@@ -611,8 +615,10 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
{
crypt_path_t *hop;
const node_t *node;
- char payload[2+4+DIGEST_LEN+ONIONSKIN_CHALLENGE_LEN];
- char *onionskin;
+ uint8_t payload[2+4+DIGEST_LEN+MAX_ONIONSKIN_CHALLENGE_LEN];
+ uint8_t *onionskin;
+ uint16_t handshake_type;
+ int onionskin_len;
size_t payload_len;
tor_assert(circ);
@@ -633,30 +639,29 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
* send an old slow create cell.
*/
cell_type = CELL_CREATE;
- if (onion_skin_create(circ->cpath->extend_info->onion_key,
- &(circ->cpath->dh_handshake_state),
- payload) < 0) {
- log_warn(LD_CIRC,"onion_skin_create (first hop) failed.");
- return - END_CIRC_REASON_INTERNAL;
- }
+ handshake_type = ONION_HANDSHAKE_TYPE_TAP;
note_request("cell: create", 1);
} else {
/* We are not an OR, and we're building the first hop of a circuit to a
* new OR: we can be speedy and use CREATE_FAST to save an RSA operation
* and a DH operation. */
cell_type = CELL_CREATE_FAST;
-
- memset(payload, 0, sizeof(payload));
- if (fast_onionskin_create(&circ->cpath->fast_handshake_state,
- (uint8_t *)payload) < 0) {
- log_warn(LD_CIRC,"onion_skin_create FAST (first hop) failed.");
- return - END_CIRC_REASON_INTERNAL;
- }
-
+ handshake_type = ONION_HANDSHAKE_TYPE_FAST;
note_request("cell: create fast", 1);
}
- if (circuit_deliver_create_cell(TO_CIRCUIT(circ), cell_type, payload) < 0)
+ memset(payload, 0, sizeof(payload));
+ onionskin_len = onion_skin_create(handshake_type,
+ circ->cpath->extend_info,
+ &circ->cpath->handshake_state,
+ payload);
+ if (onionskin_len < 0) {
+ log_warn(LD_CIRC,"onion_skin_create (first hop) failed.");
+ return - END_CIRC_REASON_INTERNAL;
+ }
+
+ if (circuit_deliver_create_cell(TO_CIRCUIT(circ), cell_type, payload,
+ onionskin_len) < 0)
return - END_CIRC_REASON_RESOURCELIMIT;
circ->cpath->state = CPATH_STATE_AWAITING_KEYS;
@@ -742,12 +747,16 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
set_uint16(payload+4, htons(hop->extend_info->port));
onionskin = payload+2+4;
- memcpy(payload+2+4+ONIONSKIN_CHALLENGE_LEN,
+ memcpy(payload+2+4+TAP_ONIONSKIN_CHALLENGE_LEN,
hop->extend_info->identity_digest, DIGEST_LEN);
- payload_len = 2+4+ONIONSKIN_CHALLENGE_LEN+DIGEST_LEN;
+ payload_len = 2+4+TAP_ONIONSKIN_CHALLENGE_LEN+DIGEST_LEN;
+
+ handshake_type = ONION_HANDSHAKE_TYPE_TAP;
- if (onion_skin_create(hop->extend_info->onion_key,
- &(hop->dh_handshake_state), onionskin) < 0) {
+ if (onion_skin_create(handshake_type,
+ hop->extend_info,
+ &hop->handshake_state,
+ onionskin) < 0) {
log_warn(LD_CIRC,"onion_skin_create failed.");
return - END_CIRC_REASON_INTERNAL;
}
@@ -758,7 +767,8 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
* it to a create cell and then send to hop */
if (relay_send_command_from_edge(0, TO_CIRCUIT(circ),
RELAY_COMMAND_EXTEND,
- payload, payload_len, hop->prev) < 0)
+ (char*)payload, payload_len,
+ hop->prev) < 0)
return 0; /* circuit is closed */
hop->state = CPATH_STATE_AWAITING_KEYS;
@@ -826,7 +836,7 @@ circuit_extend(cell_t *cell, circuit_t *circ)
relay_header_unpack(&rh, cell->payload);
- if (rh.length < 4+2+ONIONSKIN_CHALLENGE_LEN+DIGEST_LEN) {
+ if (rh.length < 4+2+TAP_ONIONSKIN_CHALLENGE_LEN+DIGEST_LEN) {
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Wrong length %d on extend cell. Closing circuit.",
rh.length);
@@ -837,7 +847,7 @@ circuit_extend(cell_t *cell, circuit_t *circ)
n_port = ntohs(get_uint16(cell->payload+RELAY_HEADER_SIZE+4));
onionskin = (char*) cell->payload+RELAY_HEADER_SIZE+4+2;
id_digest = (char*) cell->payload+RELAY_HEADER_SIZE+4+2+
- ONIONSKIN_CHALLENGE_LEN;
+ TAP_ONIONSKIN_CHALLENGE_LEN;
tor_addr_from_ipv4h(&n_addr, n_addr32);
if (!n_port || !n_addr32) {
@@ -890,8 +900,10 @@ circuit_extend(cell_t *cell, circuit_t *circ)
NULL /*onion_key*/,
&n_addr, n_port);
- circ->n_chan_onionskin = tor_malloc(ONIONSKIN_CHALLENGE_LEN);
- memcpy(circ->n_chan_onionskin, onionskin, ONIONSKIN_CHALLENGE_LEN);
+ circ->n_chan_onionskin = tor_malloc(TAP_ONIONSKIN_CHALLENGE_LEN);
+ memcpy(circ->n_chan_onionskin, onionskin, TAP_ONIONSKIN_CHALLENGE_LEN);
+ circ->n_chan_onionskin_len = TAP_ONIONSKIN_CHALLENGE_LEN;
+
circuit_set_state(circ, CIRCUIT_STATE_CHAN_WAIT);
if (should_launch) {
@@ -917,7 +929,8 @@ circuit_extend(cell_t *cell, circuit_t *circ)
"n_chan is %s",
channel_get_canonical_remote_descr(n_chan));
- if (circuit_deliver_create_cell(circ, CELL_CREATE, onionskin) < 0)
+ if (circuit_deliver_create_cell(circ, CELL_CREATE, (uint8_t*)onionskin,
+ TAP_ONIONSKIN_CHALLENGE_LEN) < 0)
return -1;
return 0;
}
@@ -1377,31 +1390,32 @@ circuit_finish_handshake(origin_circuit_t *circ, uint8_t reply_type,
}
tor_assert(hop->state == CPATH_STATE_AWAITING_KEYS);
- if (reply_type == CELL_CREATED && hop->dh_handshake_state) {
- if (onion_skin_client_handshake(hop->dh_handshake_state, (char*)reply,keys,
- DIGEST_LEN*2+CIPHER_KEY_LEN*2) < 0) {
- log_warn(LD_CIRC,"onion_skin_client_handshake failed.");
+ {
+ uint16_t handshake_type = 0xffff;
+ if (reply_type == CELL_CREATED)
+ handshake_type = ONION_HANDSHAKE_TYPE_TAP;
+ else if (reply_type == CELL_CREATED_FAST)
+ handshake_type = ONION_HANDSHAKE_TYPE_FAST;
+
+ if (handshake_type != hop->handshake_state.tag) {
+ log_warn(LD_PROTOCOL,"CREATED cell onionskin type (%u) did not "
+ "match CREATE cell onionskin type (%u).",
+ (unsigned)handshake_type,
+ (unsigned) hop->handshake_state.tag);
return -END_CIRC_REASON_TORPROTOCOL;
}
- /* Remember hash of g^xy */
- memcpy(hop->handshake_digest, reply+DH_KEY_LEN, DIGEST_LEN);
- } else if (reply_type == CELL_CREATED_FAST && !hop->dh_handshake_state) {
- if (fast_client_handshake(hop->fast_handshake_state, reply,
- (uint8_t*)keys,
- DIGEST_LEN*2+CIPHER_KEY_LEN*2) < 0) {
- log_warn(LD_CIRC,"fast_client_handshake failed.");
+
+ if (onion_skin_client_handshake(handshake_type,
+ &hop->handshake_state,
+ reply,
+ (uint8_t*)keys, sizeof(keys),
+ (uint8_t*)hop->handshake_digest) < 0) {
+ log_warn(LD_CIRC,"onion_skin_client_handshake failed.");
return -END_CIRC_REASON_TORPROTOCOL;
}
- memcpy(hop->handshake_digest, reply+DIGEST_LEN, DIGEST_LEN);
- } else {
- log_warn(LD_PROTOCOL,"CREATED cell type did not match CREATE cell type.");
- return -END_CIRC_REASON_TORPROTOCOL;
}
- crypto_dh_free(hop->dh_handshake_state); /* don't need it anymore */
- hop->dh_handshake_state = NULL;
-
- memset(hop->fast_handshake_state, 0, sizeof(hop->fast_handshake_state));
+ onion_handshake_state_release(&hop->handshake_state);
if (circuit_init_cpath_crypto(hop, keys, 0)<0) {
return -END_CIRC_REASON_TORPROTOCOL;
@@ -1470,7 +1484,7 @@ circuit_truncated(origin_circuit_t *circ, crypt_path_t *layer, int reason)
*/
int
onionskin_answer(or_circuit_t *circ, uint8_t cell_type, const char *payload,
- const char *keys)
+ size_t payload_len, const char *keys)
{
cell_t cell;
crypt_path_t *tmp_cpath;
@@ -1484,8 +1498,7 @@ onionskin_answer(or_circuit_t *circ, uint8_t cell_type, const char *payload,
circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OPEN);
- memcpy(cell.payload, payload,
- cell_type == CELL_CREATED ? ONIONSKIN_REPLY_LEN : DIGEST_LEN*2);
+ memcpy(cell.payload, payload, payload_len);
log_debug(LD_CIRC,"init digest forward 0x%.8x, backward 0x%.8x.",
(unsigned int)get_uint32(keys),
@@ -1502,6 +1515,7 @@ onionskin_answer(or_circuit_t *circ, uint8_t cell_type, const char *payload,
tmp_cpath->magic = 0;
tor_free(tmp_cpath);
+ /* XXXX Move responsibility for extracting this. */
if (cell_type == CELL_CREATED)
memcpy(circ->handshake_digest, cell.payload+DH_KEY_LEN, DIGEST_LEN);
else
diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h
index 78575af..f83cb55 100644
--- a/src/or/circuitbuild.h
+++ b/src/or/circuitbuild.h
@@ -35,7 +35,8 @@ int circuit_finish_handshake(origin_circuit_t *circ, uint8_t cell_type,
int circuit_truncated(origin_circuit_t *circ, crypt_path_t *layer,
int reason);
int onionskin_answer(or_circuit_t *circ, uint8_t cell_type,
- const char *payload, const char *keys);
+ const char *payload, size_t payload_len,
+ const char *keys);
int circuit_all_predicted_ports_handled(time_t now, int *need_uptime,
int *need_capacity);
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index 2c17fd2..2565470 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -744,8 +744,8 @@ circuit_free_cpath_node(crypt_path_t *victim)
crypto_cipher_free(victim->b_crypto);
crypto_digest_free(victim->f_digest);
crypto_digest_free(victim->b_digest);
- crypto_dh_free(victim->dh_handshake_state);
- fast_handshake_state_free(victim->fast_handshake_state);
+ onion_handshake_state_release(&victim->handshake_state);
+ crypto_dh_free(victim->rend_dh_handshake_state);
extend_info_free(victim->extend_info);
memwipe(victim, 0xBB, sizeof(crypt_path_t)); /* poison memory */
@@ -1494,7 +1494,8 @@ assert_cpath_layer_ok(const crypt_path_t *cp)
tor_assert(cp->b_crypto);
/* fall through */
case CPATH_STATE_CLOSED:
- tor_assert(!cp->dh_handshake_state);
+ /*XXXX Assert that there's no handshake_state either. */
+ tor_assert(!cp->rend_dh_handshake_state);
break;
case CPATH_STATE_AWAITING_KEYS:
/* tor_assert(cp->dh_handshake_state); */
diff --git a/src/or/command.c b/src/or/command.c
index 2718ec9..a33a9b1 100644
--- a/src/or/command.c
+++ b/src/or/command.c
@@ -30,6 +30,7 @@
#include "hibernate.h"
#include "nodelist.h"
//#include "onion.h"
+#include "onion_tap.h"
#include "onion_fast.h"
#include "relay.h"
#include "router.h"
@@ -254,8 +255,8 @@ command_process_create_cell(cell_t *cell, channel_t *chan)
circ->base_.purpose = CIRCUIT_PURPOSE_OR;
circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_ONIONSKIN_PENDING);
if (cell->command == CELL_CREATE) {
- char *onionskin = tor_malloc(ONIONSKIN_CHALLENGE_LEN);
- memcpy(onionskin, cell->payload, ONIONSKIN_CHALLENGE_LEN);
+ char *onionskin = tor_malloc(TAP_ONIONSKIN_CHALLENGE_LEN);
+ memcpy(onionskin, cell->payload, TAP_ONIONSKIN_CHALLENGE_LEN);
/* hand it off to the cpuworkers, and then return. */
if (assign_onionskin_to_cpuworker(NULL, circ, onionskin) < 0) {
@@ -282,7 +283,8 @@ command_process_create_cell(cell_t *cell, channel_t *chan)
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
return;
}
- if (onionskin_answer(circ, CELL_CREATED_FAST, reply, keys)<0) {
+ if (onionskin_answer(circ, CELL_CREATED_FAST, reply, sizeof(reply),
+ keys)<0) {
log_warn(LD_OR,"Failed to reply to CREATE_FAST cell. Closing.");
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
return;
@@ -340,7 +342,7 @@ command_process_created_cell(cell_t *cell, channel_t *chan)
log_debug(LD_OR,
"Converting created cell to extended relay cell, sending.");
relay_send_command_from_edge(0, circ, RELAY_COMMAND_EXTENDED,
- (char*)cell->payload, ONIONSKIN_REPLY_LEN,
+ (char*)cell->payload, TAP_ONIONSKIN_REPLY_LEN,
NULL);
}
}
diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c
index 3a3d687..e8087c2 100644
--- a/src/or/cpuworker.c
+++ b/src/or/cpuworker.c
@@ -35,7 +35,7 @@
#define TAG_LEN 10
/** How many bytes are sent from the cpuworker back to tor? */
#define LEN_ONION_RESPONSE \
- (1+TAG_LEN+ONIONSKIN_REPLY_LEN+CPATH_KEY_MATERIAL_LEN)
+ (1+TAG_LEN+TAP_ONIONSKIN_REPLY_LEN+CPATH_KEY_MATERIAL_LEN)
/** How many cpuworkers we have running right now. */
static int num_cpuworkers=0;
@@ -185,7 +185,8 @@ connection_cpu_process_inbuf(connection_t *conn)
}
tor_assert(! CIRCUIT_IS_ORIGIN(circ));
if (onionskin_answer(TO_OR_CIRCUIT(circ), CELL_CREATED, buf+TAG_LEN,
- buf+TAG_LEN+ONIONSKIN_REPLY_LEN) < 0) {
+ TAP_ONIONSKIN_REPLY_LEN,
+ buf+TAG_LEN+TAP_ONIONSKIN_REPLY_LEN) < 0) {
log_warn(LD_OR,"onionskin_answer failed. Closing.");
circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
goto done_processing;
@@ -214,11 +215,11 @@ connection_cpu_process_inbuf(connection_t *conn)
* Request format:
* Task type [1 byte, always CPUWORKER_TASK_ONION]
* Opaque tag TAG_LEN
- * Onionskin challenge ONIONSKIN_CHALLENGE_LEN
+ * Onionskin challenge TAP_ONIONSKIN_CHALLENGE_LEN
* Response format:
* Success/failure [1 byte, boolean.]
* Opaque tag TAG_LEN
- * Onionskin challenge ONIONSKIN_REPLY_LEN
+ * Onionskin challenge TAP_ONIONSKIN_REPLY_LEN
* Negotiated keys KEY_LEN*2+DIGEST_LEN*2
*
* (Note: this _should_ be by addr/port, since we're concerned with specific
@@ -227,17 +228,17 @@ connection_cpu_process_inbuf(connection_t *conn)
static void
cpuworker_main(void *data)
{
- char question[ONIONSKIN_CHALLENGE_LEN];
+ char question[TAP_ONIONSKIN_CHALLENGE_LEN];
uint8_t question_type;
tor_socket_t *fdarray = data;
tor_socket_t fd;
/* variables for onion processing */
char keys[CPATH_KEY_MATERIAL_LEN];
- char reply_to_proxy[ONIONSKIN_REPLY_LEN];
+ char reply_to_proxy[MAX_ONIONSKIN_REPLY_LEN];
char buf[LEN_ONION_RESPONSE];
char tag[TAG_LEN];
- crypto_pk_t *onion_key = NULL, *last_onion_key = NULL;
+ server_onion_keys_t onion_keys;
fd = fdarray[1]; /* this side is ours */
#ifndef TOR_IS_MULTITHREADED
@@ -248,7 +249,7 @@ cpuworker_main(void *data)
#endif
tor_free(data);
- dup_onion_keys(&onion_key, &last_onion_key);
+ setup_server_onion_keys(&onion_keys);
for (;;) {
ssize_t r;
@@ -275,15 +276,18 @@ cpuworker_main(void *data)
goto end;
}
- if (read_all(fd, question, ONIONSKIN_CHALLENGE_LEN, 1) !=
- ONIONSKIN_CHALLENGE_LEN) {
+ if (read_all(fd, question, TAP_ONIONSKIN_CHALLENGE_LEN, 1) !=
+ TAP_ONIONSKIN_CHALLENGE_LEN) {
log_err(LD_BUG,"read question failed. Exiting.");
goto end;
}
if (question_type == CPUWORKER_TASK_ONION) {
- if (onion_skin_server_handshake(question, onion_key, last_onion_key,
- reply_to_proxy, keys, CPATH_KEY_MATERIAL_LEN) < 0) {
+ if (onion_skin_server_handshake(ONION_HANDSHAKE_TYPE_TAP,
+ (const uint8_t*)question,
+ &onion_keys,
+ (uint8_t*)reply_to_proxy,
+ (uint8_t*)keys, CPATH_KEY_MATERIAL_LEN) < 0) {
/* failure */
log_debug(LD_OR,"onion_skin_server_handshake failed.");
*buf = 0; /* indicate failure in first byte */
@@ -295,8 +299,9 @@ cpuworker_main(void *data)
log_debug(LD_OR,"onion_skin_server_handshake succeeded.");
buf[0] = 1; /* 1 means success */
memcpy(buf+1,tag,TAG_LEN);
- memcpy(buf+1+TAG_LEN,reply_to_proxy,ONIONSKIN_REPLY_LEN);
- memcpy(buf+1+TAG_LEN+ONIONSKIN_REPLY_LEN,keys,CPATH_KEY_MATERIAL_LEN);
+ memcpy(buf+1+TAG_LEN,reply_to_proxy,TAP_ONIONSKIN_REPLY_LEN);
+ memcpy(buf+1+TAG_LEN+TAP_ONIONSKIN_REPLY_LEN,keys,
+ CPATH_KEY_MATERIAL_LEN);
}
if (write_all(fd, buf, LEN_ONION_RESPONSE, 1) != LEN_ONION_RESPONSE) {
log_err(LD_BUG,"writing response buf failed. Exiting.");
@@ -306,10 +311,7 @@ cpuworker_main(void *data)
}
}
end:
- if (onion_key)
- crypto_pk_free(onion_key);
- if (last_onion_key)
- crypto_pk_free(last_onion_key);
+ release_server_onion_keys(&onion_keys);
tor_close_socket(fd);
crypto_thread_cleanup();
spawn_exit();
@@ -497,7 +499,7 @@ assign_onionskin_to_cpuworker(connection_t *cpuworker,
qbuf[0] = CPUWORKER_TASK_ONION;
connection_write_to_buf(qbuf, 1, cpuworker);
connection_write_to_buf(tag, sizeof(tag), cpuworker);
- connection_write_to_buf(onionskin, ONIONSKIN_CHALLENGE_LEN, cpuworker);
+ connection_write_to_buf(onionskin, TAP_ONIONSKIN_CHALLENGE_LEN, cpuworker);
tor_free(onionskin);
}
return 0;
diff --git a/src/or/onion.c b/src/or/onion.c
index f468ada..90fc830 100644
--- a/src/or/onion.c
+++ b/src/or/onion.c
@@ -6,15 +6,19 @@
/**
* \file onion.c
- * \brief Functions to queue create cells, and handle onionskin
- * parsing and creation.
+ * \brief Functions to queue create cells, handle onionskin
+ * parsing and creation, and wrap the various onionskin types.
**/
#include "or.h"
#include "circuitlist.h"
#include "config.h"
#include "onion.h"
+#include "onion_fast.h"
+#include "onion_ntor.h"
+#include "onion_tap.h"
#include "rephist.h"
+#include "router.h"
/** Type for a linked list of circuits that are waiting for a free CPU worker
* to process a waiting onion handshake. */
@@ -37,6 +41,8 @@ static onion_queue_t *ol_tail=NULL;
/** Length of ol_list */
static int ol_length=0;
+/* XXXX Check lengths vs MAX_ONIONSKIN_{CHALLENGE,REPLY}_LEN */
+
/** Add <b>circ</b> to the end of ol_list and return 0, except
* if ol_list is too long, in which case do nothing and return -1.
*/
@@ -171,3 +177,236 @@ clear_pending_onions(void)
ol_length = 0;
}
+/* ============================================================ */
+
+/** Fill in a server_onion_keys_t object at <b>keys</b> with all of the keys
+ * and other info we might need to do onion handshakes. (We make a copy of
+ * our keys for each cpuworker to avoid race conditions with the main thread,
+ * and to avoid locking) */
+void
+setup_server_onion_keys(server_onion_keys_t *keys)
+{
+ memset(keys, 0, sizeof(server_onion_keys_t));
+ memcpy(keys->my_identity, router_get_my_id_digest(), DIGEST_LEN);
+ dup_onion_keys(&keys->onion_key, &keys->last_onion_key);
+#ifdef CURVE25519_ENABLED
+ keys->curve25519_key_map = construct_ntor_key_map();
+#endif
+}
+
+/** Release all storage held in <b>keys</b>, but do not free <b>keys</b>
+ * itself (as it's likely to be stack-allocated.) */
+void
+release_server_onion_keys(server_onion_keys_t *keys)
+{
+ if (! keys)
+ return;
+
+ crypto_pk_free(keys->onion_key);
+ crypto_pk_free(keys->last_onion_key);
+#ifdef CURVE25519_ENABLED
+ ntor_key_map_free(keys->curve25519_key_map);
+#endif
+ memset(keys, 0, sizeof(server_onion_keys_t));
+}
+
+/** Release whatever storage is held in <b>state</b>, depending on its
+ * type, and clear its pointer. */
+void
+onion_handshake_state_release(onion_handshake_state_t *state)
+{
+ switch (state->tag) {
+ case ONION_HANDSHAKE_TYPE_TAP:
+ crypto_dh_free(state->u.tap);
+ state->u.tap = NULL;
+ break;
+ case ONION_HANDSHAKE_TYPE_FAST:
+ fast_handshake_state_free(state->u.fast);
+ state->u.fast = NULL;
+ break;
+#ifdef CURVE25519_ENABLED
+ case ONION_HANDSHAKE_TYPE_NTOR:
+ ntor_handshake_state_free(state->u.ntor);
+ state->u.ntor = NULL;
+ break;
+#endif
+ default:
+ log_warn(LD_BUG, "called with unknown handshake state type %d",
+ (int)state->tag);
+ tor_fragile_assert();
+ }
+}
+
+/** Perform the first step of a circuit-creation handshake of type <b>type</b>
+ * (one of ONION_HANDSHAKE_TYPE_*): generate the initial "onion skin" in
+ * <b>onion_skin_out</b>, and store any state information in <b>state_out</b>.
+ * Return -1 on failure, and the length of the onionskin on acceptance.
+ */
+int
+onion_skin_create(int type,
+ const extend_info_t *node,
+ onion_handshake_state_t *state_out,
+ uint8_t *onion_skin_out)
+{
+ int r = -1;
+
+ switch (type) {
+ case ONION_HANDSHAKE_TYPE_TAP:
+ if (!node->onion_key)
+ return -1;
+
+ if (onion_skin_TAP_create(node->onion_key,
+ &state_out->u.tap,
+ (char*)onion_skin_out) < 0)
+ return -1;
+
+ r = TAP_ONIONSKIN_CHALLENGE_LEN;
+ break;
+ case ONION_HANDSHAKE_TYPE_FAST:
+ if (fast_onionskin_create(&state_out->u.fast, onion_skin_out) < 0)
+ return -1;
+
+ r = CREATE_FAST_LEN;
+ break;
+ case ONION_HANDSHAKE_TYPE_NTOR:
+#ifdef CURVE25519_ENABLED
+ if (tor_mem_is_zero((const char*)node->curve25519_onion_key.public_key,
+ CURVE25519_PUBKEY_LEN))
+ return -1;
+ if (onion_skin_ntor_create((const uint8_t*)node->identity_digest,
+ &node->curve25519_onion_key,
+ &state_out->u.ntor,
+ onion_skin_out) < 0)
+ return -1;
+
+ r = NTOR_ONIONSKIN_LEN;
+#else
+ return -1;
+#endif
+ break;
+ default:
+ log_warn(LD_BUG, "called with unknown handshake state type %d", type);
+ tor_fragile_assert();
+ r = -1;
+ }
+
+ if (r > 0)
+ state_out->tag = (uint16_t) type;
+
+ return r;
+}
+
+/** Perform the second (server-side) step of a circuit-creation handshake of
+ * type <b>type</b>, responding to the client request in <b>onion_skin</b>
+ * using the keys in <b>keys</b>. On success, write our response into
+ * <b>reply_out</b>, generate <b>keys_out_len</b> bytes worth of key material
+ * in <b>keys_out_len</b>, and return the length of the reply. On failure,
+ * return -1. */
+int
+onion_skin_server_handshake(int type,
+ const uint8_t *onion_skin,
+ const server_onion_keys_t *keys,
+ uint8_t *reply_out,
+ uint8_t *keys_out, size_t keys_out_len)
+{
+ int r = -1;
+
+ switch (type) {
+ case ONION_HANDSHAKE_TYPE_TAP:
+ if (onion_skin_TAP_server_handshake((const char*)onion_skin,
+ keys->onion_key, keys->last_onion_key,
+ (char*)reply_out,
+ (char*)keys_out, keys_out_len)<0)
+ return -1;
+ r = TAP_ONIONSKIN_REPLY_LEN;
+ break;
+ case ONION_HANDSHAKE_TYPE_FAST:
+ if (fast_server_handshake(onion_skin, reply_out, keys_out, keys_out_len)<0)
+ return -1;
+ r = CREATED_FAST_LEN;
+ break;
+ case ONION_HANDSHAKE_TYPE_NTOR:
+#ifdef CURVE25519_ENABLED
+ if (onion_skin_ntor_server_handshake(onion_skin, keys->curve25519_key_map,
+ keys->my_identity,
+ reply_out, keys_out, keys_out_len)<0)
+ return -1;
+ r = NTOR_REPLY_LEN;
+#else
+ return -1;
+#endif
+ break;
+ default:
+ log_warn(LD_BUG, "called with unknown handshake state type %d", type);
+ tor_fragile_assert();
+ return -1;
+ }
+
+ /* XXXX we should generate the rendezvous nonce stuff too. Some notes
+ * below */
+ // memcpy(hop->handshake_digest, reply+DH_KEY_LEN, DIGEST_LEN);
+
+ //memcpy(hop->handshake_digest, reply+DIGEST_LEN, DIGEST_LEN);
+
+ return r;
+}
+
+/** Perform the final (client-side) step of a circuit-creation handshake of
+ * type <b>type</b>, using our state in <b>handshake_state</b> and the
+ * server's response in <b>reply</b> On success, generate <b>keys_out_len</b>
+ * bytes worth of key material in <b>keys_out_len</b>, set
+ * <b>rend_authenticator_out</b> to the "KH" field that can be used to
+ * establish introduction points at this hop, and return 0. On failure,
+ * return -1. */
+int
+onion_skin_client_handshake(int type,
+ const onion_handshake_state_t *handshake_state,
+ const uint8_t *reply,
+ uint8_t *keys_out, size_t keys_out_len,
+ uint8_t *rend_authenticator_out)
+{
+ if (handshake_state->tag != type)
+ return -1;
+
+ switch (type) {
+ case ONION_HANDSHAKE_TYPE_TAP:
+ if (onion_skin_TAP_client_handshake(handshake_state->u.tap,
+ (const char*)reply,
+ (char *)keys_out, keys_out_len) < 0)
+ return -1;
+
+ memcpy(rend_authenticator_out, reply+DH_KEY_LEN, DIGEST_LEN);
+
+ return 0;
+ case ONION_HANDSHAKE_TYPE_FAST:
+ if (fast_client_handshake(handshake_state->u.fast, reply,
+ keys_out, keys_out_len) < 0)
+ return -1;
+
+ memcpy(rend_authenticator_out, reply+DIGEST_LEN, DIGEST_LEN);
+ return 0;
+#ifdef CURVE25519_ENABLED
+ case ONION_HANDSHAKE_TYPE_NTOR:
+ {
+ size_t keys_tmp_len = keys_out_len + DIGEST_LEN;
+ uint8_t *keys_tmp = tor_malloc(keys_tmp_len);
+ if (onion_skin_ntor_client_handshake(handshake_state->u.ntor,
+ reply,
+ keys_tmp, keys_tmp_len) < 0) {
+ tor_free(keys_tmp);
+ return -1;
+ }
+ memcpy(keys_out, keys_tmp, keys_out_len);
+ memcpy(rend_authenticator_out, keys_tmp + keys_out_len, DIGEST_LEN);
+ memwipe(keys_tmp, 0, keys_tmp_len);
+ tor_free(keys_tmp);
+ }
+ return 0;
+#endif
+ default:
+ log_warn(LD_BUG, "called with unknown handshake state type %d", type);
+ tor_fragile_assert();
+ return -1;
+ }
+}
+
diff --git a/src/or/onion.h b/src/or/onion.h
index 55ea3f9..3c12e1f 100644
--- a/src/or/onion.h
+++ b/src/or/onion.h
@@ -17,5 +17,38 @@ or_circuit_t *onion_next_task(char **onionskin_out);
void onion_pending_remove(or_circuit_t *circ);
void clear_pending_onions(void);
+typedef struct server_onion_keys_t {
+ uint8_t my_identity[DIGEST_LEN];
+ crypto_pk_t *onion_key;
+ crypto_pk_t *last_onion_key;
+#ifdef CURVE25519_ENABLED
+ di_digest256_map_t *curve25519_key_map;
+#endif
+} server_onion_keys_t;
+
+#define MAX_ONIONSKIN_CHALLENGE_LEN 255
+#define MAX_ONIONSKIN_REPLY_LEN 255
+
+void setup_server_onion_keys(server_onion_keys_t *keys);
+void release_server_onion_keys(server_onion_keys_t *keys);
+
+void onion_handshake_state_release(onion_handshake_state_t *state);
+
+int onion_skin_create(int type,
+ const extend_info_t *node,
+ onion_handshake_state_t *state_out,
+ uint8_t *onion_skin_out);
+int onion_skin_server_handshake(int type,
+ const uint8_t *onion_skin,
+ const server_onion_keys_t *keys,
+ uint8_t *reply_out,
+ uint8_t *keys_out, size_t key_out_len);
+// uint8_t *rend_authenticator_out);
+int onion_skin_client_handshake(int type,
+ const onion_handshake_state_t *handshake_state,
+ const uint8_t *reply,
+ uint8_t *keys_out, size_t key_out_len,
+ uint8_t *rend_authenticator_out);
+
#endif
diff --git a/src/or/onion_ntor.h b/src/or/onion_ntor.h
index 4f305a4..80015fd 100644
--- a/src/or/onion_ntor.h
+++ b/src/or/onion_ntor.h
@@ -17,6 +17,7 @@ typedef struct ntor_handshake_state_t ntor_handshake_state_t;
/** Length of an ntor reply, as sent from server to client. */
#define NTOR_REPLY_LEN 64
+#ifdef CURVE25519_ENABLED
void ntor_handshake_state_free(ntor_handshake_state_t *state);
int onion_skin_ntor_create(const uint8_t *router_id,
@@ -36,6 +37,7 @@ int onion_skin_ntor_client_handshake(
const uint8_t *handshake_reply,
uint8_t *key_out,
size_t key_out_len);
+#endif
#endif
diff --git a/src/or/onion_tap.c b/src/or/onion_tap.c
index 464b845..0ec526c 100644
--- a/src/or/onion_tap.c
+++ b/src/or/onion_tap.c
@@ -35,9 +35,9 @@
* The meeting point/cookies and auth are zeroed out for now.
*/
int
-onion_skin_create(crypto_pk_t *dest_router_key,
+onion_skin_TAP_create(crypto_pk_t *dest_router_key,
crypto_dh_t **handshake_state_out,
- char *onion_skin_out) /* ONIONSKIN_CHALLENGE_LEN bytes */
+ char *onion_skin_out) /* TAP_ONIONSKIN_CHALLENGE_LEN bytes */
{
char challenge[DH_KEY_LEN];
crypto_dh_t *dh = NULL;
@@ -47,7 +47,7 @@ onion_skin_create(crypto_pk_t *dest_router_key,
tor_assert(handshake_state_out);
tor_assert(onion_skin_out);
*handshake_state_out = NULL;
- memset(onion_skin_out, 0, ONIONSKIN_CHALLENGE_LEN);
+ memset(onion_skin_out, 0, TAP_ONIONSKIN_CHALLENGE_LEN);
if (!(dh = crypto_dh_new(DH_TYPE_CIRCUIT)))
goto err;
@@ -64,7 +64,7 @@ onion_skin_create(crypto_pk_t *dest_router_key,
/* set meeting point, meeting cookie, etc here. Leave zero for now. */
if (crypto_pk_public_hybrid_encrypt(dest_router_key, onion_skin_out,
- ONIONSKIN_CHALLENGE_LEN,
+ TAP_ONIONSKIN_CHALLENGE_LEN,
challenge, DH_KEY_LEN,
PK_PKCS1_OAEP_PADDING, 1)<0)
goto err;
@@ -85,14 +85,17 @@ onion_skin_create(crypto_pk_t *dest_router_key,
* next key_out_len bytes of key material in key_out.
*/
int
-onion_skin_server_handshake(const char *onion_skin, /*ONIONSKIN_CHALLENGE_LEN*/
+onion_skin_TAP_server_handshake(
+ /*TAP_ONIONSKIN_CHALLENGE_LEN*/
+ const char *onion_skin,
crypto_pk_t *private_key,
crypto_pk_t *prev_private_key,
- char *handshake_reply_out, /*ONIONSKIN_REPLY_LEN*/
+ /*TAP_ONIONSKIN_REPLY_LEN*/
+ char *handshake_reply_out,
char *key_out,
size_t key_out_len)
{
- char challenge[ONIONSKIN_CHALLENGE_LEN];
+ char challenge[TAP_ONIONSKIN_CHALLENGE_LEN];
crypto_dh_t *dh = NULL;
ssize_t len;
char *key_material=NULL;
@@ -107,8 +110,9 @@ onion_skin_server_handshake(const char *onion_skin, /*ONIONSKIN_CHALLENGE_LEN*/
break;
note_crypto_pk_op(DEC_ONIONSKIN);
len = crypto_pk_private_hybrid_decrypt(k, challenge,
- ONIONSKIN_CHALLENGE_LEN,
- onion_skin, ONIONSKIN_CHALLENGE_LEN,
+ TAP_ONIONSKIN_CHALLENGE_LEN,
+ onion_skin,
+ TAP_ONIONSKIN_CHALLENGE_LEN,
PK_PKCS1_OAEP_PADDING,0);
if (len>0)
break;
@@ -175,8 +179,8 @@ onion_skin_server_handshake(const char *onion_skin, /*ONIONSKIN_CHALLENGE_LEN*/
* After the invocation, call crypto_dh_free on handshake_state.
*/
int
-onion_skin_client_handshake(crypto_dh_t *handshake_state,
- const char *handshake_reply, /* ONIONSKIN_REPLY_LEN bytes */
+onion_skin_TAP_client_handshake(crypto_dh_t *handshake_state,
+ const char *handshake_reply, /* TAP_ONIONSKIN_REPLY_LEN bytes */
char *key_out,
size_t key_out_len)
{
diff --git a/src/or/onion_tap.h b/src/or/onion_tap.h
index 3bd90c9..deae1bf 100644
--- a/src/or/onion_tap.h
+++ b/src/or/onion_tap.h
@@ -12,18 +12,23 @@
#ifndef TOR_ONION_TAP_H
#define TOR_ONION_TAP_H
-int onion_skin_create(crypto_pk_t *router_key,
+#define TAP_ONIONSKIN_CHALLENGE_LEN (PKCS1_OAEP_PADDING_OVERHEAD+\
+ CIPHER_KEY_LEN+\
+ DH_KEY_LEN)
+#define TAP_ONIONSKIN_REPLY_LEN (DH_KEY_LEN+DIGEST_LEN)
+
+int onion_skin_TAP_create(crypto_pk_t *router_key,
crypto_dh_t **handshake_state_out,
char *onion_skin_out);
-int onion_skin_server_handshake(const char *onion_skin,
+int onion_skin_TAP_server_handshake(const char *onion_skin,
crypto_pk_t *private_key,
crypto_pk_t *prev_private_key,
char *handshake_reply_out,
char *key_out,
size_t key_out_len);
-int onion_skin_client_handshake(crypto_dh_t *handshake_state,
+int onion_skin_TAP_client_handshake(crypto_dh_t *handshake_state,
const char *handshake_reply,
char *key_out,
size_t key_out_len);
diff --git a/src/or/or.h b/src/or/or.h
index 6fada77..f7407a8 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -1381,6 +1381,7 @@ typedef struct or_connection_t {
or_handshake_state_t *handshake_state; /**< If we are setting this connection
* up, state information to do so. */
+
time_t timestamp_lastempty; /**< When was the outbuf last completely empty?*/
time_t timestamp_last_added_nonpadding; /** When did we last add a
* non-padding cell to the outbuf? */
@@ -2470,6 +2471,9 @@ typedef struct extend_info_t {
uint16_t port; /**< OR port. */
tor_addr_t addr; /**< IP address. */
crypto_pk_t *onion_key; /**< Current onionskin key. */
+#ifdef CURVE25519_ENABLED
+ curve25519_public_key_t curve25519_onion_key;
+#endif
} extend_info_t;
/** Certificate for v3 directory protocol: binds long-term authority identity
@@ -2525,6 +2529,19 @@ typedef enum {
#define CRYPT_PATH_MAGIC 0x70127012u
struct fast_handshake_state_t;
+struct ntor_handshake_state_t;
+#define ONION_HANDSHAKE_TYPE_TAP 0x0000
+#define ONION_HANDSHAKE_TYPE_FAST 0x0001
+#define ONION_HANDSHAKE_TYPE_NTOR 0x0002
+typedef struct {
+ uint16_t tag;
+ union {
+ struct fast_handshake_state_t *fast;
+ crypto_dh_t *tap;
+ struct ntor_handshake_state_t *ntor;
+ } u;
+} onion_handshake_state_t;
+
/** Holds accounting information for a single step in the layered encryption
* performed by a circuit. Used only at the client edge of a circuit. */
typedef struct crypt_path_t {
@@ -2543,16 +2560,15 @@ typedef struct crypt_path_t {
/** Digest state for cells heading away from the OR at this step. */
crypto_digest_t *b_digest;
- /** Current state of Diffie-Hellman key negotiation with the OR at this
+ /** Current state of the handshake as performed with the OR at this
* step. */
- crypto_dh_t *dh_handshake_state;
- /** Current state of 'fast' (non-PK) key negotiation with the OR at this
- * step. Used to save CPU when TLS is already providing all the
- * authentication, secrecy, and integrity we need, and we're already
- * distinguishable from an OR.
- */
- struct fast_handshake_state_t *fast_handshake_state;
+ onion_handshake_state_t handshake_state;
+ /** Diffie-hellman handshake state for performing an introduction
+ * operations */
+ crypto_dh_t *rend_dh_handshake_state;
+
/** Negotiated key material shared with the OR at this step. */
+ /* XXXX RENAME */
char handshake_digest[DIGEST_LEN];/* KH in tor-spec.txt */
/** Information to extend to the OR at this step. */
@@ -2594,10 +2610,6 @@ typedef struct {
#define CPATH_KEY_MATERIAL_LEN (20*2+16*2)
#define DH_KEY_LEN DH_BYTES
-#define ONIONSKIN_CHALLENGE_LEN (PKCS1_OAEP_PADDING_OVERHEAD+\
- CIPHER_KEY_LEN+\
- DH_KEY_LEN)
-#define ONIONSKIN_REPLY_LEN (DH_KEY_LEN+DIGEST_LEN)
/** Information used to build a circuit. */
typedef struct {
@@ -2703,9 +2715,10 @@ typedef struct circuit_t {
* more. */
int deliver_window;
+ uint8_t n_chan_onionskin_len; /* XXXX MAKE THIS GET USED. */
/** For storage while n_chan is pending
* (state CIRCUIT_STATE_CHAN_WAIT). When defined, it is always
- * length ONIONSKIN_CHALLENGE_LEN. */
+ * length n_chan_onionskin_len */
char *n_chan_onionskin;
/** When was this circuit created? We keep this timestamp with a higher
@@ -2965,6 +2978,7 @@ typedef struct or_circuit_t {
char rend_token[REND_TOKEN_LEN];
/* ???? move to a subtype or adjunct structure? Wastes 20 bytes -NM */
+ /* XXXX rename this. */
char handshake_digest[DIGEST_LEN]; /**< Stores KH for the handshake. */
/** How many more relay_early cells can we send on this circuit, according
diff --git a/src/or/rendclient.c b/src/or/rendclient.c
index 3fb4025..61fb3aa 100644
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@ -206,12 +206,12 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
cpath = rendcirc->build_state->pending_final_cpath =
tor_malloc_zero(sizeof(crypt_path_t));
cpath->magic = CRYPT_PATH_MAGIC;
- if (!(cpath->dh_handshake_state = crypto_dh_new(DH_TYPE_REND))) {
+ if (!(cpath->rend_dh_handshake_state = crypto_dh_new(DH_TYPE_REND))) {
log_warn(LD_BUG, "Internal error: couldn't allocate DH.");
status = -2;
goto perm_err;
}
- if (crypto_dh_generate_public(cpath->dh_handshake_state)<0) {
+ if (crypto_dh_generate_public(cpath->rend_dh_handshake_state)<0) {
log_warn(LD_BUG, "Internal error: couldn't generate g^x.");
status = -2;
goto perm_err;
@@ -261,7 +261,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
dh_offset = MAX_NICKNAME_LEN+1+REND_COOKIE_LEN;
}
- if (crypto_dh_get_public(cpath->dh_handshake_state, tmp+dh_offset,
+ if (crypto_dh_get_public(cpath->rend_dh_handshake_state, tmp+dh_offset,
DH_KEY_LEN)<0) {
log_warn(LD_BUG, "Internal error: couldn't extract g^x.");
status = -2;
@@ -896,9 +896,9 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const uint8_t *request,
tor_assert(circ->build_state);
tor_assert(circ->build_state->pending_final_cpath);
hop = circ->build_state->pending_final_cpath;
- tor_assert(hop->dh_handshake_state);
+ tor_assert(hop->rend_dh_handshake_state);
if (crypto_dh_compute_secret(LOG_PROTOCOL_WARN,
- hop->dh_handshake_state, (char*)request,
+ hop->rend_dh_handshake_state, (char*)request,
DH_KEY_LEN,
keys, DIGEST_LEN+CPATH_KEY_MATERIAL_LEN)<0) {
log_warn(LD_GENERAL, "Couldn't complete DH handshake.");
@@ -914,8 +914,8 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const uint8_t *request,
goto err;
}
- crypto_dh_free(hop->dh_handshake_state);
- hop->dh_handshake_state = NULL;
+ crypto_dh_free(hop->rend_dh_handshake_state);
+ hop->rend_dh_handshake_state = NULL;
/* All is well. Extend the circuit. */
circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_C_REND_JOINED);
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index 09792bd..08a7feb 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -1378,7 +1378,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
cpath->magic = CRYPT_PATH_MAGIC;
launched->build_state->expiry_time = now + MAX_REND_TIMEOUT;
- cpath->dh_handshake_state = dh;
+ cpath->rend_dh_handshake_state = dh;
dh = NULL;
if (circuit_init_cpath_crypto(cpath,keys+DIGEST_LEN,1)<0)
goto err;
@@ -2624,7 +2624,7 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit)
/* All we need to do is send a RELAY_RENDEZVOUS1 cell... */
memcpy(buf, circuit->rend_data->rend_cookie, REND_COOKIE_LEN);
- if (crypto_dh_get_public(hop->dh_handshake_state,
+ if (crypto_dh_get_public(hop->rend_dh_handshake_state,
buf+REND_COOKIE_LEN, DH_KEY_LEN)<0) {
log_warn(LD_GENERAL,"Couldn't get DH public key.");
reason = END_CIRC_REASON_INTERNAL;
@@ -2643,8 +2643,8 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit)
goto err;
}
- crypto_dh_free(hop->dh_handshake_state);
- hop->dh_handshake_state = NULL;
+ crypto_dh_free(hop->rend_dh_handshake_state);
+ hop->rend_dh_handshake_state = NULL;
/* Append the cpath entry. */
hop->state = CPATH_STATE_OPEN;
diff --git a/src/or/router.c b/src/or/router.c
index 954304d..3733bec 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -1598,6 +1598,13 @@ router_digest_is_me(const char *digest)
tor_memeq(server_identitykey_digest, digest, DIGEST_LEN));
}
+/** DOCDOC */
+const uint8_t *
+router_get_my_id_digest(void)
+{
+ return (const uint8_t *)server_identitykey_digest;
+}
+
/** Return true iff I'm a server and <b>digest</b> is equal to
* my identity digest. */
int
diff --git a/src/or/router.h b/src/or/router.h
index 85c7d35..ea0b2ab 100644
--- a/src/or/router.h
+++ b/src/or/router.h
@@ -84,6 +84,7 @@ extrainfo_t *router_get_my_extrainfo(void);
const char *router_get_my_descriptor(void);
const char *router_get_descriptor_gen_reason(void);
int router_digest_is_me(const char *digest);
+const uint8_t *router_get_my_id_digest(void);
int router_extrainfo_digest_is_me(const char *digest);
int router_is_me(const routerinfo_t *router);
int router_fingerprint_is_me(const char *fp);
diff --git a/src/test/bench.c b/src/test/bench.c
index 567b1a4..23560cd 100644
--- a/src/test/bench.c
+++ b/src/test/bench.c
@@ -110,8 +110,8 @@ bench_onion_TAP(void)
int i;
crypto_pk_t *key, *key2;
uint64_t start, end;
- char os[ONIONSKIN_CHALLENGE_LEN];
- char or[ONIONSKIN_REPLY_LEN];
+ char os[TAP_ONIONSKIN_CHALLENGE_LEN];
+ char or[TAP_ONIONSKIN_REPLY_LEN];
crypto_dh_t *dh_out;
key = crypto_pk_new();
@@ -122,17 +122,18 @@ bench_onion_TAP(void)
reset_perftime();
start = perftime();
for (i = 0; i < iters; ++i) {
- onion_skin_create(key, &dh_out, os);
+ onion_skin_TAP_create(key, &dh_out, os);
crypto_dh_free(dh_out);
}
end = perftime();
printf("Client-side, part 1: %f usec.\n", NANOCOUNT(start, end, iters)/1e3);
- onion_skin_create(key, &dh_out, os);
+ onion_skin_TAP_create(key, &dh_out, os);
start = perftime();
for (i = 0; i < iters; ++i) {
char key_out[CPATH_KEY_MATERIAL_LEN];
- onion_skin_server_handshake(os, key, NULL, or, key_out, sizeof(key_out));
+ onion_skin_TAP_server_handshake(os, key, NULL, or,
+ key_out, sizeof(key_out));
}
end = perftime();
printf("Server-side, key guessed right: %f usec\n",
@@ -141,7 +142,8 @@ bench_onion_TAP(void)
start = perftime();
for (i = 0; i < iters; ++i) {
char key_out[CPATH_KEY_MATERIAL_LEN];
- onion_skin_server_handshake(os, key2, key, or, key_out, sizeof(key_out));
+ onion_skin_TAP_server_handshake(os, key2, key, or,
+ key_out, sizeof(key_out));
}
end = perftime();
printf("Server-side, key guessed wrong: %f usec.\n",
@@ -153,7 +155,7 @@ bench_onion_TAP(void)
char key_out[CPATH_KEY_MATERIAL_LEN];
int s;
dh = crypto_dh_dup(dh_out);
- s = onion_skin_client_handshake(dh, or, key_out, sizeof(key_out));
+ s = onion_skin_TAP_client_handshake(dh, or, key_out, sizeof(key_out));
tor_assert(s == 0);
}
end = perftime();
diff --git a/src/test/test.c b/src/test/test.c
index cc2d481..daac67e 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -819,11 +819,11 @@ test_onion_handshake(void)
{
/* client-side */
crypto_dh_t *c_dh = NULL;
- char c_buf[ONIONSKIN_CHALLENGE_LEN];
+ char c_buf[TAP_ONIONSKIN_CHALLENGE_LEN];
char c_keys[40];
/* server-side */
- char s_buf[ONIONSKIN_REPLY_LEN];
+ char s_buf[TAP_ONIONSKIN_REPLY_LEN];
char s_keys[40];
/* shared */
@@ -832,18 +832,18 @@ test_onion_handshake(void)
pk = pk_generate(0);
/* client handshake 1. */
- memset(c_buf, 0, ONIONSKIN_CHALLENGE_LEN);
- test_assert(! onion_skin_create(pk, &c_dh, c_buf));
+ memset(c_buf, 0, TAP_ONIONSKIN_CHALLENGE_LEN);
+ test_assert(! onion_skin_TAP_create(pk, &c_dh, c_buf));
/* server handshake */
- memset(s_buf, 0, ONIONSKIN_REPLY_LEN);
+ memset(s_buf, 0, TAP_ONIONSKIN_REPLY_LEN);
memset(s_keys, 0, 40);
- test_assert(! onion_skin_server_handshake(c_buf, pk, NULL,
+ test_assert(! onion_skin_TAP_server_handshake(c_buf, pk, NULL,
s_buf, s_keys, 40));
/* client handshake 2 */
memset(c_keys, 0, 40);
- test_assert(! onion_skin_client_handshake(c_dh, s_buf, c_keys, 40));
+ test_assert(! onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40));
if (memcmp(c_keys, s_keys, 40)) {
puts("Aiiiie");
1
0