diff options
73 files changed, 916 insertions, 272 deletions
diff --git a/.gitignore b/.gitignore index 71737cf1b..de1eb0469 100644 --- a/.gitignore +++ b/.gitignore @@ -13,15 +13,11 @@ *.gcno *.gcov *.gcda -# latex stuff -*.aux -*.dvi -*.blg -*.bbl -*.log # Autotools stuff .deps .dirstamp +*.trs +*.log # Stuff made by our makefiles *.bak # Python droppings @@ -63,6 +59,7 @@ # /contrib/ /contrib/dist/tor.sh /contrib/dist/torctl +/contrib/dist/tor.service /contrib/operator-tools/tor.logrotate /contrib/dist/suse/tor.sh @@ -101,7 +98,9 @@ /doc/tor-resolve.html.in /doc/tor-resolve.1.xml /doc/torify.1 +/doc/torify.1.in /doc/torify.html +/doc/torify.html.in /doc/torify.1.xml # /doc/spec/ diff --git a/changes/bug10849_023 b/changes/bug10849_023 new file mode 100644 index 000000000..480dea3de --- /dev/null +++ b/changes/bug10849_023 @@ -0,0 +1,6 @@ + o Major bugfixes: + - When running a hidden service, do not allow TunneledDirConns 0; + this will keep the hidden service from running, and also + make it publish its descriptors directly over HTTP. Fixes bug 10849; + bugfix on 0.2.1.1-alpha. + diff --git a/changes/bug10849_025 b/changes/bug10849_025 new file mode 100644 index 000000000..1a3b71bab --- /dev/null +++ b/changes/bug10849_025 @@ -0,0 +1,6 @@ + o Removed code: + - The TunnelDirConns and PreferTunnelledDirConns options no longer + exist; tunneled directory connections have been available since + 0.1.2.5-alpha, and turning them off is not a good idea. This is a + brute-force fix for 10849, where "TunnelDirConns 0" would break + hidden services. diff --git a/changes/bug11233 b/changes/bug11233 new file mode 100644 index 000000000..1161b6dfd --- /dev/null +++ b/changes/bug11233 @@ -0,0 +1,4 @@ + o Minor features: + - When we encounter an unexpected CR in text that we're trying to + write to a file on Windows, log the name of the file. Should help + diagnosing bug 11233. diff --git a/changes/bug11605 b/changes/bug11605 new file mode 100644 index 000000000..973ac6db1 --- /dev/null +++ b/changes/bug11605 @@ -0,0 +1,2 @@ + o Minor bugfixes (dmalloc): + - Fix compilation with dmalloc. Fixes bug 11605; bugfix on 0.2.4.10-alpha. diff --git a/changes/bug11609 b/changes/bug11609 new file mode 100644 index 000000000..2a116137c --- /dev/null +++ b/changes/bug11609 @@ -0,0 +1,5 @@ + o Minor bugfixes (sandbox): + - Don't try to enable the sandbox when using the Tor binary to + check its configuration, hash a passphrase, or so on. Doing + so was crashing on startup for some users. Fixes bug 11609; + bugfix on 0.2.5.1-alpha. diff --git a/changes/bug11618 b/changes/bug11618 new file mode 100644 index 000000000..e650d55cd --- /dev/null +++ b/changes/bug11618 @@ -0,0 +1,5 @@ + o Minor bugfixes: + - Fix all valgrind warnings produced by the unit tests. There were + over a thousand memory leak warnings previously, mostly produced + by forgetting to free things in the unit test code. Fixes bug + 11618, bugfixes on many versions of Tor. diff --git a/changes/bug11623 b/changes/bug11623 new file mode 100644 index 000000000..58ff06d38 --- /dev/null +++ b/changes/bug11623 @@ -0,0 +1,3 @@ + o Minor bugfixes: + - Make Tor compile correctly with --disable-buf-freelists. + Fixes bug 11623; bugfix on 0.2.5.3-alpha. diff --git a/changes/bug11628 b/changes/bug11628 new file mode 100644 index 000000000..b93e1f4fc --- /dev/null +++ b/changes/bug11628 @@ -0,0 +1,4 @@ + o Minor features: + - The configure script has a --disable-seccomp option to turn off + support for libseccomp on systems that have it, in case it (or + Tor's use of it) is broken. Resolves ticket 11628. diff --git a/changes/bug11654 b/changes/bug11654 new file mode 100644 index 000000000..97c70b25d --- /dev/null +++ b/changes/bug11654 @@ -0,0 +1,4 @@ + o Minor bugfixes: + - Fix a broken log message about delayed directory fetches that + was caused by a misuse of strlcpy(). Fixes bug 11654; bugfix on + 0.2.5.3-alpha. diff --git a/changes/bug11729 b/changes/bug11729 new file mode 100644 index 000000000..93751cfea --- /dev/null +++ b/changes/bug11729 @@ -0,0 +1,5 @@ + o Minor bugfixes (build): + - When deciding whether to build the 64-bit curve25519 implementation, + detect platforms where we can compile 128-bit arithmetic but cannot + link it. Fixes bug 11729; bugfix on 0.2.4.8-alpha. Patch + from "conradev". diff --git a/changes/bug11742 b/changes/bug11742 new file mode 100644 index 000000000..000487120 --- /dev/null +++ b/changes/bug11742 @@ -0,0 +1,4 @@ + o Removed code: + - Remove /tor/dbg-stability.txt URL that was meant to help debug WFU + and MTBF calculations, but that nobody was using. Fixes #11742. + diff --git a/changes/bug11743 b/changes/bug11743 new file mode 100644 index 000000000..89e4bbc2b --- /dev/null +++ b/changes/bug11743 @@ -0,0 +1,15 @@ + o Major security fixes (directory authorities): + + - Directory authorities now include a digest of each relay's + identity key as a part of its microdescriptor. + + This is a workaround for bug #11743, where Tor clients do not + support receiving multiple microdescriptors with the same SHA256 + digest in the same consensus. When clients receive a consensus + like this, they only use one of the relays. Without this fix, a + hostile relay could selectively disable client use of target + relays by constucting a router descriptor with a different + identity and the same microdescriptor parameters and getting the + authorities to list it in a microdescriptor consensus. This fix + prevents an attacker from causing a microdescriptor collision, + because the router's identity is not forgeable. diff --git a/changes/bug11750 b/changes/bug11750 new file mode 100644 index 000000000..f779ac8fe --- /dev/null +++ b/changes/bug11750 @@ -0,0 +1,5 @@ + o Minor features (security): + - Apply the secure SipHash-2-4 function to the hash table mapping + circuit IDs and channels to circuits. We missed this one when we + were converting all the other hash functions to use SipHash back + in 0.2.5.3-alpha. Resolves ticket 11750. diff --git a/changes/bug11761 b/changes/bug11761 new file mode 100644 index 000000000..ffcae5a71 --- /dev/null +++ b/changes/bug11761 @@ -0,0 +1,4 @@ + o Minor bugfixes: + - Fix compilation when DNS_CACHE_DEBUG is enabled. Fixes bug 11761; + bugfix on 0.2.3.13-alpha. Found by "cypherpunks". + diff --git a/changes/bug4345 b/changes/bug4345 new file mode 100644 index 000000000..5e650fc34 --- /dev/null +++ b/changes/bug4345 @@ -0,0 +1,10 @@ + o Minor bugfixes: + - Check return code on spawn_func() in cpuworker code, so that we don't + think we've spawned a nonworking cpuworker and write junk to it + forever. Fix related to bug 4345; bugfix on all released Tor versions. + Found by "skruffy". + + - Use a pthread_attr to make sure that spawn_func() cannot return + an error while at the same time launching a thread. Fix related + to bug 4345; bugfix on all released Tor versions. Reported by + "cypherpunks". diff --git a/changes/bug9635 b/changes/bug9635 new file mode 100644 index 000000000..042da7b8c --- /dev/null +++ b/changes/bug9635 @@ -0,0 +1,3 @@ + o Minor features: + - Give more specific warnings when we notice at the client side that + an onion handshake has failed. Fixes ticket 9635. diff --git a/configure.ac b/configure.ac index c0c818757..d3210921e 100644 --- a/configure.ac +++ b/configure.ac @@ -161,6 +161,9 @@ AC_ARG_ENABLE(bufferevents, AC_ARG_ENABLE(tool-name-check, AS_HELP_STRING(--disable-tool-name-check, check for sanely named toolchain when cross-compiling)) +AC_ARG_ENABLE(seccomp, + AS_HELP_STRING(--disable-seccomp, do not attempt to use libseccomp)) + dnl check for the correct "ar" when cross-compiling AN_MAKEVAR([AR], [AC_PROG_AR]) AN_PROGRAM([ar], [AC_PROG_AR]) @@ -434,7 +437,6 @@ AC_CHECK_FUNCS([event_get_version \ event_get_version_number \ event_get_method \ event_set_log_callback \ - evdns_set_outgoing_bind_address \ evutil_secure_rng_set_urandom_device_file \ evutil_secure_rng_init \ event_base_loopexit]) @@ -442,7 +444,7 @@ AC_CHECK_MEMBERS([struct event.min_heap_idx], , , [#include <event.h> ]) -AC_CHECK_HEADERS(event2/event.h event2/dns.h event2/bufferevent_ssl.h) +AC_CHECK_HEADERS(event2/event.h event2/dns.h) LIBS="$save_LIBS" LDFLAGS="$save_LDFLAGS" @@ -726,8 +728,10 @@ fi dnl ============================================================ dnl Check for libseccomp -AC_CHECK_HEADERS([seccomp.h]) -AC_SEARCH_LIBS(seccomp_init, [seccomp]) +if test "x$enable_seccomp" != "xno"; then + AC_CHECK_HEADERS([seccomp.h]) + AC_SEARCH_LIBS(seccomp_init, [seccomp]) +fi dnl ============================================================ dnl We need an implementation of curve25519. @@ -765,7 +769,7 @@ if test x$enable_curve25519 != xno; then ])], [tor_cv_can_use_curve25519_donna_c64=yes], [tor_cv_can_use_curve25519_donna_c64=no], - [AC_COMPILE_IFELSE( + [AC_LINK_IFELSE( [AC_LANG_PROGRAM([dnl #include <stdint.h> typedef unsigned uint128_t __attribute__((mode(TI))); @@ -1230,7 +1234,6 @@ if [[ $dmalloc -eq 1 ]]; then AC_CHECK_HEADERS(dmalloc.h, , AC_MSG_ERROR(dmalloc header file not found. Do you have the development files for dmalloc installed?)) AC_SEARCH_LIBS(dmalloc_malloc, [dmallocth dmalloc], , AC_MSG_ERROR(Libdmalloc library not found. If you enable it you better have it installed.)) AC_DEFINE(USE_DMALLOC, 1, [Debug memory allocation library]) - AC_DEFINE(DMALLOC_FUNC_CHECK, 1, [Enable dmalloc's malloc function check]) AC_CHECK_FUNCS(dmalloc_strdup dmalloc_strndup) fi diff --git a/contrib/README b/contrib/README new file mode 100644 index 000000000..07c6f777d --- /dev/null +++ b/contrib/README @@ -0,0 +1,61 @@ +The contrib/ directory contains small tools that might be useful for using +with Tor. A few of them are included in the Tor source distribution; you can +find the others in the main Tor repository. We don't guarantee that they're +particularly useful. + +dirauth-tools/ -- Tools useful for directory authority administrators +--------------------------------------------------------------------- + +add-tor is an old script to manipulate the approved-routers file. + +nagios-check-tor-authority-cert is a nagios script to check when Tor +authority certificates are expired or nearly expired. + +client-tools/ -- Tools for use with Tor clients +----------------------------------------------- + +torify is a small wrapper script around torsocks. + +tor-resolve.py uses Tor's SOCKS port extensions to perform DNS lookups. You +should probably use src/tools/tor-resolve instead. + +dist/ -- Scripts and files for use when packaging Tor +----------------------------------------------------- + +torctl, rc.subr, and tor.sh are init scripts for use with SysV-style init +tools. Everybody likes to write init scripts differently, it seems. + +tor.service is a sample service file for use with systemd. + +The suse/ subdirectory contains files used by the suse distribution. + +operator-tools/ -- Tools for Tor relay operators +------------------------------------------------ + +tor-exit-notice.html is an HTML file for use with the DirPortFrontPage +option. It tells visitors that your relay is a Tor exit node, and that they +shouldn't assume you're the origin for the traffic that you're delivering. + +tor.logrotate is a configuration file for use with the logrotate tool. You +may need to edit it to work for you. + +linux-tor-prio.sh uses Linux iptables tools to traffic-shape your Tor relay's +traffic. If it breaks, you get to keep both pieces. + +or-tools/ -- Tools for interacting with relays +---------------------------------------------- + +checksocks.pl is a tool to scan relays to see if any of them have advertised +public SOCKS ports, so we can tell them not to. + +check-tor is a quick shell script to try doing a TLS handshake with a router +or to try fetching a directory from it. + +exitlist is a precursor of check.torproject.org: it parses a bunch of cached +server descriptors to determine which can connect to a given address:port. + +win32build -- Old files for windows packaging +--------------------------------------------- + +You shouldn't need these unless you're building some of the older Windows +packages. diff --git a/contrib/include.am b/contrib/include.am index ede980678..5d5f21649 100644 --- a/contrib/include.am +++ b/contrib/include.am @@ -1,5 +1,6 @@ EXTRA_DIST+= \ + contrib/README \ contrib/client-tools/torify \ contrib/dist/rc.subr \ contrib/dist/suse/tor.sh.in \ diff --git a/doc/tor.1.txt b/doc/tor.1.txt index ac8ccfb07..2f97ecdb3 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -593,15 +593,6 @@ GENERAL OPTIONS This is useful when running on flash memory or other media that support only a limited number of writes. (Default: 0) -[[TunnelDirConns]] **TunnelDirConns** **0**|**1**:: - If non-zero, when a directory server we contact supports it, we will build - a one-hop circuit and make an encrypted connection via its ORPort. - (Default: 1) - -[[PreferTunneledDirConns]] **PreferTunneledDirConns** **0**|**1**:: - If non-zero, we will avoid directory servers that don't support tunneled - directory connections, when possible. (Default: 1) - [[CircuitPriorityHalflife]] **CircuitPriorityHalflife** __NUM1__:: If this value is set, we override the default algorithm for choosing which circuit's cell to deliver or relay next. When the value is 0, we diff --git a/scripts/README b/scripts/README new file mode 100644 index 000000000..70c763923 --- /dev/null +++ b/scripts/README @@ -0,0 +1,58 @@ +The scripts directory holds tools for use in building, generating, testing, +and maintaining the Tor source code. It is mainly for use by developers. + +Code maintenance scripts +------------------------ + +maint/checkLogs.pl -- Verify that Tor log statements are unique. + +maint/check_config_macros.pl -- Look for autoconf tests whose results are +never used. + +maint/checkOptionDocs.pl -- Make sure that Tor options are documented in the +manpage, and that the manpage only documents real Tor options. + +maint/checkSpaces.pl -- Style checker for the Tor source code. Mainly checks +whitespace. + +maint/findMergedChanges.pl -- Find a set of changes/* files that have been +merged into an upstream version. + +maint/format_changelog.py -- Flow the changelog into the proper format. + +maint/redox.py -- Find places that should have DOCDOC comments to indicate a +need for doxygen comments, and put those comments there. + +maint/updateVersions.pl -- Update the version number in the .nsi and windows +orconfig.h files. + + +Testing scripts +--------------- + +test/cov-blame -- Mash up the results of gcov with git blame. Mainly useful +to find out who has been writing untested code. + +test/cov-diff -- Compare two directories of gcov files to identify changed +lines without coverage. + +test/coverage -- Generates a directory full of gcov files. You need to use +this script instead of calling gcov directly because of our confusingly named +object files. + +test/scan-build.sh -- Example script for invoking clang's scan-build +static analysis tools. + + +Code generation scripts +----------------------- + +codegen/gen_linux_syscalls.pl -- Generate a table mapping linux syscall +numbers to their names. + +codegen/gen_server_ciphers.py -- Generate a sorted list of TLS ciphersuites +for servers to choose from. + +codegen/get_mozilla_ciphers.py -- Generate a list of TLS ciphersuites for +clients to use in order to look like Firefox. + diff --git a/src/common/gen_linux_syscalls.pl b/scripts/codegen/gen_linux_syscalls.pl index 3c64098a0..f985bad6c 100755 --- a/src/common/gen_linux_syscalls.pl +++ b/scripts/codegen/gen_linux_syscalls.pl @@ -11,7 +11,7 @@ while (<>) { print <<EOL; /* Automatically generated with - gen_sandbox_syscalls.pl /usr/include/asm/unistd*.h + gen_linux_syscalls.pl /usr/include/asm/unistd*.h Do not edit. */ static const struct { diff --git a/src/common/gen_server_ciphers.py b/scripts/codegen/gen_server_ciphers.py index 97ed9d046..97ed9d046 100755 --- a/src/common/gen_server_ciphers.py +++ b/scripts/codegen/gen_server_ciphers.py diff --git a/src/common/get_mozilla_ciphers.py b/scripts/codegen/get_mozilla_ciphers.py index 0636eb365..0636eb365 100644 --- a/src/common/get_mozilla_ciphers.py +++ b/scripts/codegen/get_mozilla_ciphers.py diff --git a/scripts/maint/check_config_macros.pl b/scripts/maint/check_config_macros.pl new file mode 100755 index 000000000..bcde2becc --- /dev/null +++ b/scripts/maint/check_config_macros.pl @@ -0,0 +1,20 @@ +#!/usr/bin/perl -w + +use strict; + +my @macros = (); + +open(F, 'orconfig.h.in'); +while(<F>) { + if (/^#undef +([A-Za-z0-9_]*)/) { + push @macros, $1; + } +} +close F; + +for my $m (@macros) { + my $s = `git grep '$m' src`; + if ($s eq '') { + print "Unused: $m\n"; + } +} diff --git a/scripts/maint/format_changelog.py b/scripts/maint/format_changelog.py index 6997d958a..35044b318 100755 --- a/scripts/maint/format_changelog.py +++ b/scripts/maint/format_changelog.py @@ -12,7 +12,135 @@ import os import re import sys -import textwrap + +# ============================== +# Oh, look! It's a cruddy approximation to Knuth's elegant text wrapping +# algorithm, with totally ad hoc parameters! +# +# We're trying to minimize: +# The total of the cubes of ragged space on underflowed intermediate lines, +# PLUS +# 100 * the fourth power of overflowed characters +# PLUS +# .1 * a bit more than the cube of ragged space on the last line. +# +# We use an obvious dynamic programming algorithm to sorta approximate this. +# It's not coded right or optimally, but it's fast enough for changelogs +# +# (Code found in an old directory of mine, lightly cleaned. -NM) + +NO_HYPHENATE=set(""" +pf-divert +""".split()) + +LASTLINE_UNDERFLOW_EXPONENT = 1 +LASTLINE_UNDERFLOW_PENALTY = 1 + +UNDERFLOW_EXPONENT = 3 +UNDERFLOW_PENALTY = 1 + +OVERFLOW_EXPONENT = 4 +OVERFLOW_PENALTY = 2000 + +ORPHAN_PENALTY = 10000 + +def generate_wrapping(words, divisions): + lines = [] + last = 0 + for i in divisions: + w = words[last:i] + last = i + line = " ".join(w).replace("\xff ","-").replace("\xff","-") + lines.append(line) + return lines + +def wrapping_quality(words, divisions, width1, width2): + total = 0.0 + + lines = generate_wrapping(words, divisions) + for line in lines: + length = len(line) + if line is lines[0]: + width = width1 + else: + width = width2 + + if length > width: + total += OVERFLOW_PENALTY * ( + (length - width) ** OVERFLOW_EXPONENT ) + else: + if line is lines[-1]: + e,p = (LASTLINE_UNDERFLOW_EXPONENT, LASTLINE_UNDERFLOW_PENALTY) + if " " not in line: + total += ORPHAN_PENALTY + else: + e,p = (UNDERFLOW_EXPONENT, UNDERFLOW_PENALTY) + + total += p * ((width - length) ** e) + + return total + +def wrap_graf(words, prefix_len1=0, prefix_len2=0, width=72): + wrapping_after = [ (0,), ] + + w1 = width - prefix_len1 + w2 = width - prefix_len2 + + for i in range(1, len(words)+1): + best_so_far = None + best_score = 1e300 + for j in range(i): + t = wrapping_after[j] + t1 = t[:-1] + (i,) + t2 = t + (i,) + wq1 = wrapping_quality(words, t1, w1, w2) + wq2 = wrapping_quality(words, t2, w1, w2) + + if wq1 < best_score: + best_so_far = t1 + best_score = wq1 + if wq2 < best_score: + best_so_far = t2 + best_score = wq2 + wrapping_after.append( best_so_far ) + + lines = generate_wrapping(words, wrapping_after[-1]) + + return lines + +def hyphenateable(word): + if re.match(r'^[^\d\-].*-', word): + stripped = re.sub(r'^\W+','',word) + stripped = re.sub(r'\W+$','',word) + return stripped not in NO_HYPHENATE + else: + return False + +def split_paragraph(s): + "Split paragraph into words; tuned for Tor." + + r = [] + for word in s.split(): + if hyphenateable(word): + while "-" in word: + a,word = word.split("-",1) + r.append(a+"\xff") + r.append(word) + return r + +def fill(text, width, initial_indent, subsequent_indent): + words = split_paragraph(text) + lines = wrap_graf(words, len(initial_indent), len(subsequent_indent), + width) + res = [ initial_indent, lines[0], "\n" ] + for line in lines[1:]: + res.append(subsequent_indent) + res.append(line) + res.append("\n") + return "".join(res) + +# ============================== + TP_MAINHEAD = 0 TP_HEADTEXT = 1 @@ -108,10 +236,11 @@ class ChangeLog(object): if indent2 == -1: indent2 = indent1 text = " ".join(re.sub(r'\s+', ' ', line.strip()) for line in par) - print textwrap.fill(text, width=72, - initial_indent=" "*indent1, - subsequent_indent=" "*indent2, - break_on_hyphens=False) + + sys.stdout.write(fill(text, + width=72, + initial_indent=" "*indent1, + subsequent_indent=" "*indent2)) def dump(self): print self.mainhead diff --git a/src/common/compat.c b/src/common/compat.c index 1ba264a0c..974f697e3 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -2429,6 +2429,12 @@ tor_pthread_helper_fn(void *_data) func(arg); return NULL; } +/** + * A pthread attribute to make threads start detached. + */ +static pthread_attr_t attr_detached; +/** True iff we've called tor_threads_init() */ +static int threads_initialized = 0; #endif /** Minimalist interface to run a void function in the background. On @@ -2452,12 +2458,12 @@ spawn_func(void (*func)(void *), void *data) #elif defined(USE_PTHREADS) pthread_t thread; tor_pthread_data_t *d; + if (PREDICT_UNLIKELY(!threads_initialized)) + tor_threads_init(); d = tor_malloc(sizeof(tor_pthread_data_t)); d->data = data; d->func = func; - if (pthread_create(&thread,NULL,tor_pthread_helper_fn,d)) - return -1; - if (pthread_detach(thread)) + if (pthread_create(&thread,&attr_detached,tor_pthread_helper_fn,d)) return -1; return 0; #else @@ -2814,8 +2820,6 @@ tor_get_thread_id(void) * "reentrant" mutexes (i.e., once we can re-lock if we're already holding * them.) */ static pthread_mutexattr_t attr_reentrant; -/** True iff we've called tor_threads_init() */ -static int threads_initialized = 0; /** Initialize <b>mutex</b> so it can be locked. Every mutex must be set * up with tor_mutex_init() or tor_mutex_new(); not both. */ void @@ -2959,6 +2963,8 @@ tor_threads_init(void) if (!threads_initialized) { pthread_mutexattr_init(&attr_reentrant); pthread_mutexattr_settype(&attr_reentrant, PTHREAD_MUTEX_RECURSIVE); + tor_assert(0==pthread_attr_init(&attr_detached)); + tor_assert(0==pthread_attr_setdetachstate(&attr_detached, 1)); threads_initialized = 1; set_main_thread(); } diff --git a/src/common/linux_syscalls.inc b/src/common/linux_syscalls.inc index 912735660..cf47c7380 100644 --- a/src/common/linux_syscalls.inc +++ b/src/common/linux_syscalls.inc @@ -1,5 +1,5 @@ /* Automatically generated with - gen_sandbox_syscalls.pl /usr/include/asm/unistd*.h + gen_linux_syscalls.pl /usr/include/asm/unistd*.h Do not edit. */ static const struct { diff --git a/src/common/util.c b/src/common/util.c index 86bb8baae..6524be3ed 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -303,7 +303,7 @@ tor_memdup_(const void *mem, size_t len DMALLOC_PARAMS) /** As tor_memdup(), but add an extra 0 byte at the end of the resulting * memory. */ void * -tor_memdup_nulterm(const void *mem, size_t len DMALLOC_PARAMS) +tor_memdup_nulterm_(const void *mem, size_t len DMALLOC_PARAMS) { char *dup; tor_assert(len < SIZE_T_CEILING+1); @@ -2004,7 +2004,8 @@ write_str_to_file(const char *fname, const char *str, int bin) #ifdef _WIN32 if (!bin && strchr(str, '\r')) { log_warn(LD_BUG, - "We're writing a text string that already contains a CR."); + "We're writing a text string that already contains a CR to %s", + escaped(fname)); } #endif return write_bytes_to_file(fname, str, strlen(str), bin); diff --git a/src/ext/README b/src/ext/README index 58ba7f699..5d5a6e151 100644 --- a/src/ext/README +++ b/src/ext/README @@ -42,3 +42,10 @@ curve25519_donna/*.c A copy of Adam Langley's curve25519-donna mostly-portable implementations of curve25519. + +csiphash.c +siphash.h + + Marek Majkowski's implementation of siphash 2-4, a secure keyed + hash algorithm to avoid collision-based DoS attacks against hash + tables. diff --git a/src/ext/ht.h b/src/ext/ht.h index 4a68673e6..871f5bbd2 100644 --- a/src/ext/ht.h +++ b/src/ext/ht.h @@ -58,6 +58,7 @@ #define HT_NEXT_RMV(name, head, elm) name##_HT_NEXT_RMV((head), (elm)) #define HT_CLEAR(name, head) name##_HT_CLEAR(head) #define HT_INIT(name, head) name##_HT_INIT(head) +#define HT_REP_IS_BAD_(name, head) name##_HT_REP_IS_BAD_(head) /* Helper: */ static INLINE unsigned ht_improve_hash(unsigned h) diff --git a/src/or/buffers.c b/src/or/buffers.c index fb186081c..e54751db2 100644 --- a/src/or/buffers.c +++ b/src/or/buffers.c @@ -117,6 +117,9 @@ chunk_repack(chunk_t *chunk) chunk->data = &chunk->mem[0]; } +/** Keep track of total size of allocated chunks for consistency asserts */ +static size_t total_bytes_allocated_in_chunks = 0; + #if defined(ENABLE_BUF_FREELISTS) || defined(RUNNING_DOXYGEN) /** A freelist of chunks. */ typedef struct chunk_freelist_t { @@ -148,9 +151,6 @@ static chunk_freelist_t freelists[] = { * could help with? */ static uint64_t n_freelist_miss = 0; -/** DOCDOC */ -static size_t total_bytes_allocated_in_chunks = 0; - static void assert_freelist_ok(chunk_freelist_t *fl); /** Return the freelist to hold chunks of size <b>alloc</b>, or NULL if diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index cd92326b3..9d06759de 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -9,6 +9,8 @@ * \brief The actual details of building circuits. **/ +#define CIRCUITBUILD_PRIVATE + #include "or.h" #include "channel.h" #include "circpathbias.h" @@ -83,7 +85,7 @@ channel_connect_for_circuit(const tor_addr_t *addr, uint16_t port, * * Return it, or 0 if can't get a unique circ_id. */ -static circid_t +STATIC circid_t get_unique_circ_id_by_chan(channel_t *chan) { /* This number is chosen somewhat arbitrarily; see comment below for more diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h index ebcb22c45..71caea94e 100644 --- a/src/or/circuitbuild.h +++ b/src/or/circuitbuild.h @@ -58,5 +58,9 @@ const char *build_state_get_exit_nickname(cpath_build_state_t *state); const node_t *choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state); +#ifdef CIRCUITBUILD_PRIVATE +STATIC circid_t get_unique_circ_id_by_chan(channel_t *chan); +#endif + #endif diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index 90fc93f3a..e5ed9c04f 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -76,7 +76,15 @@ chan_circid_entries_eq_(chan_circid_circuit_map_t *a, static INLINE unsigned int chan_circid_entry_hash_(chan_circid_circuit_map_t *a) { - return ((unsigned)a->circ_id) ^ (unsigned)(uintptr_t)(a->chan); + /* Try to squeze the siphash input into 8 bytes to save any extra siphash + * rounds. This hash function is in the critical path. */ + uintptr_t chan = (uintptr_t) (void*) a->chan; + uint32_t array[2]; + array[0] = a->circ_id; + /* The low bits of the channel pointer are uninteresting, since the channel + * is a pretty big structure. */ + array[1] = (uint32_t) (chan >> 6); + return (unsigned) siphash24g(array, sizeof(array)); } /** Map from [chan,circid] to circuit. */ diff --git a/src/or/config.c b/src/or/config.c index 7850e5227..1faf13871 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -357,7 +357,7 @@ static config_var_t option_vars_[] = { V(OptimisticData, AUTOBOOL, "auto"), V(PortForwarding, BOOL, "0"), V(PortForwardingHelper, FILENAME, "tor-fw-helper"), - V(PreferTunneledDirConns, BOOL, "1"), + OBSOLETE("PreferTunneledDirConns"), V(ProtocolWarnings, BOOL, "0"), V(PublishServerDescriptor, CSV, "1"), V(PublishHidServDescriptors, BOOL, "1"), @@ -412,7 +412,7 @@ static config_var_t option_vars_[] = { V(TransListenAddress, LINELIST, NULL), VPORT(TransPort, LINELIST, NULL), V(TransProxyType, STRING, "default"), - V(TunnelDirConns, BOOL, "1"), + OBSOLETE("TunnelDirConns"), V(UpdateBridgesFromAuthority, BOOL, "0"), V(UseBridges, BOOL, "0"), V(UseEntryGuards, BOOL, "1"), @@ -3275,8 +3275,6 @@ options_validate(or_options_t *old_options, or_options_t *options, if (options->UseBridges && !options->Bridges) REJECT("If you set UseBridges, you must specify at least one bridge."); - if (options->UseBridges && !options->TunnelDirConns) - REJECT("If you set UseBridges, you must set TunnelDirConns."); for (cl = options->Bridges; cl; cl = cl->next) { bridge_line_t *bridge_line = parse_bridge_line(cl->value); @@ -3389,15 +3387,6 @@ options_validate(or_options_t *old_options, or_options_t *options, AF_INET6, 1, msg)<0) return -1; - if (options->PreferTunneledDirConns && !options->TunnelDirConns) - REJECT("Must set TunnelDirConns if PreferTunneledDirConns is set."); - - if ((options->Socks4Proxy || options->Socks5Proxy) && - !options->HTTPProxy && !options->PreferTunneledDirConns) - REJECT("When Socks4Proxy or Socks5Proxy is configured, " - "PreferTunneledDirConns and TunnelDirConns must both be " - "set to 1, or HTTPProxy must be configured."); - if (options->AutomapHostsSuffixes) { SMARTLIST_FOREACH(options->AutomapHostsSuffixes, char *, suf, { diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c index 6b6a68afe..61b2c29b3 100644 --- a/src/or/cpuworker.c +++ b/src/or/cpuworker.c @@ -528,7 +528,12 @@ spawn_cpuworker(void) tor_assert(SOCKET_OK(fdarray[1])); fd = fdarray[0]; - spawn_func(cpuworker_main, (void*)fdarray); + if (spawn_func(cpuworker_main, (void*)fdarray) < 0) { + tor_close_socket(fdarray[0]); + tor_close_socket(fdarray[1]); + tor_free(fdarray); + return -1; + } log_debug(LD_OR,"just spawned a cpu worker."); #ifndef TOR_IS_MULTITHREADED tor_close_socket(fdarray[1]); /* don't need the worker's side of the pipe */ diff --git a/src/or/directory.c b/src/or/directory.c index 8070a76a5..428fd01be 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -338,8 +338,6 @@ should_use_directory_guards(const or_options_t *options) if (options->DownloadExtraInfo || options->FetchDirInfoEarly || options->FetchDirInfoExtraEarly || options->FetchUselessDescriptors) return 0; - if (! options->PreferTunneledDirConns) - return 0; return 1; } @@ -834,6 +832,7 @@ directory_command_should_use_begindir(const or_options_t *options, int or_port, uint8_t router_purpose, dir_indirection_t indirection) { + (void) router_purpose; if (!or_port) return 0; /* We don't know an ORPort -- no chance. */ if (indirection == DIRIND_DIRECT_CONN || indirection == DIRIND_ANON_DIRPORT) @@ -842,9 +841,6 @@ directory_command_should_use_begindir(const or_options_t *options, if (!fascist_firewall_allows_address_or(addr, or_port) || directory_fetches_from_authorities(options)) return 0; /* We're firewalled or are acting like a relay -- also no. */ - if (!options->TunnelDirConns && - router_purpose != ROUTER_PURPOSE_BRIDGE) - return 0; /* We prefer to avoid using begindir conns. Fine. */ return 1; } @@ -3069,22 +3065,6 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, goto done; } - if (!strcmp(url,"/tor/dbg-stability.txt")) { - const char *stability; - size_t len; - if (options->BridgeAuthoritativeDir || - ! authdir_mode_tests_reachability(options) || - ! (stability = rep_hist_get_router_stability_doc(time(NULL)))) { - write_http_status_line(conn, 404, "Not found."); - goto done; - } - - len = strlen(stability); - write_http_response_header(conn, len, 0, 0); - connection_write_to_buf(stability, len, TO_CONN(conn)); - goto done; - } - #if defined(EXPORTMALLINFO) && defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO) #define ADD_MALLINFO_LINE(x) do { \ smartlist_add_asprintf(lines, "%s %d\n", #x, mi.x); \ diff --git a/src/or/dirvote.c b/src/or/dirvote.c index 4d3ee9cdb..c7be343ca 100644 --- a/src/or/dirvote.c +++ b/src/or/dirvote.c @@ -3588,6 +3588,12 @@ dirvote_create_microdescriptor(const routerinfo_t *ri, int consensus_method) tor_free(p6); } + if (consensus_method >= MIN_METHOD_FOR_ID_HASH_IN_MD) { + char idbuf[BASE64_DIGEST_LEN+1]; + digest_to_base64(idbuf, ri->cache_info.identity_digest); + smartlist_add_asprintf(chunks, "id rsa1024 %s\n", idbuf); + } + output = smartlist_join_strings(chunks, "", 0, NULL); { @@ -3657,7 +3663,8 @@ static const struct consensus_method_range_t { {MIN_METHOD_FOR_MICRODESC, MIN_METHOD_FOR_A_LINES - 1}, {MIN_METHOD_FOR_A_LINES, MIN_METHOD_FOR_P6_LINES - 1}, {MIN_METHOD_FOR_P6_LINES, MIN_METHOD_FOR_NTOR_KEY - 1}, - {MIN_METHOD_FOR_NTOR_KEY, MAX_SUPPORTED_CONSENSUS_METHOD}, + {MIN_METHOD_FOR_NTOR_KEY, MIN_METHOD_FOR_ID_HASH_IN_MD - 1}, + {MIN_METHOD_FOR_ID_HASH_IN_MD, MAX_SUPPORTED_CONSENSUS_METHOD}, {-1, -1} }; diff --git a/src/or/dirvote.h b/src/or/dirvote.h index 3a4951a95..4c57e4366 100644 --- a/src/or/dirvote.h +++ b/src/or/dirvote.h @@ -22,7 +22,7 @@ #define MIN_VOTE_INTERVAL 300 /** The highest consensus method that we currently support. */ -#define MAX_SUPPORTED_CONSENSUS_METHOD 17 +#define MAX_SUPPORTED_CONSENSUS_METHOD 18 /** Lowest consensus method that contains a 'directory-footer' marker */ #define MIN_METHOD_FOR_FOOTER 9 @@ -61,6 +61,10 @@ * Unmeasured=1 flag for unmeasured bandwidths */ #define MIN_METHOD_TO_CLIP_UNMEASURED_BW 17 +/** Lowest consensus method where authorities may include an "id" line in + * microdescriptors. */ +#define MIN_METHOD_FOR_ID_HASH_IN_MD 18 + /** Default bandwidth to clip unmeasured bandwidths to using method >= * MIN_METHOD_TO_CLIP_UNMEASURED_BW */ #define DEFAULT_MAX_UNMEASURED_BW_KB 20 diff --git a/src/or/dns.c b/src/or/dns.c index 36271939b..a9c431865 100644 --- a/src/or/dns.c +++ b/src/or/dns.c @@ -2174,7 +2174,7 @@ static void assert_cache_ok_(void) { cached_resolve_t **resolve; - int bad_rep = _cache_map_HT_REP_IS_BAD(&cache_root); + int bad_rep = HT_REP_IS_BAD_(cache_map, &cache_root); if (bad_rep) { log_err(LD_BUG, "Bad rep type %d on dns cache hash table", bad_rep); tor_assert(!bad_rep); diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c index 70587bd75..957217ac6 100644 --- a/src/or/entrynodes.c +++ b/src/or/entrynodes.c @@ -378,7 +378,7 @@ add_an_entry_guard(const node_t *chosen, int reset_status, int prepend, } else { const routerstatus_t *rs; rs = router_pick_directory_server(MICRODESC_DIRINFO|V3_DIRINFO, - PDS_PREFER_TUNNELED_DIR_CONNS_|PDS_FOR_GUARD); + PDS_FOR_GUARD); if (!rs) return NULL; node = node_get_by_id(rs->identity_digest); diff --git a/src/or/main.c b/src/or/main.c index 6713d8036..1e591577f 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2938,7 +2938,7 @@ tor_main(int argc, char *argv[]) if (tor_init(argc, argv)<0) return -1; - if (get_options()->Sandbox) { + if (get_options()->Sandbox && get_options()->command == CMD_RUN_TOR) { sandbox_cfg_t* cfg = sandbox_init_filter(); if (sandbox_init(cfg)) { diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index ef450073e..90918d4fe 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -10,6 +10,7 @@ * client or cache. */ +#define NETWORKSTATUS_PRIVATE #include "or.h" #include "channel.h" #include "circuitmux.h" @@ -183,7 +184,7 @@ router_reload_consensus_networkstatus(void) } /** Free all storage held by the vote_routerstatus object <b>rs</b>. */ -static void +STATIC void vote_routerstatus_free(vote_routerstatus_t *rs) { vote_microdesc_hash_t *h, *next; diff --git a/src/or/networkstatus.h b/src/or/networkstatus.h index 1659818f0..be0a86cdd 100644 --- a/src/or/networkstatus.h +++ b/src/or/networkstatus.h @@ -99,5 +99,9 @@ document_signature_t *document_signature_dup(const document_signature_t *sig); void networkstatus_free_all(void); int networkstatus_get_weight_scale_param(networkstatus_t *ns); +#ifdef NETWORKSTATUS_PRIVATE +STATIC void vote_routerstatus_free(vote_routerstatus_t *rs); +#endif + #endif diff --git a/src/or/nodelist.c b/src/or/nodelist.c index a38a6d499..09232f9f9 100644 --- a/src/or/nodelist.c +++ b/src/or/nodelist.c @@ -1510,8 +1510,8 @@ update_router_have_minimum_dir_info(void) } if (should_delay_dir_fetches(get_options(), &delay_fetches_msg)) { - log_notice(LD_DIR, "Delaying dir fetches: %s", delay_fetches_msg); - strlcpy(dir_info_status, "%s", sizeof(dir_info_status)); + log_notice(LD_DIR, "Delaying directory fetches: %s", delay_fetches_msg); + strlcpy(dir_info_status, delay_fetches_msg, sizeof(dir_info_status)); res = 0; goto done; } diff --git a/src/or/onion.c b/src/or/onion.c index 72571b7bd..ae39f451f 100644 --- a/src/or/onion.c +++ b/src/or/onion.c @@ -554,8 +554,10 @@ onion_skin_client_handshake(int type, switch (type) { case ONION_HANDSHAKE_TYPE_TAP: - if (reply_len != TAP_ONIONSKIN_REPLY_LEN) + if (reply_len != TAP_ONIONSKIN_REPLY_LEN) { + log_warn(LD_CIRC, "TAP reply was not of the correct length."); return -1; + } if (onion_skin_TAP_client_handshake(handshake_state->u.tap, (const char*)reply, (char *)keys_out, keys_out_len) < 0) @@ -565,8 +567,10 @@ onion_skin_client_handshake(int type, return 0; case ONION_HANDSHAKE_TYPE_FAST: - if (reply_len != CREATED_FAST_LEN) + if (reply_len != CREATED_FAST_LEN) { + log_warn(LD_CIRC, "CREATED_FAST reply was not of the correct length."); return -1; + } if (fast_client_handshake(handshake_state->u.fast, reply, keys_out, keys_out_len) < 0) return -1; @@ -575,8 +579,10 @@ onion_skin_client_handshake(int type, return 0; #ifdef CURVE25519_ENABLED case ONION_HANDSHAKE_TYPE_NTOR: - if (reply_len < NTOR_REPLY_LEN) + if (reply_len < NTOR_REPLY_LEN) { + log_warn(LD_CIRC, "ntor reply was not of the correct length."); return -1; + } { size_t keys_tmp_len = keys_out_len + DIGEST_LEN; uint8_t *keys_tmp = tor_malloc(keys_tmp_len); diff --git a/src/or/onion_fast.c b/src/or/onion_fast.c index 8e778dbc6..38b62decc 100644 --- a/src/or/onion_fast.c +++ b/src/or/onion_fast.c @@ -104,6 +104,7 @@ fast_client_handshake(const fast_handshake_state_t *handshake_state, out_len = key_out_len+DIGEST_LEN; out = tor_malloc(out_len); if (crypto_expand_key_material_TAP(tmp, sizeof(tmp), out, out_len)) { + log_warn(LD_CIRC, "Failed to expand key material"); goto done; } if (tor_memneq(out, handshake_reply_out+DIGEST_LEN, DIGEST_LEN)) { diff --git a/src/or/onion_ntor.c b/src/or/onion_ntor.c index 9cf7d5dd6..ef501f69d 100644 --- a/src/or/onion_ntor.c +++ b/src/or/onion_ntor.c @@ -256,7 +256,7 @@ onion_skin_ntor_client_handshake( si += CURVE25519_OUTPUT_LEN; curve25519_handshake(si, &handshake_state->seckey_x, &handshake_state->pubkey_B); - bad |= safe_mem_is_zero(si, CURVE25519_OUTPUT_LEN); + bad |= (safe_mem_is_zero(si, CURVE25519_OUTPUT_LEN) << 1); si += CURVE25519_OUTPUT_LEN; APPEND(si, handshake_state->router_id, DIGEST_LEN); APPEND(si, handshake_state->pubkey_B.public_key, CURVE25519_PUBKEY_LEN); @@ -281,7 +281,7 @@ onion_skin_ntor_client_handshake( /* Compute auth */ h_tweak(s.auth, s.auth_input, sizeof(s.auth_input), T->t_mac); - bad |= tor_memneq(s.auth, auth_candidate, DIGEST256_LEN); + bad |= (tor_memneq(s.auth, auth_candidate, DIGEST256_LEN) << 2); crypto_expand_key_material_rfc5869_sha256( s.secret_input, sizeof(s.secret_input), @@ -290,6 +290,11 @@ onion_skin_ntor_client_handshake( key_out, key_out_len); memwipe(&s, 0, sizeof(s)); + + if (bad) { + log_warn(LD_PROTOCOL, "Invalid result from curve25519 handshake: %d", bad); + } + return bad ? -1 : 0; } diff --git a/src/or/onion_tap.c b/src/or/onion_tap.c index 3782e75ab..9a9f374b9 100644 --- a/src/or/onion_tap.c +++ b/src/or/onion_tap.c @@ -194,8 +194,10 @@ onion_skin_TAP_client_handshake(crypto_dh_t *handshake_state, len = crypto_dh_compute_secret(LOG_PROTOCOL_WARN, handshake_state, handshake_reply, DH_KEY_LEN, key_material, key_material_len); - if (len < 0) + if (len < 0) { + log_warn(LD_PROTOCOL,"DH computation failed."); goto err; + } if (tor_memneq(key_material, handshake_reply+DH_KEY_LEN, DIGEST_LEN)) { /* H(K) does *not* match. Something fishy. */ diff --git a/src/or/or.h b/src/or/or.h index aeaeb8e6a..6aa6b59e8 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -3886,10 +3886,6 @@ typedef struct { * testing our DNS server. */ int EnforceDistinctSubnets; /**< If true, don't allow multiple routers in the * same network zone in the same circuit. */ - int TunnelDirConns; /**< If true, use BEGIN_DIR rather than BEGIN when - * possible. */ - int PreferTunneledDirConns; /**< If true, avoid dirservers that don't - * support BEGIN_DIR, when possible. */ int PortForwarding; /**< If true, use NAT-PMP or UPnP to automatically * forward the DirPort and ORPort on the NAT device */ char *PortForwardingHelper; /** < Filename or full path of the port @@ -4974,8 +4970,6 @@ typedef struct dir_server_t { * node that's currently a guard. */ #define PDS_FOR_GUARD (1<<5) -#define PDS_PREFER_TUNNELED_DIR_CONNS_ (1<<16) - /** Possible ways to weight routers when choosing one randomly. See * routerlist_sl_choose_by_bandwidth() for more information.*/ typedef enum bandwidth_weight_rule_t { diff --git a/src/or/rephist.c b/src/or/rephist.c index 70be39e23..a0f24e18f 100644 --- a/src/or/rephist.c +++ b/src/or/rephist.c @@ -879,126 +879,6 @@ rep_hist_record_mtbf_data(time_t now, int missing_means_down) return -1; } -/** Format the current tracked status of the router in <b>hist</b> at time - * <b>now</b> for analysis; return it in a newly allocated string. */ -static char * -rep_hist_format_router_status(or_history_t *hist, time_t now) -{ - char sor_buf[ISO_TIME_LEN+1]; - char sod_buf[ISO_TIME_LEN+1]; - double wfu; - double mtbf; - int up = 0, down = 0; - char *cp = NULL; - - if (hist->start_of_run) { - format_iso_time(sor_buf, hist->start_of_run); - up = 1; - } - if (hist->start_of_downtime) { - format_iso_time(sod_buf, hist->start_of_downtime); - down = 1; - } - - wfu = get_weighted_fractional_uptime(hist, now); - mtbf = get_stability(hist, now); - tor_asprintf(&cp, - "%s%s%s" - "%s%s%s" - "wfu %0.3f\n" - " weighted-time %lu\n" - " weighted-uptime %lu\n" - "mtbf %0.1f\n" - " weighted-run-length %lu\n" - " total-run-weights %f\n", - up?"uptime-started ":"", up?sor_buf:"", up?" UTC\n":"", - down?"downtime-started ":"", down?sod_buf:"", down?" UTC\n":"", - wfu, - hist->total_weighted_time, - hist->weighted_uptime, - mtbf, - hist->weighted_run_length, - hist->total_run_weights - ); - return cp; -} - -/** The last stability analysis document that we created, or NULL if we never - * have created one. */ -static char *last_stability_doc = NULL; -/** The last time we created a stability analysis document, or 0 if we never - * have created one. */ -static time_t built_last_stability_doc_at = 0; -/** Shortest allowable time between building two stability documents. */ -#define MAX_STABILITY_DOC_BUILD_RATE (3*60) - -/** Return a pointer to a NUL-terminated document describing our view of the - * stability of the routers we've been tracking. Return NULL on failure. */ -const char * -rep_hist_get_router_stability_doc(time_t now) -{ - char *result; - smartlist_t *chunks; - if (built_last_stability_doc_at + MAX_STABILITY_DOC_BUILD_RATE > now) - return last_stability_doc; - - if (!history_map) - return NULL; - - tor_free(last_stability_doc); - chunks = smartlist_new(); - - if (rep_hist_have_measured_enough_stability()) { - smartlist_add(chunks, tor_strdup("we-have-enough-measurements\n")); - } else { - smartlist_add(chunks, tor_strdup("we-do-not-have-enough-measurements\n")); - } - - DIGESTMAP_FOREACH(history_map, id, or_history_t *, hist) { - const node_t *node; - char dbuf[BASE64_DIGEST_LEN+1]; - char *info; - digest_to_base64(dbuf, id); - node = node_get_by_id(id); - if (node) { - char ip[INET_NTOA_BUF_LEN+1]; - char tbuf[ISO_TIME_LEN+1]; - time_t published = node_get_published_on(node); - node_get_address_string(node,ip,sizeof(ip)); - if (published > 0) - format_iso_time(tbuf, published); - else - strlcpy(tbuf, "???", sizeof(tbuf)); - smartlist_add_asprintf(chunks, - "router %s %s %s\n" - "published %s\n" - "relevant-flags %s%s%s\n" - "declared-uptime %ld\n", - dbuf, node_get_nickname(node), ip, - tbuf, - node->is_running ? "Running " : "", - node->is_valid ? "Valid " : "", - node->ri && node->ri->is_hibernating ? "Hibernating " : "", - node_get_declared_uptime(node)); - } else { - smartlist_add_asprintf(chunks, - "router %s {no descriptor}\n", dbuf); - } - info = rep_hist_format_router_status(hist, now); - if (info) - smartlist_add(chunks, info); - - } DIGESTMAP_FOREACH_END; - - result = smartlist_join_strings(chunks, "", 0, NULL); - SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); - smartlist_free(chunks); - - last_stability_doc = result; - built_last_stability_doc_at = time(NULL); - return result; -} - /** Helper: return the first j >= i such that !strcmpstart(sl[j], prefix) and * such that no line sl[k] with i <= k < j starts with "R ". Return -1 if no * such line exists. */ @@ -3041,11 +2921,9 @@ rep_hist_free_all(void) tor_free(write_array); tor_free(dir_read_array); tor_free(dir_write_array); - tor_free(last_stability_doc); tor_free(exit_bytes_read); tor_free(exit_bytes_written); tor_free(exit_streams); - built_last_stability_doc_at = 0; predicted_ports_free(); bidi_map_free(); diff --git a/src/or/rephist.h b/src/or/rephist.h index df01ae6cb..cd6231e6e 100644 --- a/src/or/rephist.h +++ b/src/or/rephist.h @@ -47,7 +47,6 @@ double rep_hist_get_stability(const char *id, time_t when); double rep_hist_get_weighted_fractional_uptime(const char *id, time_t when); long rep_hist_get_weighted_time_known(const char *id, time_t when); int rep_hist_have_measured_enough_stability(void); -const char *rep_hist_get_router_stability_doc(time_t now); void rep_hist_note_used_port(time_t now, uint16_t port); smartlist_t *rep_hist_get_predicted_ports(time_t now); diff --git a/src/or/routerlist.c b/src/or/routerlist.c index c15274e99..8f3477a4a 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -1282,8 +1282,6 @@ const routerstatus_t * router_pick_directory_server(dirinfo_type_t type, int flags) { const routerstatus_t *choice; - if (get_options()->PreferTunneledDirConns) - flags |= PDS_PREFER_TUNNELED_DIR_CONNS_; if (!routerlist) return NULL; @@ -1385,8 +1383,6 @@ router_pick_dirserver_generic(smartlist_t *sourcelist, { const routerstatus_t *choice; int busy = 0; - if (get_options()->PreferTunneledDirConns) - flags |= PDS_PREFER_TUNNELED_DIR_CONNS_; choice = router_pick_trusteddirserver_impl(sourcelist, type, flags, &busy); if (choice || !(flags & PDS_RETRY_IF_NO_SERVERS)) @@ -1411,10 +1407,7 @@ router_pick_dirserver_generic(smartlist_t *sourcelist, /** Pick a random running valid directory server/mirror from our * routerlist. Arguments are as for router_pick_directory_server(), except - * that RETRY_IF_NO_SERVERS is ignored, and: - * - * If the PDS_PREFER_TUNNELED_DIR_CONNS_ flag is set, prefer directory servers - * that we can use with BEGINDIR. + * that RETRY_IF_NO_SERVERS is ignored. */ static const routerstatus_t * router_pick_directory_server_impl(dirinfo_type_t type, int flags) @@ -1428,7 +1421,6 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags) const networkstatus_t *consensus = networkstatus_get_latest_consensus(); int requireother = ! (flags & PDS_ALLOW_SELF); int fascistfirewall = ! (flags & PDS_IGNORE_FASCISTFIREWALL); - int prefer_tunnel = (flags & PDS_PREFER_TUNNELED_DIR_CONNS_); int for_guard = (flags & PDS_FOR_GUARD); int try_excluding = 1, n_excluded = 0; @@ -1481,8 +1473,7 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags) is_overloaded = status->last_dir_503_at + DIR_503_TIMEOUT > now; - if (prefer_tunnel && - (!fascistfirewall || + if ((!fascistfirewall || fascist_firewall_allows_address_or(&addr, status->or_port))) smartlist_add(is_trusted ? trusted_tunnel : is_overloaded ? overloaded_tunnel : tunnel, (void*)node); @@ -1569,7 +1560,6 @@ router_pick_trusteddirserver_impl(const smartlist_t *sourcelist, time_t now = time(NULL); const int requireother = ! (flags & PDS_ALLOW_SELF); const int fascistfirewall = ! (flags & PDS_IGNORE_FASCISTFIREWALL); - const int prefer_tunnel = (flags & PDS_PREFER_TUNNELED_DIR_CONNS_); const int no_serverdesc_fetching =(flags & PDS_NO_EXISTING_SERVERDESC_FETCH); const int no_microdesc_fetching =(flags & PDS_NO_EXISTING_MICRODESC_FETCH); const double auth_weight = (sourcelist == fallback_dir_servers) ? @@ -1630,8 +1620,7 @@ router_pick_trusteddirserver_impl(const smartlist_t *sourcelist, } } - if (prefer_tunnel && - d->or_port && + if (d->or_port && (!fascistfirewall || fascist_firewall_allows_address_or(&addr, d->or_port))) smartlist_add(is_overloaded ? overloaded_tunnel : tunnel, (void*)d); diff --git a/src/or/statefile.c b/src/or/statefile.c index da3134171..7b9998fc1 100644 --- a/src/or/statefile.c +++ b/src/or/statefile.c @@ -294,6 +294,16 @@ or_state_save_broken(char *fname) tor_free(fname2); } +STATIC or_state_t * +or_state_new(void) +{ + or_state_t *new_state = tor_malloc_zero(sizeof(or_state_t)); + new_state->magic_ = OR_STATE_MAGIC; + config_init(&state_format, new_state); + + return new_state; +} + /** Reload the persistent state from disk, generating a new state as needed. * Return 0 on success, less than 0 on failure. */ @@ -321,9 +331,7 @@ or_state_load(void) log_warn(LD_GENERAL,"State file \"%s\" is not a file? Failing.", fname); goto done; } - new_state = tor_malloc_zero(sizeof(or_state_t)); - new_state->magic_ = OR_STATE_MAGIC; - config_init(&state_format, new_state); + new_state = or_state_new(); if (contents) { config_line_t *lines=NULL; int assign_retval; @@ -358,9 +366,7 @@ or_state_load(void) tor_free(contents); config_free(&state_format, new_state); - new_state = tor_malloc_zero(sizeof(or_state_t)); - new_state->magic_ = OR_STATE_MAGIC; - config_init(&state_format, new_state); + new_state = or_state_new(); } else if (contents) { log_info(LD_GENERAL, "Loaded state from \"%s\"", fname); } else { @@ -625,10 +631,19 @@ save_transport_to_state(const char *transport, tor_free(transport_addrport); } +STATIC void +or_state_free(or_state_t *state) +{ + if (!state) + return; + + config_free(&state_format, state); +} + void or_state_free_all(void) { - config_free(&state_format, global_state); + or_state_free(global_state); global_state = NULL; } diff --git a/src/or/statefile.h b/src/or/statefile.h index c1413ff95..15bb0b4aa 100644 --- a/src/or/statefile.h +++ b/src/or/statefile.h @@ -20,6 +20,8 @@ void or_state_free_all(void); #ifdef STATEFILE_PRIVATE STATIC config_line_t *get_transport_in_state_by_name(const char *transport); +STATIC void or_state_free(or_state_t *state); +STATIC or_state_t *or_state_new(void); #endif #endif diff --git a/src/test/bench.c b/src/test/bench.c index c9cc101b7..f6c33626f 100644 --- a/src/test/bench.c +++ b/src/test/bench.c @@ -338,6 +338,28 @@ bench_dmap(void) } static void +bench_siphash(void) +{ + char buf[128]; + int lens[] = { 7, 8, 15, 16, 20, 32, 111, 128, -1 }; + int i, j; + uint64_t start, end; + const int N = 300000; + crypto_rand(buf, sizeof(buf)); + + for (i = 0; lens[i] > 0; ++i) { + reset_perftime(); + start = perftime(); + for (j = 0; j < N; ++j) { + siphash24g(buf, lens[i]); + } + end = perftime(); + printf("siphash24g(%d): %.2f ns per call\n", + lens[i], NANOCOUNT(start,end,N)); + } +} + +static void bench_cell_ops(void) { const int iters = 1<<16; @@ -487,6 +509,7 @@ typedef struct benchmark_t { static struct benchmark_t benchmarks[] = { ENT(dmap), + ENT(siphash), ENT(aes), ENT(onion_TAP), #ifdef CURVE25519_ENABLED diff --git a/src/test/test.c b/src/test/test.c index 771725e23..c96b39659 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -32,6 +32,7 @@ const char tor_git_revision[] = ""; #define ROUTER_PRIVATE #define CIRCUITSTATS_PRIVATE #define CIRCUITLIST_PRIVATE +#define STATEFILE_PRIVATE /* * Linux doesn't provide lround in math.h by default, but mac os does... @@ -59,6 +60,7 @@ double fabs(double x); #include "policies.h" #include "rephist.h" #include "routerparse.h" +#include "statefile.h" #ifdef CURVE25519_ENABLED #include "crypto_curve25519.h" #include "onion_ntor.h" @@ -416,9 +418,10 @@ test_onion_queues(void) or_circuit_t *circ1 = or_circuit_new(0, NULL); or_circuit_t *circ2 = or_circuit_new(0, NULL); - create_cell_t *onionskin = NULL; + create_cell_t *onionskin = NULL, *create2_ptr; create_cell_t *create1 = tor_malloc_zero(sizeof(create_cell_t)); create_cell_t *create2 = tor_malloc_zero(sizeof(create_cell_t)); + create2_ptr = create2; /* remember, but do not free */ create_cell_init(create1, CELL_CREATE, ONION_HANDSHAKE_TYPE_TAP, TAP_ONIONSKIN_CHALLENGE_LEN, buf1); @@ -438,6 +441,7 @@ test_onion_queues(void) test_eq_ptr(circ2, onion_next_task(&onionskin)); test_eq(1, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); + tt_ptr_op(onionskin, ==, create2_ptr); clear_pending_onions(); test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); @@ -448,6 +452,7 @@ test_onion_queues(void) circuit_free(TO_CIRCUIT(circ2)); tor_free(create1); tor_free(create2); + tor_free(onionskin); } static void @@ -466,14 +471,14 @@ test_circuit_timeout(void) circuit_build_times_t estimate; circuit_build_times_t final; double timeout1, timeout2; - or_state_t state; + or_state_t *state=NULL; int i, runs; double close_ms; circuit_build_times_init(&initial); circuit_build_times_init(&estimate); circuit_build_times_init(&final); - memset(&state, 0, sizeof(or_state_t)); + state = or_state_new(); circuitbuild_running_unit_tests(); #define timeout0 (build_time_t)(30*1000.0) @@ -505,8 +510,9 @@ test_circuit_timeout(void) test_assert(estimate.total_build_times <= CBT_NCIRCUITS_TO_OBSERVE); - circuit_build_times_update_state(&estimate, &state); - test_assert(circuit_build_times_parse_state(&final, &state) == 0); + circuit_build_times_update_state(&estimate, state); + circuit_build_times_free_timeouts(&final); + test_assert(circuit_build_times_parse_state(&final, state) == 0); circuit_build_times_update_alpha(&final); timeout2 = circuit_build_times_calculate_timeout(&final, @@ -595,7 +601,10 @@ test_circuit_timeout(void) } done: - return; + circuit_build_times_free_timeouts(&initial); + circuit_build_times_free_timeouts(&estimate); + circuit_build_times_free_timeouts(&final); + or_state_free(state); } /** Test encoding and parsing of rendezvous service descriptors. */ @@ -946,6 +955,7 @@ test_geoip(void) geoip_start_dirreq((uint64_t) 1, 1024, DIRREQ_TUNNELED); s = geoip_format_dirreq_stats(now + 86400); test_streq(dirreq_stats_4, s); + tor_free(s); /* Stop collecting directory request statistics and start gathering * entry stats. */ @@ -1008,6 +1018,8 @@ test_geoip_with_pt(void) get_options_mutable()->BridgeRelay = 1; get_options_mutable()->BridgeRecordUsageByCountry = 1; + memset(&in6, 0, sizeof(in6)); + /* No clients seen yet. */ s = geoip_get_transport_history(); tor_assert(!s); diff --git a/src/test/test_buffers.c b/src/test/test_buffers.c index 6dd771593..e86ec8ea8 100644 --- a/src/test/test_buffers.c +++ b/src/test/test_buffers.c @@ -481,13 +481,22 @@ test_buffer_allocation_tracking(void *arg) fetch_from_buf(junk, 4096, buf1); /* drop a 1k chunk... */ tt_int_op(buf_allocation(buf1), ==, 3*4096); /* now 3 4k chunks */ +#ifdef ENABLE_BUF_FREELISTS tt_int_op(buf_get_total_allocation(), ==, 16384); /* that chunk went onto the freelist. */ +#else + tt_int_op(buf_get_total_allocation(), ==, 12288); /* that chunk was really + freed. */ +#endif write_to_buf(junk, 4000, buf2); tt_int_op(buf_allocation(buf2), ==, 4096); /* another 4k chunk. */ - tt_int_op(buf_get_total_allocation(), ==, 16384); /* that chunk came from - the freelist. */ + /* + * If we're using freelists, size stays at 16384 because we just pulled a + * chunk from the freelist. If we aren't, we bounce back up to 16384 by + * allocating a new chunk. + */ + tt_int_op(buf_get_total_allocation(), ==, 16384); write_to_buf(junk, 4000, buf2); tt_int_op(buf_allocation(buf2), ==, 8192); /* another 4k chunk. */ tt_int_op(buf_get_total_allocation(), ==, 5*4096); /* that chunk was new. */ @@ -513,6 +522,7 @@ test_buffer_allocation_tracking(void *arg) buf_free(buf1); buf_free(buf2); buf_shrink_freelists(1); + tor_free(junk); } static void @@ -587,6 +597,53 @@ test_buffer_time_tracking(void *arg) buf_free(buf2); } +static void +test_buffers_zlib(void *arg) +{ + char *msg = NULL; + char *contents = NULL; + char *expanded = NULL; + buf_t *buf = NULL; + tor_zlib_state_t *zlib_state = NULL; + size_t out_len, in_len; + + (void) arg; + + buf = buf_new_with_capacity(128); /* will round up */ + zlib_state = tor_zlib_new(1, ZLIB_METHOD); + + msg = tor_malloc(512); + crypto_rand(msg, 512); + tt_int_op(write_to_buf_zlib(buf, zlib_state, msg, 128, 0), ==, 0); + tt_int_op(write_to_buf_zlib(buf, zlib_state, msg+128, 128, 0), ==, 0); + tt_int_op(write_to_buf_zlib(buf, zlib_state, msg+256, 256, 0), ==, 0); + tt_int_op(write_to_buf_zlib(buf, zlib_state, "all done", 9, 1), ==, 0); + + in_len = buf_datalen(buf); + contents = tor_malloc(in_len); + + tt_int_op(fetch_from_buf(contents, in_len, buf), ==, 0); + + tt_int_op(0, ==, tor_gzip_uncompress(&expanded, &out_len, + contents, in_len, + ZLIB_METHOD, 1, + LOG_WARN)); + + tt_int_op(out_len, >=, 128); + tt_mem_op(msg, ==, expanded, 128); + tt_int_op(out_len, >=, 512); + tt_mem_op(msg, ==, expanded, 512); + tt_int_op(out_len, ==, 512+9); + tt_mem_op("all done", ==, expanded+512, 9); + + done: + buf_free(buf); + tor_zlib_free(zlib_state); + tor_free(contents); + tor_free(expanded); + tor_free(msg); +} + struct testcase_t buffer_tests[] = { { "basic", test_buffers_basic, TT_FORK, NULL, NULL }, { "copy", test_buffer_copy, TT_FORK, NULL, NULL }, @@ -595,6 +652,7 @@ struct testcase_t buffer_tests[] = { { "allocation_tracking", test_buffer_allocation_tracking, TT_FORK, NULL, NULL }, { "time_tracking", test_buffer_time_tracking, TT_FORK, NULL, NULL }, + { "zlib", test_buffers_zlib, TT_FORK, NULL, NULL }, END_OF_TESTCASES }; diff --git a/src/test/test_cell_formats.c b/src/test/test_cell_formats.c index b0eb2fca2..d7f60680c 100644 --- a/src/test/test_cell_formats.c +++ b/src/test/test_cell_formats.c @@ -8,7 +8,9 @@ #define CONNECTION_EDGE_PRIVATE #define RELAY_PRIVATE #include "or.h" +#include "channel.h" #include "connection_edge.h" +#include "connection_or.h" #include "onion.h" #include "onion_tap.h" #include "onion_fast.h" @@ -1212,6 +1214,47 @@ test_cfmt_resolved_cells(void *arg) #undef CLEAR_CELL } +static void +test_cfmt_is_destroy(void *arg) +{ + cell_t cell; + packed_cell_t packed; + circid_t circid = 0; + channel_t *chan; + (void)arg; + + chan = tor_malloc_zero(sizeof(channel_t)); + + memset(&cell, 0xff, sizeof(cell)); + cell.circ_id = 3003; + cell.command = CELL_RELAY; + + cell_pack(&packed, &cell, 0); + chan->wide_circ_ids = 0; + tt_assert(! packed_cell_is_destroy(chan, &packed, &circid)); + tt_int_op(circid, ==, 0); + + cell_pack(&packed, &cell, 1); + chan->wide_circ_ids = 1; + tt_assert(! packed_cell_is_destroy(chan, &packed, &circid)); + tt_int_op(circid, ==, 0); + + cell.command = CELL_DESTROY; + + cell_pack(&packed, &cell, 0); + chan->wide_circ_ids = 0; + tt_assert(packed_cell_is_destroy(chan, &packed, &circid)); + tt_int_op(circid, ==, 3003); + + circid = 0; + cell_pack(&packed, &cell, 1); + chan->wide_circ_ids = 1; + tt_assert(packed_cell_is_destroy(chan, &packed, &circid)); + + done: + tor_free(chan); +} + #define TEST(name, flags) \ { #name, test_cfmt_ ## name, flags, 0, NULL } @@ -1224,6 +1267,7 @@ struct testcase_t cell_format_tests[] = { TEST(extend_cells, 0), TEST(extended_cells, 0), TEST(resolved_cells, 0), + TEST(is_destroy, 0), END_OF_TESTCASES }; diff --git a/src/test/test_circuitlist.c b/src/test/test_circuitlist.c index ad8d0ac3a..7b7d4153e 100644 --- a/src/test/test_circuitlist.c +++ b/src/test/test_circuitlist.c @@ -2,9 +2,11 @@ /* See LICENSE for licensing information */ #define TOR_CHANNEL_INTERNAL_ +#define CIRCUITBUILD_PRIVATE #define CIRCUITLIST_PRIVATE #include "or.h" #include "channel.h" +#include "circuitbuild.h" #include "circuitlist.h" #include "test.h" @@ -257,9 +259,84 @@ test_rend_token_maps(void *arg) circuit_free(TO_CIRCUIT(c4)); } +static void +test_pick_circid(void *arg) +{ + bitarray_t *ba = NULL; + channel_t *chan1, *chan2; + circid_t circid; + int i; + (void) arg; + + chan1 = tor_malloc_zero(sizeof(channel_t)); + chan2 = tor_malloc_zero(sizeof(channel_t)); + chan2->wide_circ_ids = 1; + + chan1->circ_id_type = CIRC_ID_TYPE_NEITHER; + tt_int_op(0, ==, get_unique_circ_id_by_chan(chan1)); + + /* Basic tests, with no collisions */ + chan1->circ_id_type = CIRC_ID_TYPE_LOWER; + for (i = 0; i < 50; ++i) { + circid = get_unique_circ_id_by_chan(chan1); + tt_uint_op(0, <, circid); + tt_uint_op(circid, <, (1<<15)); + } + chan1->circ_id_type = CIRC_ID_TYPE_HIGHER; + for (i = 0; i < 50; ++i) { + circid = get_unique_circ_id_by_chan(chan1); + tt_uint_op((1<<15), <, circid); + tt_uint_op(circid, <, (1<<16)); + } + + chan2->circ_id_type = CIRC_ID_TYPE_LOWER; + for (i = 0; i < 50; ++i) { + circid = get_unique_circ_id_by_chan(chan2); + tt_uint_op(0, <, circid); + tt_uint_op(circid, <, (1u<<31)); + } + chan2->circ_id_type = CIRC_ID_TYPE_HIGHER; + for (i = 0; i < 50; ++i) { + circid = get_unique_circ_id_by_chan(chan2); + tt_uint_op((1u<<31), <, circid); + } + + /* Now make sure that we can behave well when we are full up on circuits */ + chan1->circ_id_type = CIRC_ID_TYPE_LOWER; + chan2->circ_id_type = CIRC_ID_TYPE_LOWER; + chan1->wide_circ_ids = chan2->wide_circ_ids = 0; + ba = bitarray_init_zero((1<<15)); + for (i = 0; i < (1<<15); ++i) { + circid = get_unique_circ_id_by_chan(chan1); + if (circid == 0) { + tt_int_op(i, >, (1<<14)); + break; + } + tt_uint_op(circid, <, (1<<15)); + tt_assert(! bitarray_is_set(ba, circid)); + bitarray_set(ba, circid); + channel_mark_circid_unusable(chan1, circid); + } + tt_int_op(i, <, (1<<15)); + /* Make sure that being full on chan1 does not interfere with chan2 */ + for (i = 0; i < 100; ++i) { + circid = get_unique_circ_id_by_chan(chan2); + tt_uint_op(circid, >, 0); + tt_uint_op(circid, <, (1<<15)); + channel_mark_circid_unusable(chan2, circid); + } + + done: + tor_free(chan1); + tor_free(chan2); + bitarray_free(ba); + circuit_free_all(); +} + struct testcase_t circuitlist_tests[] = { { "maps", test_clist_maps, TT_FORK, NULL, NULL }, { "rend_token_maps", test_rend_token_maps, TT_FORK, NULL, NULL }, + { "pick_circid", test_pick_circid, TT_FORK, NULL, NULL }, END_OF_TESTCASES }; diff --git a/src/test/test_config.c b/src/test/test_config.c index dbb50798b..94ac4dca1 100644 --- a/src/test/test_config.c +++ b/src/test/test_config.c @@ -124,6 +124,7 @@ test_config_addressmap(void *arg) test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL)); /* Test top-level-domain matching a bit harder */ + config_free_lines(get_options_mutable()->AddressMap); addressmap_clear_configured(); strlcpy(buf, "MapAddress *.com *.torserver.exit\n" "MapAddress *.torproject.org 1.1.1.1\n" @@ -153,6 +154,7 @@ test_config_addressmap(void *arg) test_streq(address, "2.2.2.2"); /* We don't support '*' as a mapping directive */ + config_free_lines(get_options_mutable()->AddressMap); addressmap_clear_configured(); strlcpy(buf, "MapAddress * *.torserver.exit\n", sizeof(buf)); config_get_lines(buf, &(get_options_mutable()->AddressMap), 0); @@ -170,7 +172,8 @@ test_config_addressmap(void *arg) #undef addressmap_rewrite done: - ; + config_free_lines(get_options_mutable()->AddressMap); + get_options_mutable()->AddressMap = NULL; } static int @@ -193,9 +196,9 @@ static void test_config_check_or_create_data_subdir(void *arg) { or_options_t *options = get_options_mutable(); - char *datadir = options->DataDirectory = tor_strdup(get_fname("datadir-0")); + char *datadir; const char *subdir = "test_stats"; - char *subpath = get_datadir_fname(subdir); + char *subpath; struct stat st; int r; #if !defined (_WIN32) || defined (WINCE) @@ -203,6 +206,10 @@ test_config_check_or_create_data_subdir(void *arg) #endif (void)arg; + tor_free(options->DataDirectory); + datadir = options->DataDirectory = tor_strdup(get_fname("datadir-0")); + subpath = get_datadir_fname(subdir); + #if defined (_WIN32) && !defined (WINCE) tt_int_op(mkdir(options->DataDirectory), ==, 0); #else @@ -251,7 +258,7 @@ static void test_config_write_to_data_subdir(void *arg) { or_options_t* options = get_options_mutable(); - char *datadir = options->DataDirectory = tor_strdup(get_fname("datadir-1")); + char *datadir; char *cp = NULL; const char* subdir = "test_stats"; const char* fname = "test_file"; @@ -270,9 +277,13 @@ test_config_write_to_data_subdir(void *arg) "accusam et justo duo dolores et\n" "ea rebum. Stet clita kasd gubergren, no sea takimata\n" "sanctus est Lorem ipsum dolor sit amet."; - char* filepath = get_datadir_fname2(subdir, fname); + char* filepath = NULL; (void)arg; + tor_free(options->DataDirectory); + datadir = options->DataDirectory = tor_strdup(get_fname("datadir-1")); + filepath = get_datadir_fname2(subdir, fname); + #if defined (_WIN32) && !defined (WINCE) tt_int_op(mkdir(options->DataDirectory), ==, 0); #else diff --git a/src/test/test_controller_events.c b/src/test/test_controller_events.c index 3a9aeca2f..ee35239e4 100644 --- a/src/test/test_controller_events.c +++ b/src/test/test_controller_events.c @@ -148,6 +148,7 @@ static void test_cntev_append_cell_stats(void *arg) { smartlist_t *event_parts; + char *cp = NULL; const char *key = "Z"; uint64_t include_if_non_zero[CELL_COMMAND_MAX_ + 1], number_to_include[CELL_COMMAND_MAX_ + 1]; @@ -178,7 +179,9 @@ test_cntev_append_cell_stats(void *arg) append_cell_stats_by_command(event_parts, key, include_if_non_zero, number_to_include); - tt_str_op("Z=relay:1", ==, smartlist_pop_last(event_parts)); + cp = smartlist_pop_last(event_parts); + tt_str_op("Z=relay:1", ==, cp); + tor_free(cp); /* Add four CREATE cells. */ include_if_non_zero[CELL_CREATE] = 3; @@ -186,20 +189,22 @@ test_cntev_append_cell_stats(void *arg) append_cell_stats_by_command(event_parts, key, include_if_non_zero, number_to_include); - tt_str_op("Z=create:4,relay:1", ==, smartlist_pop_last(event_parts)); + cp = smartlist_pop_last(event_parts); + tt_str_op("Z=create:4,relay:1", ==, cp); done: - ; + tor_free(cp); + smartlist_free(event_parts); } static void test_cntev_format_cell_stats(void *arg) { char *event_string = NULL; - origin_circuit_t *ocirc; - or_circuit_t *or_circ; + origin_circuit_t *ocirc = NULL; + or_circuit_t *or_circ = NULL; cell_stats_t *cell_stats = NULL; - channel_tls_t *n_chan, *p_chan; + channel_tls_t *n_chan=NULL, *p_chan=NULL; (void)arg; n_chan = tor_malloc_zero(sizeof(channel_tls_t)); @@ -282,6 +287,10 @@ test_cntev_format_cell_stats(void *arg) done: tor_free(cell_stats); tor_free(event_string); + tor_free(or_circ); + tor_free(ocirc); + tor_free(p_chan); + tor_free(n_chan); } #define TEST(name, flags) \ diff --git a/src/test/test_dir.c b/src/test/test_dir.c index 9e01bdbd4..90667e9a4 100644 --- a/src/test/test_dir.c +++ b/src/test/test_dir.c @@ -11,6 +11,7 @@ #define ROUTER_PRIVATE #define ROUTERLIST_PRIVATE #define HIBERNATE_PRIVATE +#define NETWORKSTATUS_PRIVATE #include "or.h" #include "config.h" #include "directory.h" @@ -194,6 +195,7 @@ test_dir_formats(void) test_assert(crypto_pk_cmp_keys(rp1->onion_pkey, pk1) == 0); test_assert(crypto_pk_cmp_keys(rp1->identity_pkey, pk2) == 0); //test_assert(rp1->exit_policy == NULL); + tor_free(buf); strlcpy(buf2, "router Fred 10.3.2.1 9005 0 0\n" @@ -277,6 +279,8 @@ test_dir_formats(void) routerinfo_free(r1); if (r2) routerinfo_free(r2); + if (rp2) + routerinfo_free(rp2); tor_free(buf); tor_free(pk1_str); @@ -1011,16 +1015,14 @@ vote_tweaks_for_v3ns(networkstatus_t *v, int voter, time_t now) /* Monkey around with the list a bit */ vrs = smartlist_get(v->routerstatus_list, 2); smartlist_del_keeporder(v->routerstatus_list, 2); - tor_free(vrs->version); - tor_free(vrs); + vote_routerstatus_free(vrs); vrs = smartlist_get(v->routerstatus_list, 0); vrs->status.is_fast = 1; if (voter == 3) { vrs = smartlist_get(v->routerstatus_list, 0); smartlist_del_keeporder(v->routerstatus_list, 0); - tor_free(vrs->version); - tor_free(vrs); + vote_routerstatus_free(vrs); vrs = smartlist_get(v->routerstatus_list, 0); memset(vrs->status.descriptor_digest, (int)'Z', DIGEST_LEN); test_assert(router_add_to_routerlist( @@ -1360,7 +1362,8 @@ test_a_networkstatus( vote->dist_seconds = 300; authority_cert_free(vote->cert); vote->cert = authority_cert_dup(cert2); - vote->net_params = smartlist_new(); + SMARTLIST_FOREACH(vote->net_params, char *, c, tor_free(c)); + smartlist_clear(vote->net_params); smartlist_split_string(vote->net_params, "bar=2000000000 circuitwindow=20", NULL, 0, 0); tor_free(vote->client_versions); @@ -1404,7 +1407,8 @@ test_a_networkstatus( vote->dist_seconds = 250; authority_cert_free(vote->cert); vote->cert = authority_cert_dup(cert3); - vote->net_params = smartlist_new(); + SMARTLIST_FOREACH(vote->net_params, char *, c, tor_free(c)); + smartlist_clear(vote->net_params); smartlist_split_string(vote->net_params, "circuitwindow=80 foo=660", NULL, 0, 0); smartlist_add(vote->supported_methods, tor_strdup("4")); @@ -1981,6 +1985,7 @@ vote_tweaks_for_umbw(networkstatus_t *v, int voter, time_t now) (void)now; test_assert(v->supported_methods); + SMARTLIST_FOREACH(v->supported_methods, char *, c, tor_free(c)); smartlist_clear(v->supported_methods); /* Method 17 is MIN_METHOD_TO_CLIP_UNMEASURED_BW_KB */ smartlist_split_string(v->supported_methods, diff --git a/src/test/test_extorport.c b/src/test/test_extorport.c index f91ac7415..d47792fdb 100644 --- a/src/test/test_extorport.c +++ b/src/test/test_extorport.c @@ -172,6 +172,7 @@ test_ext_or_init_auth(void *arg) (void)arg; /* Check default filename location */ + tor_free(options->DataDirectory); options->DataDirectory = tor_strdup("foo"); cp = get_ext_or_auth_cookie_file_name(); tt_str_op(cp, ==, "foo"PATH_SEPARATOR"extended_orport_auth_cookie"); diff --git a/src/test/test_microdesc.c b/src/test/test_microdesc.c index 53a03a48a..78f4823b8 100644 --- a/src/test/test_microdesc.c +++ b/src/test/test_microdesc.c @@ -5,7 +5,10 @@ #include "or.h" #include "config.h" +#include "dirvote.h" #include "microdesc.h" +#include "routerlist.h" +#include "routerparse.h" #include "test.h" @@ -261,6 +264,7 @@ test_md_cache_broken(void *data) options = get_options_mutable(); tt_assert(options); + tor_free(options->DataDirectory); options->DataDirectory = tor_strdup(get_fname("md_datadir_test2")); #ifdef _WIN32 @@ -284,9 +288,113 @@ test_md_cache_broken(void *data) microdesc_free_all(); } +/* Generated by chutney. */ +static const char test_ri[] = + "router test005r 127.0.0.1 5005 0 7005\n" + "platform Tor 0.2.5.4-alpha-dev on Linux\n" + "protocols Link 1 2 Circuit 1\n" + "published 2014-05-06 22:57:55\n" + "fingerprint 09DE 3BA2 48C2 1C3F 3760 6CD3 8460 43A6 D5EC F59E\n" + "uptime 0\n" + "bandwidth 1073741824 1073741824 0\n" + "extra-info-digest 361F9428F9FA4DD854C03DDBCC159D0D9FA996C9\n" + "onion-key\n" + "-----BEGIN RSA PUBLIC KEY-----\n" + "MIGJAoGBANBJz8Vldl12aFeSMPLiA4nOetLDN0oxU8bB1SDhO7Uu2zdWYVYAF5J0\n" + "st7WvrVy/jA9v/fsezNAPskBanecHRSkdMTpkcgRPMHE7CTGEwIy1Yp1X4bPgDlC\n" + "VCnbs5Pcts5HnWEYNK7qHDAUn+IlmjOO+pTUY8uyq+GQVz6H9wFlAgMBAAE=\n" + "-----END RSA PUBLIC KEY-----\n" + "signing-key\n" + "-----BEGIN RSA PUBLIC KEY-----\n" + "MIGJAoGBANbGUC4802Ke6C3nOVxN0U0HhIRrs32cQFEL4v+UUMJPgjbistHBvOax\n" + "CWVR/sMXM2kKJeGThJ9ZUs2p9dDG4WHPUXgkMqzTTEeeFa7pQKU0brgbmLaJq0Pi\n" + "mxmqC5RkTHa5bQvq6QlSFprAEoovV27cWqBM9jVdV9hyc//6kwPzAgMBAAE=\n" + "-----END RSA PUBLIC KEY-----\n" + "hidden-service-dir\n" + "ntor-onion-key Gg73xH7+kTfT6bi1uNVx9gwQdQas9pROIfmc4NpAdC4=\n" + "reject *:25\n" + "reject *:119\n" + "reject *:135-139\n" + "reject *:445\n" + "reject *:563\n" + "reject *:1214\n" + "reject *:4661-4666\n" + "reject *:6346-6429\n" + "reject *:6699\n" + "reject *:6881-6999\n" + "accept *:*\n" + "router-signature\n" + "-----BEGIN SIGNATURE-----\n" + "ImzX5PF2vRCrG1YzGToyjoxYhgh1vtHEDjmP+tIS/iil1DSnHZNpHSuHp0L1jE9S\n" + "yZyrtKaqpBE/aecAM3j4CWCn/ipnAAQkHcyRLin1bYvqBtRzyopVCRlUhF+uWrLq\n" + "t0xkIE39ss/EwmQr7iIgkdVH4oRIMsjYnFFJBG26nYY=\n" + "-----END SIGNATURE-----\n"; + +static const char test_md_8[] = + "onion-key\n" + "-----BEGIN RSA PUBLIC KEY-----\n" + "MIGJAoGBANBJz8Vldl12aFeSMPLiA4nOetLDN0oxU8bB1SDhO7Uu2zdWYVYAF5J0\n" + "st7WvrVy/jA9v/fsezNAPskBanecHRSkdMTpkcgRPMHE7CTGEwIy1Yp1X4bPgDlC\n" + "VCnbs5Pcts5HnWEYNK7qHDAUn+IlmjOO+pTUY8uyq+GQVz6H9wFlAgMBAAE=\n" + "-----END RSA PUBLIC KEY-----\n" + "p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n"; + +static const char test_md_16[] = + "onion-key\n" + "-----BEGIN RSA PUBLIC KEY-----\n" + "MIGJAoGBANBJz8Vldl12aFeSMPLiA4nOetLDN0oxU8bB1SDhO7Uu2zdWYVYAF5J0\n" + "st7WvrVy/jA9v/fsezNAPskBanecHRSkdMTpkcgRPMHE7CTGEwIy1Yp1X4bPgDlC\n" + "VCnbs5Pcts5HnWEYNK7qHDAUn+IlmjOO+pTUY8uyq+GQVz6H9wFlAgMBAAE=\n" + "-----END RSA PUBLIC KEY-----\n" + "ntor-onion-key Gg73xH7+kTfT6bi1uNVx9gwQdQas9pROIfmc4NpAdC4=\n" + "p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n"; + +static const char test_md_18[] = + "onion-key\n" + "-----BEGIN RSA PUBLIC KEY-----\n" + "MIGJAoGBANBJz8Vldl12aFeSMPLiA4nOetLDN0oxU8bB1SDhO7Uu2zdWYVYAF5J0\n" + "st7WvrVy/jA9v/fsezNAPskBanecHRSkdMTpkcgRPMHE7CTGEwIy1Yp1X4bPgDlC\n" + "VCnbs5Pcts5HnWEYNK7qHDAUn+IlmjOO+pTUY8uyq+GQVz6H9wFlAgMBAAE=\n" + "-----END RSA PUBLIC KEY-----\n" + "ntor-onion-key Gg73xH7+kTfT6bi1uNVx9gwQdQas9pROIfmc4NpAdC4=\n" + "p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n" + "id rsa1024 Cd47okjCHD83YGzThGBDptXs9Z4\n"; + +static void +test_md_generate(void *arg) +{ + routerinfo_t *ri; + microdesc_t *md = NULL; + (void)arg; + + ri = router_parse_entry_from_string(test_ri, NULL, 0, 0, NULL); + tt_assert(ri); + md = dirvote_create_microdescriptor(ri, 8); + tt_str_op(md->body, ==, test_md_8); + + /* XXXX test family lines. */ + /* XXXX test method 14 for A lines. */ + /* XXXX test method 15 for P6 lines. */ + + microdesc_free(md); + md = NULL; + md = dirvote_create_microdescriptor(ri, 16); + tt_str_op(md->body, ==, test_md_16); + + microdesc_free(md); + md = NULL; + md = dirvote_create_microdescriptor(ri, 18); + tt_str_op(md->body, ==, test_md_18); + + done: + microdesc_free(md); + routerinfo_free(ri); +} + struct testcase_t microdesc_tests[] = { { "cache", test_md_cache, TT_FORK, NULL, NULL }, { "broken_cache", test_md_cache_broken, TT_FORK, NULL, NULL }, + { "generate", test_md_generate, 0, NULL, NULL }, END_OF_TESTCASES }; diff --git a/src/test/test_oom.c b/src/test/test_oom.c index 989ca1203..e205673be 100644 --- a/src/test/test_oom.c +++ b/src/test/test_oom.c @@ -6,6 +6,7 @@ #define RELAY_PRIVATE #define BUFFERS_PRIVATE #define CIRCUITLIST_PRIVATE +#define CONNECTION_PRIVATE #include "or.h" #include "buffers.h" #include "circuitlist.h" @@ -216,6 +217,7 @@ test_oom_streambuf(void *arg) struct timeval tv = { 1389641159, 0 }; uint32_t tvms; int i; + smartlist_t *edgeconns = smartlist_new(); (void) arg; @@ -257,17 +259,21 @@ test_oom_streambuf(void *arg) tor_gettimeofday_cache_set(&tv); ec = dummy_edge_conn_new(c1, CONN_TYPE_EXIT, 1000, 1000); tt_assert(ec); + smartlist_add(edgeconns, ec); tv.tv_usec += 10*1000; tor_gettimeofday_cache_set(&tv); ec = dummy_edge_conn_new(c2, CONN_TYPE_AP, 1000, 1000); tt_assert(ec); + smartlist_add(edgeconns, ec); tv.tv_usec += 10*1000; tor_gettimeofday_cache_set(&tv); ec = dummy_edge_conn_new(c4, CONN_TYPE_EXIT, 1000, 1000); /* Yes, 4 twice*/ tt_assert(ec); + smartlist_add(edgeconns, ec); tv.tv_usec += 10*1000; tor_gettimeofday_cache_set(&tv); ec = dummy_edge_conn_new(c4, CONN_TYPE_EXIT, 1000, 1000); + smartlist_add(edgeconns, ec); tt_assert(ec); } @@ -302,6 +308,7 @@ test_oom_streambuf(void *arg) tor_gettimeofday_cache_set(&tv); ec = dummy_edge_conn_new(c4, CONN_TYPE_EXIT, 1000, 1000); tt_assert(ec); + smartlist_add(edgeconns, ec); } tt_int_op(buf_get_total_allocation(), ==, 4096*17*2); tt_int_op(circuit_max_queued_item_age(c4, tvms), ==, 1000); @@ -337,6 +344,10 @@ test_oom_streambuf(void *arg) circuit_free(c4); circuit_free(c5); + SMARTLIST_FOREACH(edgeconns, edge_connection_t *, ec, + connection_free_(TO_CONN(ec))); + smartlist_free(edgeconns); + UNMOCK(circuit_mark_for_close_); } diff --git a/src/test/test_policy.c b/src/test/test_policy.c index e3e7b3673..4cdcd034b 100644 --- a/src/test/test_policy.c +++ b/src/test/test_policy.c @@ -394,6 +394,7 @@ test_dump_exit_policy_to_string(void *arg) ep = router_dump_exit_policy_to_string(ri,1,1); test_streq("accept *:*\nreject *:25\nreject 8.8.8.8:*",ep); + tor_free(ep); policy_entry = router_parse_addr_policy_item_from_string("reject6 [FC00::]/7:*",-1); @@ -421,6 +422,7 @@ test_dump_exit_policy_to_string(void *arg) if (ri->exit_policy) { SMARTLIST_FOREACH(ri->exit_policy, addr_policy_t *, entry, addr_policy_free(entry)); + smartlist_free(ri->exit_policy); } tor_free(ri); tor_free(ep); diff --git a/src/test/test_pt.c b/src/test/test_pt.c index 327792105..f71627df1 100644 --- a/src/test/test_pt.c +++ b/src/test/test_pt.c @@ -129,6 +129,8 @@ test_pt_parsing(void) test_assert(parse_version(line, mp) == 0); done: + reset_mp(mp); + smartlist_free(mp->transports); tor_free(mp); } @@ -227,6 +229,10 @@ test_pt_protocol(void) test_assert(mp->conf_state == PT_PROTO_CONFIGURED); done: + reset_mp(mp); + smartlist_free(mp->transports); + tor_free(mp->argv[0]); + tor_free(mp->argv); tor_free(mp); } @@ -423,7 +429,7 @@ test_pt_configure_proxy(void *arg) } done: - tor_free(dummy_state); + or_state_free(dummy_state); UNMOCK(tor_get_lines_from_handle); UNMOCK(tor_process_handle_destroy); UNMOCK(get_or_state); @@ -433,6 +439,15 @@ test_pt_configure_proxy(void *arg) smartlist_free(controlevent_msgs); controlevent_msgs = NULL; } + if (mp->transports) { + SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t)); + smartlist_free(mp->transports); + } + smartlist_free(mp->transports_to_launch); + tor_free(mp->process_handle); + tor_free(mp->argv[0]); + tor_free(mp->argv); + tor_free(mp); } #define PT_LEGACY(name) \ diff --git a/src/test/test_routerkeys.c b/src/test/test_routerkeys.c index 1c8174b06..182e0f6f8 100644 --- a/src/test/test_routerkeys.c +++ b/src/test/test_routerkeys.c @@ -27,6 +27,7 @@ test_routerkeys_write_fingerprint(void *arg) tt_assert(key); options->ORPort_set = 1; /* So that we can get the server ID key */ + tor_free(options->DataDirectory); options->DataDirectory = tor_strdup(ddir); options->Nickname = tor_strdup("haflinger"); set_server_identity_key(key); diff --git a/src/test/test_status.c b/src/test/test_status.c index b704053d0..46dd47313 100644 --- a/src/test/test_status.c +++ b/src/test/test_status.c @@ -613,6 +613,9 @@ NS_DECL(or_state_t *, get_or_state, (void)); NS_DECL(int, accounting_is_enabled, (const or_options_t *options)); NS_DECL(time_t, accounting_get_end_time, (void)); +static or_state_t * NS(mock_state) = NULL; +static or_options_t * NS(mock_options) = NULL; + static void NS(test_main)(void *arg) { @@ -652,6 +655,8 @@ NS(test_main)(void *arg) NS_UNMOCK(server_mode); NS_UNMOCK(accounting_is_enabled); NS_UNMOCK(accounting_get_end_time); + tor_free_(NS(mock_state)); + tor_free_(NS(mock_options)); } static double @@ -669,10 +674,10 @@ NS(we_are_hibernating)(void) static const or_options_t * NS(get_options)(void) { - or_options_t *mock_options = tor_malloc_zero(sizeof(or_options_t)); - mock_options->AccountingMax = 0; + NS(mock_options) = tor_malloc_zero(sizeof(or_options_t)); + NS(mock_options)->AccountingMax = 0; - return mock_options; + return NS(mock_options); } static int @@ -771,11 +776,11 @@ NS(accounting_get_end_time)(void) static or_state_t * NS(get_or_state)(void) { - or_state_t *mock_state = tor_malloc_zero(sizeof(or_state_t)); - mock_state->AccountingBytesReadInInterval = 0; - mock_state->AccountingBytesWrittenInInterval = 0; + NS(mock_state) = tor_malloc_zero(sizeof(or_state_t)); + NS(mock_state)->AccountingBytesReadInInterval = 0; + NS(mock_state)->AccountingBytesWrittenInInterval = 0; - return mock_state; + return NS(mock_state); } #undef NS_SUBMODULE diff --git a/src/test/test_util.c b/src/test/test_util.c index 6d6b6dbdf..f2a0eafb3 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -2241,18 +2241,21 @@ test_util_asprintf(void *ptr) test_assert(cp); test_streq("simple string 100% safe", cp); test_eq(strlen(cp), r); + tor_free(cp); /* empty string */ r = tor_asprintf(&cp, "%s", ""); test_assert(cp); test_streq("", cp); test_eq(strlen(cp), r); + tor_free(cp); /* numbers (%i) */ r = tor_asprintf(&cp, "I like numbers-%2i, %i, etc.", -1, 2); test_assert(cp); test_streq("I like numbers--1, 2, etc.", cp); test_eq(strlen(cp), r); + /* don't free cp; next test uses it. */ /* numbers (%d) */ r = tor_asprintf(&cp2, "First=%d, Second=%d", 101, 202); @@ -3143,6 +3146,8 @@ smartlist_new_from_text_lines(const char *lines) last_line = smartlist_pop_last(sl); if (last_line != NULL && *last_line != '\0') { smartlist_add(sl, last_line); + } else { + tor_free(last_line); } return sl; |