diff options
Diffstat (limited to 'src')
67 files changed, 1097 insertions, 769 deletions
diff --git a/src/common/compat.c b/src/common/compat.c index 1ba264a0cc..111070cc10 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -1702,6 +1702,106 @@ log_credential_status(void) } #endif +#ifndef _WIN32 +/** Cached struct from the last getpwname() call we did successfully. */ +static struct passwd *passwd_cached = NULL; + +/** Helper: copy a struct passwd object. + * + * We only copy the fields pw_uid, pw_gid, pw_name, pw_dir. Tor doesn't use + * any others, and I don't want to run into incompatibilities. + */ +static struct passwd * +tor_passwd_dup(const struct passwd *pw) +{ + struct passwd *new_pw = tor_malloc_zero(sizeof(struct passwd)); + if (pw->pw_name) + new_pw->pw_name = tor_strdup(pw->pw_name); + if (pw->pw_dir) + new_pw->pw_dir = tor_strdup(pw->pw_dir); + new_pw->pw_uid = pw->pw_uid; + new_pw->pw_gid = pw->pw_gid; + + return new_pw; +} + +/** Helper: free one of our cached 'struct passwd' values. */ +static void +tor_passwd_free(struct passwd *pw) +{ + if (!pw) + return; + + tor_free(pw->pw_name); + tor_free(pw->pw_dir); + tor_free(pw); +} + +/** Wrapper around getpwnam() that caches result. Used so that we don't need + * to give the sandbox access to /etc/passwd. + * + * The following fields alone will definitely be copied in the output: pw_uid, + * pw_gid, pw_name, pw_dir. Other fields are not present in cached values. + * + * When called with a NULL argument, this function clears storage associated + * with static variables it uses. + **/ +const struct passwd * +tor_getpwnam(const char *username) +{ + struct passwd *pw; + + if (username == NULL) { + tor_passwd_free(passwd_cached); + passwd_cached = NULL; + return NULL; + } + + if ((pw = getpwnam(username))) { + tor_passwd_free(passwd_cached); + passwd_cached = tor_passwd_dup(pw); + log_notice(LD_GENERAL, "Caching new entry %s for %s", + passwd_cached->pw_name, username); + return pw; + } + + /* Lookup failed */ + if (! passwd_cached || ! passwd_cached->pw_name) + return NULL; + + if (! strcmp(username, passwd_cached->pw_name)) + return passwd_cached; + + return NULL; +} + +/** Wrapper around getpwnam() that can use cached result from + * tor_getpwnam(). Used so that we don't need to give the sandbox access to + * /etc/passwd. + * + * The following fields alone will definitely be copied in the output: pw_uid, + * pw_gid, pw_name, pw_dir. Other fields are not present in cached values. + */ +const struct passwd * +tor_getpwuid(uid_t uid) +{ + struct passwd *pw; + + if ((pw = getpwuid(uid))) { + return pw; + } + + /* Lookup failed */ + if (! passwd_cached) + return NULL; + + if (uid == passwd_cached->pw_uid) + return passwd_cached; + + return NULL; +} +#endif + /** Call setuid and setgid to run as <b>user</b> and switch to their * primary group. Return 0 on success. On failure, log and return -1. */ @@ -1709,7 +1809,7 @@ int switch_id(const char *user) { #ifndef _WIN32 - struct passwd *pw = NULL; + const struct passwd *pw = NULL; uid_t old_uid; gid_t old_gid; static int have_already_switched_id = 0; @@ -1730,7 +1830,7 @@ switch_id(const char *user) old_gid = getgid(); /* Lookup the user and group information, if we have a problem, bail out. */ - pw = getpwnam(user); + pw = tor_getpwnam(user); if (pw == NULL) { log_warn(LD_CONFIG, "Error setting configured user: %s not found", user); return -1; @@ -1901,10 +2001,10 @@ tor_disable_debugger_attach(void) char * get_user_homedir(const char *username) { - struct passwd *pw; + const struct passwd *pw; tor_assert(username); - if (!(pw = getpwnam(username))) { + if (!(pw = tor_getpwnam(username))) { log_err(LD_CONFIG,"User \"%s\" not found.", username); return NULL; } @@ -2429,6 +2529,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 +2558,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 +2920,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 +3063,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(); } @@ -3447,6 +3553,6 @@ get_total_system_memory(size_t *mem_out) *mem_out = mem_cached = (size_t) m; - return -1; + return 0; } diff --git a/src/common/compat.h b/src/common/compat.h index 314b1aa001..683c4d0897 100644 --- a/src/common/compat.h +++ b/src/common/compat.h @@ -633,6 +633,11 @@ int switch_id(const char *user); char *get_user_homedir(const char *username); #endif +#ifndef _WIN32 +const struct passwd *tor_getpwnam(const char *username); +const struct passwd *tor_getpwuid(uid_t uid); +#endif + int get_parent_directory(char *fname); char *make_path_absolute(char *fname); diff --git a/src/common/gen_linux_syscalls.pl b/src/common/gen_linux_syscalls.pl deleted file mode 100755 index 3c64098a0b..0000000000 --- a/src/common/gen_linux_syscalls.pl +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/perl -w - -use strict; -my %syscalls = (); - -while (<>) { - if (/^#define (__NR_\w+) /) { - $syscalls{$1} = 1; - } -} - -print <<EOL; -/* Automatically generated with - gen_sandbox_syscalls.pl /usr/include/asm/unistd*.h - Do not edit. - */ -static const struct { - int syscall_num; const char *syscall_name; -} SYSCALLS_BY_NUMBER[] = { -EOL - -for my $k (sort keys %syscalls) { - my $name = $k; - $name =~ s/^__NR_//; - print <<EOL; -#ifdef $k - { $k, "$name" }, -#endif -EOL - -} - -print <<EOL - {0, NULL} -}; - -EOL diff --git a/src/common/gen_server_ciphers.py b/src/common/gen_server_ciphers.py deleted file mode 100755 index 97ed9d0469..0000000000 --- a/src/common/gen_server_ciphers.py +++ /dev/null @@ -1,115 +0,0 @@ -#!/usr/bin/python -# Copyright 2014, The Tor Project, Inc -# See LICENSE for licensing information - -# This script parses openssl headers to find ciphersuite names, determines -# which ones we should be willing to use as a server, and sorts them according -# to preference rules. -# -# Run it on all the files in your openssl include directory. - -import re -import sys - -EPHEMERAL_INDICATORS = [ "_EDH_", "_DHE_", "_ECDHE_" ] -BAD_STUFF = [ "_DES_40_", "MD5", "_RC4_", "_DES_64_", - "_SEED_", "_CAMELLIA_", "_NULL" ] - -# these never get #ifdeffed. -MANDATORY = [ - "TLS1_TXT_DHE_RSA_WITH_AES_256_SHA", - "TLS1_TXT_DHE_RSA_WITH_AES_128_SHA", - "SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA", -] - -def find_ciphers(filename): - with open(filename) as f: - for line in f: - m = re.search(r'(?:SSL3|TLS1)_TXT_\w+', line) - if m: - yield m.group(0) - -def usable_cipher(ciph): - ephemeral = False - for e in EPHEMERAL_INDICATORS: - if e in ciph: - ephemeral = True - if not ephemeral: - return False - - if "_RSA_" not in ciph: - return False - - for b in BAD_STUFF: - if b in ciph: - return False - return True - -# All fields we sort on, in order of priority. -FIELDS = [ 'cipher', 'fwsec', 'mode', 'digest', 'bitlength' ] -# Map from sorted fields to recognized value in descending order of goodness -FIELD_VALS = { 'cipher' : [ 'AES', 'DES'], - 'fwsec' : [ 'ECDHE', 'DHE' ], - 'mode' : [ 'GCM', 'CBC' ], - 'digest' : [ 'SHA384', 'SHA256', 'SHA' ], - 'bitlength' : [ '256', '128', '192' ], -} - -class Ciphersuite(object): - def __init__(self, name, fwsec, cipher, bitlength, mode, digest): - self.name = name - self.fwsec = fwsec - self.cipher = cipher - self.bitlength = bitlength - self.mode = mode - self.digest = digest - - for f in FIELDS: - assert(getattr(self, f) in FIELD_VALS[f]) - - def sort_key(self): - return tuple(FIELD_VALS[f].index(getattr(self,f)) for f in FIELDS) - - -def parse_cipher(ciph): - m = re.match('(?:TLS1|SSL3)_TXT_(EDH|DHE|ECDHE)_RSA(?:_WITH)?_(AES|DES)_(256|128|192)(|_CBC|_CBC3|_GCM)_(SHA|SHA256|SHA384)$', ciph) - - if not m: - print "/* Couldn't parse %s ! */"%ciph - return None - - fwsec, cipher, bits, mode, digest = m.groups() - if fwsec == 'EDH': - fwsec = 'DHE' - - if mode in [ '_CBC3', '_CBC', '' ]: - mode = 'CBC' - elif mode == '_GCM': - mode = 'GCM' - - return Ciphersuite(ciph, fwsec, cipher, bits, mode, digest) - -ALL_CIPHERS = [] - -for fname in sys.argv[1:]: - ALL_CIPHERS += (parse_cipher(c) - for c in find_ciphers(fname) - if usable_cipher(c) ) - -ALL_CIPHERS.sort(key=Ciphersuite.sort_key) - -for c in ALL_CIPHERS: - if c is ALL_CIPHERS[-1]: - colon = ';' - else: - colon = ' ":"' - - if c.name in MANDATORY: - print " /* Required */" - print ' %s%s'%(c.name,colon) - else: - print "#ifdef %s"%c.name - print ' %s%s'%(c.name,colon) - print "#endif" - - diff --git a/src/common/get_mozilla_ciphers.py b/src/common/get_mozilla_ciphers.py deleted file mode 100644 index 0636eb3658..0000000000 --- a/src/common/get_mozilla_ciphers.py +++ /dev/null @@ -1,210 +0,0 @@ -#!/usr/bin/python -# coding=utf-8 -# Copyright 2011, The Tor Project, Inc -# original version by Arturo Filastò -# See LICENSE for licensing information - -# This script parses Firefox and OpenSSL sources, and uses this information -# to generate a ciphers.inc file. -# -# It takes two arguments: the location of a firefox source directory, and the -# location of an openssl source directory. - -import os -import re -import sys - -if len(sys.argv) != 3: - print >>sys.stderr, "Syntax: get_mozilla_ciphers.py <firefox-source-dir> <openssl-source-dir>" - sys.exit(1) - -ff_root = sys.argv[1] -ossl_root = sys.argv[2] - -def ff(s): - return os.path.join(ff_root, s) -def ossl(s): - return os.path.join(ossl_root, s) - -##### -# Read the cpp file to understand what Ciphers map to what name : -# Make "ciphers" a map from name used in the javascript to a cipher macro name -fileA = open(ff('security/manager/ssl/src/nsNSSComponent.cpp'),'r') - -# The input format is a file containing exactly one section of the form: -# static CipherPref CipherPrefs[] = { -# {"name", MACRO_NAME}, // comment -# ... -# {NULL, 0} -# } - -inCipherSection = False -cipherLines = [] -for line in fileA: - if line.startswith('static const CipherPref sCipherPrefs[]'): - # Get the starting boundary of the Cipher Preferences - inCipherSection = True - elif inCipherSection: - line = line.strip() - if line.startswith('{ nullptr, 0}'): - # At the ending boundary of the Cipher Prefs - break - else: - cipherLines.append(line) -fileA.close() - -# Parse the lines and put them into a dict -ciphers = {} -cipher_pref = {} -key_pending = None -for line in cipherLines: - m = re.search(r'^{\s*\"([^\"]+)\",\s*(\S+)\s*(?:,\s*(true|false))?\s*}', line) - if m: - assert not key_pending - key,value,enabled = m.groups() - if enabled == 'true': - ciphers[key] = value - cipher_pref[value] = key - continue - m = re.search(r'^{\s*\"([^\"]+)\",', line) - if m: - assert not key_pending - key_pending = m.group(1) - continue - m = re.search(r'^\s*(\S+)(?:,\s*(true|false))?\s*}', line) - if m: - assert key_pending - key = key_pending - value,enabled = m.groups() - key_pending = None - if enabled == 'true': - ciphers[key] = value - cipher_pref[value] = key - -#### -# Now find the correct order for the ciphers -fileC = open(ff('security/nss/lib/ssl/ssl3con.c'), 'r') -firefox_ciphers = [] -inEnum=False -for line in fileC: - if not inEnum: - if "ssl3CipherSuiteCfg cipherSuites[" in line: - inEnum = True - continue - - if line.startswith("};"): - break - - m = re.match(r'^\s*\{\s*([A-Z_0-9]+),', line) - if m: - firefox_ciphers.append(m.group(1)) - -fileC.close() - -##### -# Read the JS file to understand what ciphers are enabled. The format is -# pref("name", true/false); -# Build a map enabled_ciphers from javascript name to "true" or "false", -# and an (unordered!) list of the macro names for those ciphers that are -# enabled. -fileB = open(ff('netwerk/base/public/security-prefs.js'), 'r') - -enabled_ciphers = {} -for line in fileB: - m = re.match(r'pref\(\"([^\"]+)\"\s*,\s*(\S*)\s*\)', line) - if not m: - continue - key, val = m.groups() - if key.startswith("security.ssl3"): - enabled_ciphers[key] = val -fileB.close() - -used_ciphers = [] -for k, v in enabled_ciphers.items(): - if v == "true": - used_ciphers.append(ciphers[k]) - -#oSSLinclude = ('/usr/include/openssl/ssl3.h', '/usr/include/openssl/ssl.h', -# '/usr/include/openssl/ssl2.h', '/usr/include/openssl/ssl23.h', -# '/usr/include/openssl/tls1.h') -oSSLinclude = ('ssl/ssl3.h', 'ssl/ssl.h', - 'ssl/ssl2.h', 'ssl/ssl23.h', - 'ssl/tls1.h') - -##### -# This reads the hex code for the ciphers that are used by firefox. -# sslProtoD is set to a map from macro name to macro value in sslproto.h; -# cipher_codes is set to an (unordered!) list of these hex values. -sslProto = open(ff('security/nss/lib/ssl/sslproto.h'), 'r') -sslProtoD = {} - -for line in sslProto: - m = re.match('#define\s+(\S+)\s+(\S+)', line) - if m: - key, value = m.groups() - sslProtoD[key] = value -sslProto.close() - -cipher_codes = [] -for x in used_ciphers: - cipher_codes.append(sslProtoD[x].lower()) - -#### -# Now read through all the openssl include files, and try to find the openssl -# macro names for those files. -openssl_macro_by_hex = {} -all_openssl_macros = {} -for fl in oSSLinclude: - fp = open(ossl(fl), 'r') - for line in fp.readlines(): - m = re.match('#define\s+(\S+)\s+(\S+)', line) - if m: - value,key = m.groups() - if key.startswith('0x') and "_CK_" in value: - key = key.replace('0x0300','0x').lower() - #print "%s %s" % (key, value) - openssl_macro_by_hex[key] = value - all_openssl_macros[value]=key - fp.close() - -# Now generate the output. -print """\ -/* This is an include file used to define the list of ciphers clients should - * advertise. Before including it, you should define the CIPHER and XCIPHER - * macros. - * - * This file was automatically generated by get_mozilla_ciphers.py. - */""" -# Go in order by the order in CipherPrefs -for firefox_macro in firefox_ciphers: - - try: - js_cipher_name = cipher_pref[firefox_macro] - except KeyError: - # This one has no javascript preference. - continue - - # The cipher needs to be enabled in security-prefs.js - if enabled_ciphers.get(js_cipher_name, 'false') != 'true': - continue - - hexval = sslProtoD[firefox_macro].lower() - - try: - openssl_macro = openssl_macro_by_hex[hexval.lower()] - openssl_macro = openssl_macro.replace("_CK_", "_TXT_") - if openssl_macro not in all_openssl_macros: - raise KeyError() - format = {'hex':hexval, 'macro':openssl_macro, 'note':""} - except KeyError: - # openssl doesn't have a macro for this. - format = {'hex':hexval, 'macro':firefox_macro, - 'note':"/* No openssl macro found for "+hexval+" */\n"} - - res = """\ -%(note)s#ifdef %(macro)s - CIPHER(%(hex)s, %(macro)s) -#else - XCIPHER(%(hex)s, %(macro)s) -#endif""" % format - print res diff --git a/src/common/linux_syscalls.inc b/src/common/linux_syscalls.inc index 912735660d..cf47c73809 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/log.c b/src/common/log.c index 592dc2c5d4..517fa4faaa 100644 --- a/src/common/log.c +++ b/src/common/log.c @@ -562,6 +562,27 @@ tor_log_update_sigsafe_err_fds(void) UNLOCK_LOGS(); } +/** Add to <b>out</b> a copy of every currently configured log file name. Used + * to enable access to these filenames with the sandbox code. */ +void +tor_log_get_logfile_names(smartlist_t *out) +{ + logfile_t *lf; + tor_assert(out); + + LOCK_LOGS(); + + for (lf = logfiles; lf; lf = lf->next) { + if (lf->is_temporary || lf->is_syslog || lf->callback) + continue; + if (lf->filename == NULL) + continue; + smartlist_add(out, tor_strdup(lf->filename)); + } + + UNLOCK_LOGS(); +} + /** Output a message to the log, prefixed with a function name <b>fn</b>. */ #ifdef __GNUC__ /** GCC-based implementation of the log_fn backend, used when we have diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 8516c754f3..bb2b3ed742 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -115,6 +115,7 @@ static int filter_nopar_gen[] = { #endif SCMP_SYS(getrlimit), SCMP_SYS(gettimeofday), + SCMP_SYS(gettid), SCMP_SYS(getuid), #ifdef __NR_getuid32 SCMP_SYS(getuid32), @@ -129,6 +130,7 @@ static int filter_nopar_gen[] = { SCMP_SYS(munmap), SCMP_SYS(read), SCMP_SYS(rt_sigreturn), + SCMP_SYS(sched_getaffinity), SCMP_SYS(set_robust_list), #ifdef __NR_sigreturn SCMP_SYS(sigreturn), @@ -204,6 +206,7 @@ sb_rt_sigaction(scmp_filter_ctx ctx, sandbox_cfg_t *filter) return rc; } +#if 0 /** * Function responsible for setting up the execve syscall for * the seccomp filter sandbox. @@ -232,6 +235,7 @@ sb_execve(scmp_filter_ctx ctx, sandbox_cfg_t *filter) return 0; } +#endif /** * Function responsible for setting up the time syscall for @@ -856,7 +860,9 @@ sb_stat64(scmp_filter_ctx ctx, sandbox_cfg_t *filter) static sandbox_filter_func_t filter_func[] = { sb_rt_sigaction, sb_rt_sigprocmask, +#if 0 sb_execve, +#endif sb_time, sb_accept4, #ifdef __NR_mmap2 @@ -1240,6 +1246,7 @@ sandbox_cfg_allow_openat_filename_array(sandbox_cfg_t **cfg, ...) return 0; } +#if 0 int sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, const char *com) { @@ -1279,6 +1286,7 @@ sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, ...) va_end(ap); return 0; } +#endif int sandbox_getaddrinfo(const char *name, const char *servname, @@ -1659,6 +1667,7 @@ sandbox_cfg_allow_openat_filename_array(sandbox_cfg_t **cfg, ...) return 0; } +#if 0 int sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, const char *com) { @@ -1672,6 +1681,7 @@ sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, ...) (void)cfg; return 0; } +#endif int sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file) diff --git a/src/common/sandbox.h b/src/common/sandbox.h index c40f5e0d1f..b57215285e 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -198,6 +198,7 @@ int sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file); */ int sandbox_cfg_allow_openat_filename_array(sandbox_cfg_t **cfg, ...); +#if 0 /** * Function used to add a execve allowed filename to a supplied configuration. * The (char*) specifies the path to the allowed file; that pointer is stolen. @@ -211,6 +212,7 @@ int sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, const char *com); * one must be NULL. */ int sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, ...); +#endif /** * Function used to add a stat/stat64 allowed filename to a configuration. diff --git a/src/common/torlog.h b/src/common/torlog.h index 4493b251d2..34f70f3c00 100644 --- a/src/common/torlog.h +++ b/src/common/torlog.h @@ -156,9 +156,12 @@ void tor_log_err_sigsafe(const char *m, ...); int tor_log_get_sigsafe_err_fds(const int **out); void tor_log_update_sigsafe_err_fds(void); -#if defined(__GNUC__) || defined(RUNNING_DOXYGEN) +struct smartlist_t; +void tor_log_get_logfile_names(struct smartlist_t *out); + extern int log_global_min_severity_; +#if defined(__GNUC__) || defined(RUNNING_DOXYGEN) void log_fn_(int severity, log_domain_mask_t domain, const char *funcname, const char *format, ...) CHECK_PRINTF(4,5); diff --git a/src/common/util.c b/src/common/util.c index 86bb8baaef..e27036a84d 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); @@ -1516,7 +1516,7 @@ void format_iso_time_nospace_usec(char *buf, const struct timeval *tv) { tor_assert(tv); - format_iso_time_nospace(buf, tv->tv_sec); + format_iso_time_nospace(buf, (time_t)tv->tv_sec); tor_snprintf(buf+ISO_TIME_LEN, 8, ".%06d", (int)tv->tv_usec); } @@ -1871,7 +1871,7 @@ check_private_dir(const char *dirname, cpd_check_t check, char *f; #ifndef _WIN32 int mask; - struct passwd *pw = NULL; + const struct passwd *pw = NULL; uid_t running_uid; gid_t running_gid; #else @@ -1918,7 +1918,7 @@ check_private_dir(const char *dirname, cpd_check_t check, if (effective_user) { /* Look up the user and group information. * If we have a problem, bail out. */ - pw = getpwnam(effective_user); + pw = tor_getpwnam(effective_user); if (pw == NULL) { log_warn(LD_CONFIG, "Error setting configured user: %s not found", effective_user); @@ -1932,13 +1932,13 @@ check_private_dir(const char *dirname, cpd_check_t check, } if (st.st_uid != running_uid) { - struct passwd *pw = NULL; + const struct passwd *pw = NULL; char *process_ownername = NULL; - pw = getpwuid(running_uid); + pw = tor_getpwuid(running_uid); process_ownername = pw ? tor_strdup(pw->pw_name) : tor_strdup("<unknown>"); - pw = getpwuid(st.st_uid); + pw = tor_getpwuid(st.st_uid); log_warn(LD_FS, "%s is not owned by this user (%s, %d) but by " "%s (%d). Perhaps you are running Tor as the wrong user?", @@ -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); @@ -4539,6 +4540,30 @@ stream_status_to_string(enum stream_status stream_status) } } +/* DOCDOC */ +static void +log_portfw_spawn_error_message(const char *buf, + const char *executable, int *child_status) +{ + /* Parse error message */ + int retval, child_state, saved_errno; + retval = tor_sscanf(buf, SPAWN_ERROR_MESSAGE "%x/%x", + &child_state, &saved_errno); + if (retval == 2) { + log_warn(LD_GENERAL, + "Failed to start child process \"%s\" in state %d: %s", + executable, child_state, strerror(saved_errno)); + if (child_status) + *child_status = 1; + } else { + /* Failed to parse message from child process, log it as a + warning */ + log_warn(LD_GENERAL, + "Unexpected message from port forwarding helper \"%s\": %s", + executable, buf); + } +} + #ifdef _WIN32 /** Return a smartlist containing lines outputted from @@ -4686,23 +4711,7 @@ log_from_pipe(FILE *stream, int severity, const char *executable, /* Check if buf starts with SPAWN_ERROR_MESSAGE */ if (strcmpstart(buf, SPAWN_ERROR_MESSAGE) == 0) { - /* Parse error message */ - int retval, child_state, saved_errno; - retval = tor_sscanf(buf, SPAWN_ERROR_MESSAGE "%x/%x", - &child_state, &saved_errno); - if (retval == 2) { - log_warn(LD_GENERAL, - "Failed to start child process \"%s\" in state %d: %s", - executable, child_state, strerror(saved_errno)); - if (child_status) - *child_status = 1; - } else { - /* Failed to parse message from child process, log it as a - warning */ - log_warn(LD_GENERAL, - "Unexpected message from port forwarding helper \"%s\": %s", - executable, buf); - } + log_portfw_spawn_error_message(buf, executable, child_status); } else { log_fn(severity, LD_GENERAL, "Port forwarding helper says: %s", buf); } @@ -4780,7 +4789,7 @@ get_string_from_pipe(FILE *stream, char *buf_out, size_t count) /** Parse a <b>line</b> from tor-fw-helper and issue an appropriate * log message to our user. */ static void -handle_fw_helper_line(const char *line) +handle_fw_helper_line(const char *executable, const char *line) { smartlist_t *tokens = smartlist_new(); char *message = NULL; @@ -4791,6 +4800,19 @@ handle_fw_helper_line(const char *line) int port = 0; int success = 0; + if (strcmpstart(line, SPAWN_ERROR_MESSAGE) == 0) { + /* We need to check for SPAWN_ERROR_MESSAGE again here, since it's + * possible that it got sent after we tried to read it in log_from_pipe. + * + * XXX Ideally, we should be using one of stdout/stderr for the real + * output, and one for the output of the startup code. We used to do that + * before cd05f35d2c. + */ + int child_status; + log_portfw_spawn_error_message(line, executable, &child_status); + goto done; + } + smartlist_split_string(tokens, line, NULL, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); @@ -4870,7 +4892,8 @@ handle_fw_helper_line(const char *line) /** Read what tor-fw-helper has to say in its stdout and handle it * appropriately */ static int -handle_fw_helper_output(process_handle_t *process_handle) +handle_fw_helper_output(const char *executable, + process_handle_t *process_handle) { smartlist_t *fw_helper_output = NULL; enum stream_status stream_status = 0; @@ -4885,7 +4908,7 @@ handle_fw_helper_output(process_handle_t *process_handle) /* Handle the lines we got: */ SMARTLIST_FOREACH_BEGIN(fw_helper_output, char *, line) { - handle_fw_helper_line(line); + handle_fw_helper_line(executable, line); tor_free(line); } SMARTLIST_FOREACH_END(line); @@ -5000,7 +5023,7 @@ tor_check_port_forwarding(const char *filename, stderr_status = log_from_pipe(child_handle->stderr_handle, LOG_INFO, filename, &retval); #endif - if (handle_fw_helper_output(child_handle) < 0) { + if (handle_fw_helper_output(filename, child_handle) < 0) { log_warn(LD_GENERAL, "Failed to handle fw helper output."); stdout_status = -1; retval = -1; diff --git a/src/ext/README b/src/ext/README index 58ba7f699d..5d5a6e1518 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 4a68673e6e..871f5bbd2d 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/ext/tinytest_macros.h b/src/ext/tinytest_macros.h index db2dfcbe6b..c3728d1fdd 100644 --- a/src/ext/tinytest_macros.h +++ b/src/ext/tinytest_macros.h @@ -113,8 +113,8 @@ #define tt_assert_test_fmt_type(a,b,str_test,type,test,printf_type,printf_fmt, \ setup_block,cleanup_block,die_on_fail) \ TT_STMT_BEGIN \ - type val1_ = (type)(a); \ - type val2_ = (type)(b); \ + type val1_ = (a); \ + type val2_ = (b); \ int tt_status_ = (test); \ if (!tt_status_ || tinytest_get_verbosity_()>1) { \ printf_type print_; \ @@ -163,7 +163,7 @@ (val1_ op val2_),"%lu",TT_EXIT_TEST_FUNCTION) #define tt_ptr_op(a,op,b) \ - tt_assert_test_type(a,b,#a" "#op" "#b,void*, \ + tt_assert_test_type(a,b,#a" "#op" "#b,const void*, \ (val1_ op val2_),"%p",TT_EXIT_TEST_FUNCTION) #define tt_str_op(a,op,b) \ @@ -173,7 +173,7 @@ #define tt_mem_op(expr1, op, expr2, len) \ tt_assert_test_fmt_type(expr1,expr2,#expr1" "#op" "#expr2, \ - const char *, \ + const void *, \ (val1_ && val2_ && memcmp(val1_, val2_, len) op 0), \ char *, "%s", \ { print_ = tinytest_format_hex_(value_, (len)); }, \ @@ -189,7 +189,7 @@ (val1_ op val2_),"%lu",(void)0) #define tt_want_ptr_op(a,op,b) \ - tt_assert_test_type(a,b,#a" "#op" "#b,void*, \ + tt_assert_test_type(a,b,#a" "#op" "#b,const void*, \ (val1_ op val2_),"%p",(void)0) #define tt_want_str_op(a,op,b) \ diff --git a/src/or/buffers.c b/src/or/buffers.c index e54751db28..033f86288e 100644 --- a/src/or/buffers.c +++ b/src/or/buffers.c @@ -62,25 +62,8 @@ static int parse_socks_client(const uint8_t *data, size_t datalen, int state, char **reason, ssize_t *drain_out); -#define DEBUG_CHUNK_ALLOC - /* Chunk manipulation functions */ -/** A single chunk on a buffer or in a freelist. */ -typedef struct chunk_t { - struct chunk_t *next; /**< The next chunk on the buffer or freelist. */ - size_t datalen; /**< The number of bytes stored in this chunk */ - size_t memlen; /**< The number of usable bytes of storage in <b>mem</b>. */ -#ifdef DEBUG_CHUNK_ALLOC - size_t DBG_alloc; -#endif - char *data; /**< A pointer to the first byte of data stored in <b>mem</b>. */ - uint32_t inserted_time; /**< Timestamp in truncated ms since epoch - * when this chunk was inserted. */ - char mem[FLEXIBLE_ARRAY_MEMBER]; /**< The actual memory used for storage in - * this chunk. */ -} chunk_t; - #define CHUNK_HEADER_LEN STRUCT_OFFSET(chunk_t, mem[0]) /** Return the number of bytes needed to allocate a chunk to hold @@ -407,19 +390,6 @@ buf_dump_freelist_sizes(int severity) #endif } -/** Magic value for buf_t.magic, to catch pointer errors. */ -#define BUFFER_MAGIC 0xB0FFF312u -/** A resizeable buffer, optimized for reading and writing. */ -struct buf_t { - uint32_t magic; /**< Magic cookie for debugging: Must be set to - * BUFFER_MAGIC. */ - size_t datalen; /**< How many bytes is this buffer holding right now? */ - size_t default_chunk_size; /**< Don't allocate any chunks smaller than - * this for this buffer. */ - chunk_t *head; /**< First chunk in the list, or NULL for none. */ - chunk_t *tail; /**< Last chunk in the list, or NULL for none. */ -}; - /** Collapse data from the first N chunks from <b>buf</b> into buf->head, * growing it as necessary, until buf->head has the first <b>bytes</b> bytes * of data from the buffer, or until buf->head has all the data in <b>buf</b>. @@ -2507,6 +2477,7 @@ write_to_buf_zlib(buf_t *buf, tor_zlib_state_t *state, char *next; size_t old_avail, avail; int over = 0; + do { int need_new_chunk = 0; if (!buf->tail || ! CHUNK_REMAINING_CAPACITY(buf->tail)) { diff --git a/src/or/buffers.h b/src/or/buffers.h index a201282da6..c90e14750e 100644 --- a/src/or/buffers.h +++ b/src/or/buffers.h @@ -106,6 +106,35 @@ void assert_buf_ok(buf_t *buf); STATIC int buf_find_string_offset(const buf_t *buf, const char *s, size_t n); STATIC void buf_pullup(buf_t *buf, size_t bytes, int nulterminate); void buf_get_first_chunk_data(const buf_t *buf, const char **cp, size_t *sz); + +#define DEBUG_CHUNK_ALLOC +/** A single chunk on a buffer or in a freelist. */ +typedef struct chunk_t { + struct chunk_t *next; /**< The next chunk on the buffer or freelist. */ + size_t datalen; /**< The number of bytes stored in this chunk */ + size_t memlen; /**< The number of usable bytes of storage in <b>mem</b>. */ +#ifdef DEBUG_CHUNK_ALLOC + size_t DBG_alloc; +#endif + char *data; /**< A pointer to the first byte of data stored in <b>mem</b>. */ + uint32_t inserted_time; /**< Timestamp in truncated ms since epoch + * when this chunk was inserted. */ + char mem[FLEXIBLE_ARRAY_MEMBER]; /**< The actual memory used for storage in + * this chunk. */ +} chunk_t; + +/** Magic value for buf_t.magic, to catch pointer errors. */ +#define BUFFER_MAGIC 0xB0FFF312u +/** A resizeable buffer, optimized for reading and writing. */ +struct buf_t { + uint32_t magic; /**< Magic cookie for debugging: Must be set to + * BUFFER_MAGIC. */ + size_t datalen; /**< How many bytes is this buffer holding right now? */ + size_t default_chunk_size; /**< Don't allocate any chunks smaller than + * this for this buffer. */ + chunk_t *head; /**< First chunk in the list, or NULL for none. */ + chunk_t *tail; /**< Last chunk in the list, or NULL for none. */ +}; #endif #endif diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index cd92326b3a..9d06759dec 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 ebcb22c459..71caea94ed 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 e482fa5358..6238e08e1e 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. */ @@ -1821,7 +1829,7 @@ circuit_max_queued_cell_age(const circuit_t *c, uint32_t now) age = now - cell->inserted_time; if (! CIRCUIT_IS_ORIGIN(c)) { - const or_circuit_t *orcirc = TO_OR_CIRCUIT((circuit_t*)c); + const or_circuit_t *orcirc = CONST_TO_OR_CIRCUIT(c); if (NULL != (cell = TOR_SIMPLEQ_FIRST(&orcirc->p_chan_cells.head))) { uint32_t age2 = now - cell->inserted_time; if (age2 > age) @@ -1863,10 +1871,10 @@ circuit_max_queued_data_age(const circuit_t *c, uint32_t now) { if (CIRCUIT_IS_ORIGIN(c)) { return circuit_get_streams_max_data_age( - TO_ORIGIN_CIRCUIT((circuit_t*)c)->p_streams, now); + CONST_TO_ORIGIN_CIRCUIT(c)->p_streams, now); } else { return circuit_get_streams_max_data_age( - TO_OR_CIRCUIT((circuit_t*)c)->n_streams, now); + CONST_TO_OR_CIRCUIT(c)->n_streams, now); } } @@ -2059,15 +2067,10 @@ assert_circuit_ok(const circuit_t *c) tor_assert(c->purpose >= CIRCUIT_PURPOSE_MIN_ && c->purpose <= CIRCUIT_PURPOSE_MAX_); - { - /* Having a separate variable for this pleases GCC 4.2 in ways I hope I - * never understand. -NM. */ - circuit_t *nonconst_circ = (circuit_t*) c; - if (CIRCUIT_IS_ORIGIN(c)) - origin_circ = TO_ORIGIN_CIRCUIT(nonconst_circ); - else - or_circ = TO_OR_CIRCUIT(nonconst_circ); - } + if (CIRCUIT_IS_ORIGIN(c)) + origin_circ = CONST_TO_ORIGIN_CIRCUIT(c); + else + or_circ = CONST_TO_OR_CIRCUIT(c); if (c->n_chan) { tor_assert(!c->n_hop); diff --git a/src/or/circuituse.c b/src/or/circuituse.c index d10430668b..467bef652f 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -296,7 +296,7 @@ circuit_get_best(const entry_connection_t *conn, } if (!circuit_is_acceptable(origin_circ,conn,must_be_open,purpose, - need_uptime,need_internal,now.tv_sec)) + need_uptime,need_internal, (time_t)now.tv_sec)) continue; /* now this is an acceptable circ to hand back. but that doesn't @@ -683,9 +683,9 @@ circuit_expire_building(void) victim->purpose, circuit_purpose_to_string(victim->purpose)); } else if (circuit_build_times_count_close( - get_circuit_build_times_mutable(), - first_hop_succeeded, - victim->timestamp_created.tv_sec)) { + get_circuit_build_times_mutable(), + first_hop_succeeded, + (time_t)victim->timestamp_created.tv_sec)) { circuit_build_times_set_timeout(get_circuit_build_times_mutable()); } } @@ -783,6 +783,64 @@ circuit_expire_building(void) } } +/** + * As a diagnostic for bug 8387, log information about how many one-hop + * circuits we have around that have been there for at least <b>age</b> + * seconds. Log a few of them. + */ +void +circuit_log_ancient_one_hop_circuits(int age) +{ +#define MAX_ANCIENT_ONEHOP_CIRCUITS_TO_LOG 10 + time_t cutoff = time(NULL) - age; + int n_found = 0; + smartlist_t *log_these = smartlist_new(); + const circuit_t *circ; + + TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + const origin_circuit_t *ocirc; + if (! CIRCUIT_IS_ORIGIN(circ)) + continue; + if (circ->timestamp_created.tv_sec >= cutoff) + continue; + ocirc = CONST_TO_ORIGIN_CIRCUIT(circ); + + if (ocirc->build_state && ocirc->build_state->onehop_tunnel) { + ++n_found; + + if (smartlist_len(log_these) < MAX_ANCIENT_ONEHOP_CIRCUITS_TO_LOG) + smartlist_add(log_these, (origin_circuit_t*) ocirc); + } + } + + if (n_found == 0) + goto done; + + log_notice(LD_HEARTBEAT, + "Diagnostic for issue 8387: Found %d one-hop circuits more " + "than %d seconds old! Logging %d...", + n_found, age, smartlist_len(log_these)); + + SMARTLIST_FOREACH_BEGIN(log_these, const origin_circuit_t *, ocirc) { + char created[ISO_TIME_LEN+1]; + circ = TO_CIRCUIT(ocirc); + format_local_iso_time(created, + (time_t)circ->timestamp_created.tv_sec); + + log_notice(LD_HEARTBEAT, " #%d created at %s. %s, %s. %s for close. " + "%s for new conns.", + ocirc_sl_idx, + created, + circuit_state_to_string(circ->state), + circuit_purpose_to_string(circ->purpose), + circ->marked_for_close ? "Marked" : "Not marked", + ocirc->unusable_for_new_conns ? "Not usable" : "usable"); + } SMARTLIST_FOREACH_END(ocirc); + + done: + smartlist_free(log_these); +} + /** Remove any elements in <b>needed_ports</b> that are handled by an * open or in-progress circuit. */ diff --git a/src/or/circuituse.h b/src/or/circuituse.h index 11e5a64163..f228a67585 100644 --- a/src/or/circuituse.h +++ b/src/or/circuituse.h @@ -16,6 +16,7 @@ void circuit_expire_building(void); void circuit_remove_handled_ports(smartlist_t *needed_ports); int circuit_stream_is_being_handled(entry_connection_t *conn, uint16_t port, int min); +void circuit_log_ancient_one_hop_circuits(int age); #if 0 int circuit_conforms_to_options(const origin_circuit_t *circ, const or_options_t *options); diff --git a/src/or/config.c b/src/or/config.c index 7850e52270..0f7b1d2a2e 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"), @@ -536,9 +536,11 @@ static int options_transition_affects_descriptor( const or_options_t *old_options, const or_options_t *new_options); static int check_nickname_list(char **lst, const char *name, char **msg); -static int parse_client_transport_line(const char *line, int validate_only); +static int parse_client_transport_line(const or_options_t *options, + const char *line, int validate_only); -static int parse_server_transport_line(const char *line, int validate_only); +static int parse_server_transport_line(const or_options_t *options, + const char *line, int validate_only); static char *get_bindaddr_from_transport_listen_line(const char *line, const char *transport); static int parse_dir_authority_line(const char *line, @@ -1141,13 +1143,11 @@ options_act_reversible(const or_options_t *old_options, char **msg) if (!running_tor) goto commit; - if (!sandbox_is_active()) { - mark_logs_temp(); /* Close current logs once new logs are open. */ - logs_marked = 1; - if (options_init_logs(options, 0)<0) { /* Configure the tor_log(s) */ - *msg = tor_strdup("Failed to init Log options. See logs for details."); - goto rollback; - } + mark_logs_temp(); /* Close current logs once new logs are open. */ + logs_marked = 1; + if (options_init_logs(options, 0)<0) { /* Configure the tor_log(s) */ + *msg = tor_strdup("Failed to init Log options. See logs for details."); + goto rollback; } commit: @@ -1426,7 +1426,7 @@ options_act(const or_options_t *old_options) pt_prepare_proxy_list_for_config_read(); if (options->ClientTransportPlugin) { for (cl = options->ClientTransportPlugin; cl; cl = cl->next) { - if (parse_client_transport_line(cl->value, 0)<0) { + if (parse_client_transport_line(options, cl->value, 0)<0) { log_warn(LD_BUG, "Previously validated ClientTransportPlugin line " "could not be added!"); @@ -1437,7 +1437,7 @@ options_act(const or_options_t *old_options) if (options->ServerTransportPlugin && server_mode(options)) { for (cl = options->ServerTransportPlugin; cl; cl = cl->next) { - if (parse_server_transport_line(cl->value, 0)<0) { + if (parse_server_transport_line(options, cl->value, 0)<0) { log_warn(LD_BUG, "Previously validated ServerTransportPlugin line " "could not be added!"); @@ -3029,6 +3029,11 @@ options_validate(or_options_t *old_options, or_options_t *options, if (options->KeepalivePeriod < 1) REJECT("KeepalivePeriod option must be positive."); + if (options->PortForwarding && options->Sandbox) { + REJECT("PortForwarding is not compatible with Sandbox; at most one can " + "be set"); + } + if (ensure_bandwidth_cap(&options->BandwidthRate, "BandwidthRate", msg) < 0) return -1; @@ -3275,8 +3280,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); @@ -3286,13 +3289,13 @@ options_validate(or_options_t *old_options, or_options_t *options, } for (cl = options->ClientTransportPlugin; cl; cl = cl->next) { - if (parse_client_transport_line(cl->value, 1)<0) - REJECT("Transport line did not parse. See logs for details."); + if (parse_client_transport_line(options, cl->value, 1)<0) + REJECT("Invalid client transport line. See logs for details."); } for (cl = options->ServerTransportPlugin; cl; cl = cl->next) { - if (parse_server_transport_line(cl->value, 1)<0) - REJECT("Server transport line did not parse. See logs for details."); + if (parse_server_transport_line(options, cl->value, 1)<0) + REJECT("Invalid server transport line. See logs for details."); } if (options->ServerTransportPlugin && !server_mode(options)) { @@ -3389,15 +3392,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, { @@ -3751,6 +3745,11 @@ options_transition_allowed(const or_options_t *old, "Sandbox is active"); return -1; } + if (! opt_streq(old->DirPortFrontPage, new_val->DirPortFrontPage)) { + *msg = tor_strdup("Can't change DirPortFrontPage" + " while Sandbox is active"); + return -1; + } } return 0; @@ -4745,7 +4744,8 @@ parse_bridge_line(const char *line) * our internal transport list. * - If it's a managed proxy line, launch the managed proxy. */ static int -parse_client_transport_line(const char *line, int validate_only) +parse_client_transport_line(const or_options_t *options, + const char *line, int validate_only) { smartlist_t *items = NULL; int r; @@ -4812,6 +4812,12 @@ parse_client_transport_line(const char *line, int validate_only) goto err; } + if (is_managed && options->Sandbox) { + log_warn(LD_CONFIG, "Managed proxies are not compatible with Sandbox mode." + "(ClientTransportPlugin line was %s)", escaped(line)); + goto err; + } + if (is_managed) { /* managed */ if (!validate_only && is_useless_proxy) { log_notice(LD_GENERAL, "Pluggable transport proxy (%s) does not provide " @@ -5038,7 +5044,8 @@ get_options_for_server_transport(const char *transport) * If <b>validate_only</b> is 0, the line is well-formed, and it's a * managed proxy line, launch the managed proxy. */ static int -parse_server_transport_line(const char *line, int validate_only) +parse_server_transport_line(const or_options_t *options, + const char *line, int validate_only) { smartlist_t *items = NULL; int r; @@ -5093,6 +5100,12 @@ parse_server_transport_line(const char *line, int validate_only) goto err; } + if (is_managed && options->Sandbox) { + log_warn(LD_CONFIG, "Managed proxies are not compatible with Sandbox mode." + "(ServerTransportPlugin line was %s)", escaped(line)); + goto err; + } + if (is_managed) { /* managed */ if (!validate_only) { proxy_argc = line_length-2; diff --git a/src/or/connection.c b/src/or/connection.c index 3cc4e09fb7..cef9172ff1 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -1017,7 +1017,7 @@ connection_listener_new(const struct sockaddr *listensockaddr, tor_socket_t s = TOR_INVALID_SOCKET; /* the socket we're going to make */ or_options_t const *options = get_options(); #if defined(HAVE_PWD_H) && defined(HAVE_SYS_UN_H) - struct passwd *pw = NULL; + const struct passwd *pw = NULL; #endif uint16_t usePort = 0, gotPort = 0; int start_reading = 0; @@ -1157,7 +1157,7 @@ connection_listener_new(const struct sockaddr *listensockaddr, } #ifdef HAVE_PWD_H if (options->User) { - pw = getpwnam(options->User); + pw = tor_getpwnam(options->User); if (pw == NULL) { log_warn(LD_NET,"Unable to chown() %s socket: user %s not found.", address, options->User); diff --git a/src/or/control.c b/src/or/control.c index d571900ac3..2865d78329 100755 --- a/src/or/control.c +++ b/src/or/control.c @@ -1492,7 +1492,7 @@ getinfo_helper_misc(control_connection_t *conn, const char *question, *answer = tor_strdup(""); #else int myUid = geteuid(); - struct passwd *myPwEntry = getpwuid(myUid); + const struct passwd *myPwEntry = tor_getpwuid(myUid); if (myPwEntry) { *answer = tor_strdup(myPwEntry->pw_name); diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c index 6b6a68afe5..61b2c29b38 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 8070a76a55..22ba056ee1 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -261,7 +261,7 @@ directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose, size_t payload_len, size_t extrainfo_len) { const or_options_t *options = get_options(); - int post_via_tor; + dir_indirection_t indirection; const smartlist_t *dirservers = router_get_trusted_dir_servers(); int found = 0; const int exclude_self = (dir_purpose == DIR_PURPOSE_UPLOAD_VOTE || @@ -305,11 +305,19 @@ directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose, (int) extrainfo_len); } tor_addr_from_ipv4h(&ds_addr, ds->addr); - post_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose) || - !fascist_firewall_allows_address_dir(&ds_addr, ds->dir_port); + if (purpose_needs_anonymity(dir_purpose, router_purpose)) { + indirection = DIRIND_ANONYMOUS; + } else if (!fascist_firewall_allows_address_dir(&ds_addr,ds->dir_port)) { + if (fascist_firewall_allows_address_or(&ds_addr,ds->or_port)) + indirection = DIRIND_ONEHOP; + else + indirection = DIRIND_ANONYMOUS; + } else { + indirection = DIRIND_DIRECT_CONN; + } directory_initiate_command_routerstatus(rs, dir_purpose, router_purpose, - post_via_tor, + indirection, NULL, payload, upload_len, 0); } SMARTLIST_FOREACH_END(ds); if (!found) { @@ -338,8 +346,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 +840,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 +849,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; } @@ -2303,7 +2307,7 @@ write_http_response_header_impl(dir_connection_t *conn, ssize_t length, } if (cache_lifetime > 0) { char expbuf[RFC1123_TIME_LEN+1]; - format_rfc1123_time(expbuf, now + cache_lifetime); + format_rfc1123_time(expbuf, (time_t)(now + cache_lifetime)); /* We could say 'Cache-control: max-age=%d' here if we start doing * http/1.1 */ tor_snprintf(cp, sizeof(tmp)-(cp-tmp), @@ -3069,22 +3073,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/dirserv.c b/src/or/dirserv.c index f5994e0318..aedd092522 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -2507,7 +2507,7 @@ dirserv_read_measured_bandwidths(const char *from_file, } line[strlen(line)-1] = '\0'; - file_time = tor_parse_ulong(line, 10, 0, ULONG_MAX, &ok, NULL); + file_time = (time_t)tor_parse_ulong(line, 10, 0, ULONG_MAX, &ok, NULL); if (!ok) { log_warn(LD_DIRSERV, "Non-integer time in bandwidth file: %s", escaped(line)); @@ -3296,8 +3296,6 @@ connection_dirserv_add_servers_to_outbuf(dir_connection_t *conn) } body = signed_descriptor_get_body(sd); if (conn->zlib_state) { - /* XXXX024 This 'last' business should actually happen on the last - * routerinfo, not on the last fingerprint. */ int last = ! smartlist_len(conn->fingerprint_stack); connection_write_to_buf_zlib(body, sd->signed_descriptor_len, conn, last); @@ -3314,6 +3312,11 @@ connection_dirserv_add_servers_to_outbuf(dir_connection_t *conn) if (!smartlist_len(conn->fingerprint_stack)) { /* We just wrote the last one; finish up. */ + if (conn->zlib_state) { + connection_write_to_buf_zlib("", 0, conn, 1); + tor_zlib_free(conn->zlib_state); + conn->zlib_state = NULL; + } conn->dir_spool_src = DIR_SPOOL_NONE; smartlist_free(conn->fingerprint_stack); conn->fingerprint_stack = NULL; @@ -3339,8 +3342,6 @@ connection_dirserv_add_microdescs_to_outbuf(dir_connection_t *conn) if (!md || !md->body) continue; if (conn->zlib_state) { - /* XXXX024 This 'last' business should actually happen on the last - * routerinfo, not on the last fingerprint. */ int last = !smartlist_len(conn->fingerprint_stack); connection_write_to_buf_zlib(md->body, md->bodylen, conn, last); if (last) { @@ -3352,6 +3353,11 @@ connection_dirserv_add_microdescs_to_outbuf(dir_connection_t *conn) } } if (!smartlist_len(conn->fingerprint_stack)) { + if (conn->zlib_state) { + connection_write_to_buf_zlib("", 0, conn, 1); + tor_zlib_free(conn->zlib_state); + conn->zlib_state = NULL; + } conn->dir_spool_src = DIR_SPOOL_NONE; smartlist_free(conn->fingerprint_stack); conn->fingerprint_stack = NULL; diff --git a/src/or/dirvote.c b/src/or/dirvote.c index 4d3ee9cdb3..c7be343ca2 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 3a4951a95f..4c57e43661 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 36271939b4..a9c4318651 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 70587bd758..957217ac6c 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 e5a48cf98b..1168f43c9d 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -1757,7 +1757,7 @@ refill_callback(periodic_timer_t *timer, void *arg) accounting_add_bytes(bytes_read, bytes_written, seconds_rolled_over); if (milliseconds_elapsed > 0) - connection_bucket_refill(milliseconds_elapsed, now.tv_sec); + connection_bucket_refill(milliseconds_elapsed, (time_t)now.tv_sec); stats_prev_global_read_bucket = global_read_bucket; stats_prev_global_write_bucket = global_write_bucket; @@ -2554,6 +2554,9 @@ tor_free_all(int postfork) #endif /* ENABLE_MEMPOOLS */ if (!postfork) { tor_tls_free_all(); +#ifndef _WIN32 + tor_getpwnam(NULL); +#endif } /* stuff in main.c */ @@ -2825,6 +2828,16 @@ sandbox_init_filter(void) NULL, 0 ); + { + smartlist_t *logfiles = smartlist_new(); + tor_log_get_logfile_names(logfiles); + SMARTLIST_FOREACH(logfiles, char *, logfile_name, { + /* steals reference */ + sandbox_cfg_allow_open_filename(&cfg, logfile_name); + }); + smartlist_free(logfiles); + } + // orport if (server_mode(get_options())) { sandbox_cfg_allow_open_filename_array(&cfg, @@ -2837,6 +2850,10 @@ sandbox_init_filter(void) get_datadir_fname2("keys", "secret_onion_key_ntor.old"), get_datadir_fname2("keys", "secret_onion_key.tmp"), get_datadir_fname2("keys", "secret_id_key.tmp"), + get_datadir_fname2("stats", "bridge-stats"), + get_datadir_fname2("stats", "bridge-stats.tmp"), + get_datadir_fname2("stats", "dirreq-stats"), + get_datadir_fname2("stats", "dirreq-stats.tmp"), get_datadir_fname("fingerprint"), get_datadir_fname("fingerprint.tmp"), get_datadir_fname("hashed-fingerprint"), @@ -2847,12 +2864,19 @@ sandbox_init_filter(void) NULL, 0 ); + if (options->DirPortFrontPage) { + sandbox_cfg_allow_open_filename(&cfg, + tor_strdup(options->DirPortFrontPage)); + } + RENAME_SUFFIX("fingerprint", ".tmp"); RENAME_SUFFIX2("keys", "secret_onion_key_ntor", ".tmp"); RENAME_SUFFIX2("keys", "secret_id_key", ".tmp"); RENAME_SUFFIX2("keys", "secret_id_key.old", ".tmp"); RENAME_SUFFIX2("keys", "secret_onion_key", ".tmp"); RENAME_SUFFIX2("keys", "secret_onion_key.old", ".tmp"); + RENAME_SUFFIX2("stats", "bridge-stats", ".tmp"); + RENAME_SUFFIX2("stats", "dirreq-stats", ".tmp"); RENAME_SUFFIX("hashed-fingerprint", ".tmp"); RENAME_SUFFIX("router-stability", ".tmp"); @@ -2865,7 +2889,7 @@ sandbox_init_filter(void) sandbox_cfg_allow_stat_filename_array(&cfg, get_datadir_fname("keys"), - get_datadir_fname("stats/dirreq-stats"), + get_datadir_fname2("stats", "dirreq-stats"), NULL, 0 ); } @@ -2944,7 +2968,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/microdesc.c b/src/or/microdesc.c index ec85de0d6b..fdb549a9ac 100644 --- a/src/or/microdesc.c +++ b/src/or/microdesc.c @@ -386,18 +386,21 @@ microdesc_cache_clean(microdesc_cache_t *cache, time_t cutoff, int force) smartlist_t *nodes = nodelist_find_nodes_with_microdesc(*mdp); const networkstatus_t *ns = networkstatus_get_latest_consensus(); long networkstatus_age = -1; + const int ht_badness = HT_REP_IS_BAD_(microdesc_map, &cache->map); if (ns) { networkstatus_age = now - ns->valid_after; } log_warn(LD_BUG, "Microdescriptor seemed very old " "(last listed %d hours ago vs %d hour cutoff), but is still " "marked as being held by %d node(s). I found %d node(s) " - "holding it. Current networkstatus is %ld hours old.", + "holding it. Current networkstatus is %ld hours old. " + "Hashtable badness is %d.", (int)((now - (*mdp)->last_listed) / 3600), (int)((now - cutoff) / 3600), held_by_nodes, smartlist_len(nodes), - networkstatus_age / 3600); + networkstatus_age / 3600, + ht_badness); SMARTLIST_FOREACH_BEGIN(nodes, const node_t *, node) { const char *rs_match = "No RS"; @@ -664,8 +667,10 @@ microdesc_free_(microdesc_t *md, const char *fname, int lineno) tor_fragile_assert(); } if (md->held_by_nodes) { + microdesc_cache_t *cache = get_microdesc_cache(); int found=0; const smartlist_t *nodes = nodelist_get_list(); + const int ht_badness = HT_REP_IS_BAD_(microdesc_map, &cache->map); SMARTLIST_FOREACH(nodes, node_t *, node, { if (node->md == md) { ++found; @@ -674,12 +679,13 @@ microdesc_free_(microdesc_t *md, const char *fname, int lineno) }); if (found) { log_warn(LD_BUG, "microdesc_free() called from %s:%d, but md was still " - "referenced %d node(s); held_by_nodes == %u", - fname, lineno, found, md->held_by_nodes); + "referenced %d node(s); held_by_nodes == %u, ht_badness == %d", + fname, lineno, found, md->held_by_nodes, ht_badness); } else { log_warn(LD_BUG, "microdesc_free() called from %s:%d with held_by_nodes " - "set to %u, but md was not referenced by any nodes", - fname, lineno, md->held_by_nodes); + "set to %u, but md was not referenced by any nodes. " + "ht_badness == %d", + fname, lineno, md->held_by_nodes, ht_badness); } tor_fragile_assert(); } diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index ef450073e7..890da0ad17 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; @@ -829,7 +830,7 @@ update_consensus_networkstatus_fetch_time_impl(time_t now, int flav) if (directory_fetches_dir_info_early(options)) { /* We want to cache the next one at some point after this one * is no longer fresh... */ - start = c->fresh_until + min_sec_before_caching; + start = (time_t)(c->fresh_until + min_sec_before_caching); /* Some clients may need the consensus sooner than others. */ if (options->FetchDirInfoExtraEarly || authdir_mode_v3(options)) { dl_interval = 60; @@ -842,7 +843,7 @@ update_consensus_networkstatus_fetch_time_impl(time_t now, int flav) } else { /* We're an ordinary client or a bridge. Give all the caches enough * time to download the consensus. */ - start = c->fresh_until + (interval*3)/4; + start = (time_t)(c->fresh_until + (interval*3)/4); /* But download the next one well before this one is expired. */ dl_interval = ((c->valid_until - start) * 7 )/ 8; @@ -850,7 +851,7 @@ update_consensus_networkstatus_fetch_time_impl(time_t now, int flav) * to choose the rest of the interval *after* them. */ if (directory_fetches_dir_info_later(options)) { /* Give all the *clients* enough time to download the consensus. */ - start = start + dl_interval + min_sec_before_caching; + start = (time_t)(start + dl_interval + min_sec_before_caching); /* But try to get it before ours actually expires. */ dl_interval = (c->valid_until - start) - min_sec_before_caching; } diff --git a/src/or/networkstatus.h b/src/or/networkstatus.h index 1659818f0a..be0a86cdd8 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 a38a6d4993..09232f9f99 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 72571b7bd9..ae39f451f4 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 8e778dbc63..38b62decc3 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 9cf7d5dd6e..ef501f69da 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 3782e75abf..9a9f374b93 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 701877c64b..6aa6b59e8e 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -3231,20 +3231,33 @@ typedef struct or_circuit_rendinfo_s { /** Convert a circuit_t* to a pointer to the enclosing or_circuit_t. Assert * if the cast is impossible. */ static or_circuit_t *TO_OR_CIRCUIT(circuit_t *); +static const or_circuit_t *CONST_TO_OR_CIRCUIT(const circuit_t *); /** Convert a circuit_t* to a pointer to the enclosing origin_circuit_t. * Assert if the cast is impossible. */ static origin_circuit_t *TO_ORIGIN_CIRCUIT(circuit_t *); +static const origin_circuit_t *CONST_TO_ORIGIN_CIRCUIT(const circuit_t *); static INLINE or_circuit_t *TO_OR_CIRCUIT(circuit_t *x) { tor_assert(x->magic == OR_CIRCUIT_MAGIC); return DOWNCAST(or_circuit_t, x); } +static INLINE const or_circuit_t *CONST_TO_OR_CIRCUIT(const circuit_t *x) +{ + tor_assert(x->magic == OR_CIRCUIT_MAGIC); + return DOWNCAST(or_circuit_t, x); +} static INLINE origin_circuit_t *TO_ORIGIN_CIRCUIT(circuit_t *x) { tor_assert(x->magic == ORIGIN_CIRCUIT_MAGIC); return DOWNCAST(origin_circuit_t, x); } +static INLINE const origin_circuit_t *CONST_TO_ORIGIN_CIRCUIT( + const circuit_t *x) +{ + tor_assert(x->magic == ORIGIN_CIRCUIT_MAGIC); + return DOWNCAST(origin_circuit_t, x); +} /** Bitfield type: things that we're willing to use invalid routers for. */ typedef enum invalid_router_usage_t { @@ -3873,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 @@ -4961,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 70be39e230..5446c25e36 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. */ @@ -1051,7 +931,7 @@ correct_time(time_t t, time_t now, time_t stored_at, time_t started_measuring) return 0; else { long run_length = stored_at - t; - t = now - run_length; + t = (time_t)(now - run_length); if (t < started_measuring) t = started_measuring; return t; @@ -1212,7 +1092,7 @@ rep_hist_load_mtbf_data(time_t now) hist->start_of_run = correct_time(start_of_run, now, stored_at, tracked_since); if (hist->start_of_run < latest_possible_start + wrl) - latest_possible_start = hist->start_of_run - wrl; + latest_possible_start = (time_t)(hist->start_of_run - wrl); hist->weighted_run_length = wrl; hist->total_run_weights = trw; @@ -2431,7 +2311,7 @@ rep_hist_buffer_stats_add_circ(circuit_t *circ, time_t end_of_interval) return; start_of_interval = (circ->timestamp_created.tv_sec > start_of_buffer_stats_interval) ? - circ->timestamp_created.tv_sec : + (time_t)circ->timestamp_created.tv_sec : start_of_buffer_stats_interval; interval_length = (int) (end_of_interval - start_of_interval); if (interval_length <= 0) @@ -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 df01ae6cb3..cd6231e6e4 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/router.c b/src/or/router.c index 86cefc9a6f..2cdbb0c8bb 100755 --- a/src/or/router.c +++ b/src/or/router.c @@ -1267,7 +1267,8 @@ router_perform_bandwidth_test(int num_circs, time_t now) } /** Return true iff our network is in some sense disabled: either we're - * hibernating, entering hibernation, or */ + * hibernating, entering hibernation, or the network is turned off with + * DisableNetwork. */ int net_is_disabled(void) { diff --git a/src/or/routerlist.c b/src/or/routerlist.c index c15274e991..8f3477a4a4 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/routerparse.c b/src/or/routerparse.c index 14f800e7be..5add728d6d 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -4129,11 +4129,13 @@ microdescs_parse_from_string(const char *s, const char *eos, microdesc_free(md); md = NULL; + SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); memarea_clear(area); smartlist_clear(tokens); s = start_of_next_microdesc; } + SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); memarea_drop_all(area); smartlist_free(tokens); diff --git a/src/or/statefile.c b/src/or/statefile.c index da31341712..7b9998fc1a 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 c1413ff952..15bb0b4aae 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/or/status.c b/src/or/status.c index 7e2afbce80..afaa9de840 100644 --- a/src/or/status.c +++ b/src/or/status.c @@ -9,6 +9,7 @@ #define STATUS_PRIVATE #include "or.h" +#include "circuituse.h" #include "config.h" #include "status.h" #include "nodelist.h" @@ -135,6 +136,8 @@ log_heartbeat(time_t now) if (public_server_mode(options)) rep_hist_log_circuit_handshake_stats(now); + circuit_log_ancient_one_hop_circuits(1800); + tor_free(uptime); tor_free(bw_sent); tor_free(bw_rcvd); diff --git a/src/test/bench.c b/src/test/bench.c index c9cc101b72..f6c33626f2 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 b49f946827..8bce9c91f4 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... @@ -61,6 +62,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" @@ -418,9 +420,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); @@ -440,6 +443,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)); @@ -450,6 +454,7 @@ test_onion_queues(void) circuit_free(TO_CIRCUIT(circ2)); tor_free(create1); tor_free(create2); + tor_free(onionskin); } static void @@ -468,14 +473,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) @@ -507,8 +512,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, @@ -597,7 +603,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. */ @@ -948,6 +957,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. */ @@ -1010,6 +1020,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.h b/src/test/test.h index 0ccf6c718e..861ce5ac3e 100644 --- a/src/test/test.h +++ b/src/test/test.h @@ -59,6 +59,29 @@ tt_assert_test_type(a,b,#a" "#op" "#b,double,(val1_ op val2_),"%f", \ TT_EXIT_TEST_FUNCTION) +#ifdef _MSC_VER +#define U64_PRINTF_TYPE uint64_t +#define U64_PRINTF_TYPE int64_t +#else +#define U64_PRINTF_TYPE unsigned long long +#define I64_PRINTF_TYPE long long +#endif + +#define tt_size_op(a,op,b) \ + tt_assert_test_fmt_type(a,b,#a" "#op" "#b,size_t,(val1_ op val2_), \ + U64_PRINTF_TYPE, U64_FORMAT, \ + {print_ = (U64_PRINTF_TYPE) value_;}, {}, TT_EXIT_TEST_FUNCTION) + +#define tt_u64_op(a,op,b) \ + tt_assert_test_fmt_type(a,b,#a" "#op" "#b,uint64_t,(val1_ op val2_), \ + U64_PRINTF_TYPE, U64_FORMAT, \ + {print_ = (U64_PRINTF_TYPE) value_;}, {}, TT_EXIT_TEST_FUNCTION) + +#define tt_i64_op(a,op,b) \ + tt_assert_test_fmt_type(a,b,#a" "#op" "#b,int64_t,(val1_ op val2_), \ + I64_PRINTF_TYPE, I64_FORMAT, \ + {print_ = (I64_PRINTF_TYPE) value_;}, {}, TT_EXIT_TEST_FUNCTION) + const char *get_fname(const char *name); crypto_pk_t *pk_generate(int idx); diff --git a/src/test/test_buffers.c b/src/test/test_buffers.c index c2cfd2700f..61ac5bc36b 100644 --- a/src/test/test_buffers.c +++ b/src/test/test_buffers.c @@ -222,7 +222,7 @@ test_buffer_pullup(void *arg) buf_pullup(buf, 16, 1); buf_get_first_chunk_data(buf, &cp, &sz); tt_ptr_op(cp, ==, NULL); - tt_ptr_op(sz, ==, 0); + tt_uint_op(sz, ==, 0); /* Let's make sure nothing got allocated */ tt_int_op(buf_get_total_allocation(), ==, 0); @@ -522,6 +522,7 @@ test_buffer_allocation_tracking(void *arg) buf_free(buf1); buf_free(buf2); buf_shrink_freelists(1); + tor_free(junk); } static void @@ -596,6 +597,124 @@ test_buffer_time_tracking(void *arg) buf_free(buf2); } +static void +test_buffers_zlib_impl(int finalize_with_nil) +{ + 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; + int done; + + 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); + done = !finalize_with_nil; + tt_int_op(write_to_buf_zlib(buf, zlib_state, "all done", 9, done), ==, 0); + if (finalize_with_nil) { + tt_int_op(write_to_buf_zlib(buf, zlib_state, "", 0, 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); +} + +static void +test_buffers_zlib(void *arg) +{ + (void) arg; + test_buffers_zlib_impl(0); +} +static void +test_buffers_zlib_fin_with_nil(void *arg) +{ + (void) arg; + test_buffers_zlib_impl(1); +} + +static void +test_buffers_zlib_fin_at_chunk_end(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; + size_t sz, headerjunk; + (void) arg; + + buf = buf_new_with_capacity(128); /* will round up */ + sz = buf_get_default_chunk_size(buf); + msg = tor_malloc_zero(sz); + + write_to_buf(msg, 1, buf); + tt_assert(buf->head); + + /* Fill up the chunk so the zlib stuff won't fit in one chunk. */ + tt_uint_op(buf->head->memlen, <, sz); + headerjunk = buf->head->memlen - 7; + write_to_buf(msg, headerjunk-1, buf); + tt_uint_op(buf->head->datalen, ==, headerjunk); + printf("<%u>\n", (unsigned)buf_datalen(buf)); + tt_uint_op(buf_datalen(buf), ==, headerjunk); + /* Write an empty string, with finalization on. */ + zlib_state = tor_zlib_new(1, ZLIB_METHOD); + tt_int_op(write_to_buf_zlib(buf, zlib_state, "", 0, 1), ==, 0); + + printf("<%u>\n", (unsigned)buf_datalen(buf)); + + in_len = buf_datalen(buf); + contents = tor_malloc(in_len); + + tt_int_op(fetch_from_buf(contents, in_len, buf), ==, 0); + + tt_uint_op(in_len, >, headerjunk); + + tt_int_op(0, ==, tor_gzip_uncompress(&expanded, &out_len, + contents + headerjunk, in_len - headerjunk, + ZLIB_METHOD, 1, + LOG_WARN)); + + tt_int_op(out_len, ==, 0); + tt_assert(expanded); + + 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 }, @@ -604,6 +723,10 @@ 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 }, + { "zlib_fin_with_nil", test_buffers_zlib_fin_with_nil, TT_FORK, NULL, NULL }, + { "zlib_fin_at_chunk_end", test_buffers_zlib_fin_at_chunk_end, TT_FORK, + NULL, NULL}, END_OF_TESTCASES }; diff --git a/src/test/test_cell_formats.c b/src/test/test_cell_formats.c index b0eb2fca25..d7f60680c2 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 ad8d0ac3af..b19edd1fd4 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" @@ -51,7 +53,7 @@ circuitmux_detach_mock(circuitmux_t *cmux, circuit_t *circ) tt_int_op(cam.ncalls, ==, 1); \ tt_ptr_op(cam.cmux, ==, (mux_)); \ tt_ptr_op(cam.circ, ==, (circ_)); \ - tt_ptr_op(cam.dir, ==, (dir_)); \ + tt_int_op(cam.dir, ==, (dir_)); \ memset(&cam, 0, sizeof(cam)); \ } while (0) @@ -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 dbb50798b8..94ac4dca13 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 3a9aeca2f0..b45e97a417 100644 --- a/src/test/test_controller_events.c +++ b/src/test/test_controller_events.c @@ -118,26 +118,26 @@ test_cntev_sum_up_cell_stats(void *arg) cell_stats = tor_malloc_zero(sizeof(cell_stats_t)); add_testing_cell_stats_entry(circ, CELL_RELAY, 0, 0, 0); sum_up_cell_stats_by_command(circ, cell_stats); - tt_int_op(1, ==, cell_stats->added_cells_appward[CELL_RELAY]); + tt_u64_op(1, ==, cell_stats->added_cells_appward[CELL_RELAY]); /* A single RELAY cell was added to the exitward queue. */ add_testing_cell_stats_entry(circ, CELL_RELAY, 0, 0, 1); sum_up_cell_stats_by_command(circ, cell_stats); - tt_int_op(1, ==, cell_stats->added_cells_exitward[CELL_RELAY]); + tt_u64_op(1, ==, cell_stats->added_cells_exitward[CELL_RELAY]); /* A single RELAY cell was removed from the appward queue where it spent * 20 msec. */ add_testing_cell_stats_entry(circ, CELL_RELAY, 2, 1, 0); sum_up_cell_stats_by_command(circ, cell_stats); - tt_int_op(20, ==, cell_stats->total_time_appward[CELL_RELAY]); - tt_int_op(1, ==, cell_stats->removed_cells_appward[CELL_RELAY]); + tt_u64_op(20, ==, cell_stats->total_time_appward[CELL_RELAY]); + tt_u64_op(1, ==, cell_stats->removed_cells_appward[CELL_RELAY]); /* A single RELAY cell was removed from the exitward queue where it * spent 30 msec. */ add_testing_cell_stats_entry(circ, CELL_RELAY, 3, 1, 1); sum_up_cell_stats_by_command(circ, cell_stats); - tt_int_op(30, ==, cell_stats->total_time_exitward[CELL_RELAY]); - tt_int_op(1, ==, cell_stats->removed_cells_exitward[CELL_RELAY]); + tt_u64_op(30, ==, cell_stats->total_time_exitward[CELL_RELAY]); + tt_u64_op(1, ==, cell_stats->removed_cells_exitward[CELL_RELAY]); done: tor_free(cell_stats); @@ -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_crypto.c b/src/test/test_crypto.c index 1fda334760..5d8edb6550 100644 --- a/src/test/test_crypto.c +++ b/src/test/test_crypto.c @@ -1132,7 +1132,8 @@ test_crypto_curve25519_persist(void *arg) content = read_file_to_str(fname, RFTS_BIN, &st); tt_assert(content); taglen = strlen("== c25519v1: testing =="); - tt_int_op(st.st_size, ==, 32+CURVE25519_PUBKEY_LEN+CURVE25519_SECKEY_LEN); + tt_u64_op((uint64_t)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; diff --git a/src/test/test_dir.c b/src/test/test_dir.c index 9e01bdbd48..c03b63be27 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( @@ -1064,7 +1066,7 @@ test_vrs_for_v3ns(vote_routerstatus_t *vrs, int voter, time_t now) test_eq(rs->or_port, 443); test_eq(rs->dir_port, 8000); /* no flags except "running" (16) and "v2dir" (64) */ - test_eq(vrs->flags, U64_LITERAL(80)); + tt_u64_op(vrs->flags, ==, U64_LITERAL(80)); } else if (tor_memeq(rs->identity_digest, "\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5" "\x5\x5\x5\x5", @@ -1090,10 +1092,10 @@ test_vrs_for_v3ns(vote_routerstatus_t *vrs, int voter, time_t now) test_eq(rs->ipv6_orport, 4711); if (voter == 1) { /* all except "authority" (1) and "v2dir" (64) */ - test_eq(vrs->flags, U64_LITERAL(190)); + tt_u64_op(vrs->flags, ==, U64_LITERAL(190)); } else { /* 1023 - authority(1) - madeofcheese(16) - madeoftin(32) - v2dir(256) */ - test_eq(vrs->flags, U64_LITERAL(718)); + tt_u64_op(vrs->flags, ==, U64_LITERAL(718)); } } else if (tor_memeq(rs->identity_digest, "\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33" @@ -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")); @@ -1771,7 +1775,7 @@ test_dir_random_weighted(void *testdata) inp[i].u64 = vals[i]; total += vals[i]; } - tt_int_op(total, ==, 45); + tt_u64_op(total, ==, 45); for (i=0; i<n; ++i) { choice = choose_array_element_by_weight(inp, 10); tt_int_op(choice, >=, 0); @@ -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 f91ac7415e..93c8f77d5b 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"); @@ -201,7 +202,7 @@ test_ext_or_init_auth(void *arg) tt_int_op(ext_or_auth_cookie_is_set, ==, 1); cp = read_file_to_str(fn, RFTS_BIN, &st); tt_ptr_op(cp, !=, NULL); - tt_int_op(st.st_size, ==, 64); + tt_u64_op((uint64_t)st.st_size, ==, 64); test_memeq(cp, "! Extended ORPort Auth Cookie !\x0a", 32); test_memeq(cp+32, ext_or_auth_cookie, 32); memcpy(cookie0, ext_or_auth_cookie, 32); @@ -337,7 +338,7 @@ test_ext_or_cookie_auth_testvec(void *arg) handle_client_auth_nonce(client_nonce, 32, &client_hash, &reply, &reply_len)); tt_ptr_op(reply, !=, NULL ); - tt_ptr_op(reply_len, ==, 64); + tt_uint_op(reply_len, ==, 64); test_memeq(reply+32, "te road There is always another ", 32); /* HMACSHA256("Gliding wrapt in a brown mantle," * "ExtORPort authentication server-to-client hash" diff --git a/src/test/test_microdesc.c b/src/test/test_microdesc.c index 53a03a48ad..78f4823b87 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 1afe3fd162..32f4803bba 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" @@ -226,6 +227,7 @@ test_oom_streambuf(void *arg) struct timeval tv = { 1389641159, 0 }; uint32_t tvms; int i; + smartlist_t *edgeconns = smartlist_new(); (void) arg; @@ -270,17 +272,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); } @@ -315,6 +321,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); @@ -350,6 +357,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 e3e7b36733..4cdcd034bb 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 3277921052..f71627df1e 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 1c8174b065..182e0f6f87 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 b704053d04..46dd473132 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 eadbf730ea..c7fa141188 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -153,7 +153,7 @@ test_util_write_chunks_to_file(void *arg) // assert the file has been written (expected size) str = read_file_to_str(fname, RFTS_BIN, &st); tt_assert(str != NULL); - tt_int_op(st.st_size, ==, data_str_len); + tt_u64_op((uint64_t)st.st_size, ==, data_str_len); test_mem_op(data_str, ==, str, data_str_len); tor_free(str); @@ -184,14 +184,14 @@ test_util_write_chunks_to_file(void *arg) // assert the file has been written (expected size) str = read_file_to_str(fname, RFTS_BIN, &st); tt_assert(str != NULL); - tt_int_op(st.st_size, ==, data_str_len); + tt_u64_op((uint64_t)st.st_size, ==, data_str_len); test_mem_op(data_str, ==, str, data_str_len); tor_free(str); // assert the tempfile still contains the known string str = read_file_to_str(tempname, RFTS_BIN, &st); tt_assert(str != NULL); - tt_int_op(st.st_size, ==, temp_str_len); + tt_u64_op((uint64_t)st.st_size, ==, temp_str_len); test_mem_op(temp_str, ==, str, temp_str_len); done: @@ -346,7 +346,7 @@ test_util_time(void) tv.tv_sec = (time_t)1326296338; tv.tv_usec = 3060; - format_iso_time(timestr, tv.tv_sec); + format_iso_time(timestr, (time_t)tv.tv_sec); test_streq("2012-01-11 15:38:58", timestr); /* The output of format_local_iso_time will vary by timezone, and setting our timezone for testing purposes would be a nontrivial flaky pain. @@ -354,7 +354,7 @@ test_util_time(void) format_local_iso_time(timestr, tv.tv_sec); test_streq("2012-01-11 10:38:58", timestr); */ - format_iso_time_nospace(timestr, tv.tv_sec); + format_iso_time_nospace(timestr, (time_t)tv.tv_sec); test_streq("2012-01-11T15:38:58", timestr); test_eq(strlen(timestr), ISO_TIME_LEN); format_iso_time_nospace_usec(timestr, &tv); @@ -1092,7 +1092,7 @@ test_util_strmisc(void) test_eq(i, 0); test_eq(0UL, tor_parse_ulong(TOOBIG, 10, 0, ULONG_MAX, &i, NULL)); test_eq(i, 0); - test_eq(U64_LITERAL(0), tor_parse_uint64(TOOBIG, 10, + tt_u64_op(U64_LITERAL(0), ==, tor_parse_uint64(TOOBIG, 10, 0, UINT64_MAX, &i, NULL)); test_eq(i, 0); } @@ -1290,21 +1290,21 @@ test_util_pow2(void) test_eq(tor_log2(UINT64_MAX), 63); /* Test round_to_power_of_2 */ - test_eq(round_to_power_of_2(120), 128); - test_eq(round_to_power_of_2(128), 128); - test_eq(round_to_power_of_2(130), 128); - test_eq(round_to_power_of_2(U64_LITERAL(40000000000000000)), - U64_LITERAL(1)<<55); - test_eq(round_to_power_of_2(U64_LITERAL(0xffffffffffffffff)), + tt_u64_op(round_to_power_of_2(120), ==, 128); + tt_u64_op(round_to_power_of_2(128), ==, 128); + tt_u64_op(round_to_power_of_2(130), ==, 128); + tt_u64_op(round_to_power_of_2(U64_LITERAL(40000000000000000)), ==, + U64_LITERAL(1)<<55); + tt_u64_op(round_to_power_of_2(U64_LITERAL(0xffffffffffffffff)), ==, U64_LITERAL(1)<<63); - test_eq(round_to_power_of_2(0), 1); - test_eq(round_to_power_of_2(1), 1); - test_eq(round_to_power_of_2(2), 2); - test_eq(round_to_power_of_2(3), 2); - test_eq(round_to_power_of_2(4), 4); - test_eq(round_to_power_of_2(5), 4); - test_eq(round_to_power_of_2(6), 4); - test_eq(round_to_power_of_2(7), 8); + tt_u64_op(round_to_power_of_2(0), ==, 1); + tt_u64_op(round_to_power_of_2(1), ==, 1); + tt_u64_op(round_to_power_of_2(2), ==, 2); + tt_u64_op(round_to_power_of_2(3), ==, 2); + tt_u64_op(round_to_power_of_2(4), ==, 4); + tt_u64_op(round_to_power_of_2(5), ==, 4); + tt_u64_op(round_to_power_of_2(6), ==, 4); + tt_u64_op(round_to_power_of_2(7), ==, 8); done: ; @@ -2247,18 +2247,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); @@ -3149,6 +3152,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; @@ -3628,17 +3633,17 @@ test_util_max_mem(void *arg) r = get_total_system_memory(&memory1); r2 = get_total_system_memory(&memory2); tt_int_op(r, ==, r2); - tt_int_op(memory2, ==, memory1); + tt_uint_op(memory2, ==, memory1); TT_BLATHER(("System memory: "U64_FORMAT, U64_PRINTF_ARG(memory1))); if (r==0) { /* You have at least a megabyte. */ - tt_int_op(memory1, >, (1<<20)); + tt_uint_op(memory1, >, (1<<20)); } else { /* You do not have a petabyte. */ #if SIZEOF_SIZE_T == SIZEOF_UINT64_T - tt_int_op(memory1, <, (U64_LITERAL(1)<<50)); + tt_uint_op(memory1, <, (U64_LITERAL(1)<<50)); #endif } |