diff options
44 files changed, 2337 insertions, 334 deletions
diff --git a/.gitignore b/.gitignore index 912b06e2c5..613920167d 100644 --- a/.gitignore +++ b/.gitignore @@ -174,6 +174,9 @@ cscope.* /src/test/test-child.exe /src/test/test-ntor-cl.exe /src/test/test_workqueue.exe +/src/test/test_zero_length_keys.sh +/src/test/test_ntor.sh +/src/test/test_bt.sh # /src/tools/ /src/tools/tor-checkkey diff --git a/changes/bug-15642-default-fallback-default-dirs b/changes/bug-15642-default-fallback-default-dirs new file mode 100644 index 0000000000..a1e194bf1e --- /dev/null +++ b/changes/bug-15642-default-fallback-default-dirs @@ -0,0 +1,10 @@ + o Minor bugfixes (configuration, unit tests): + - Only add the default fallback directories when the DirAuthorities, + AlternateDirAuthority, and FallbackDir directory config options + are set to their defaults. + The default fallback directory list is currently empty, this fix + will only change tor's behaviour when it has default fallback + directories. + Includes unit tests for consider_adding_dir_servers(). + Fixes bug 15642; bugfix on 90f6071d8dc0 in 0.2.4.7-alpha. + Patch by "teor". diff --git a/changes/bug-15771-reachability b/changes/bug-15771-reachability new file mode 100644 index 0000000000..aff6268efb --- /dev/null +++ b/changes/bug-15771-reachability @@ -0,0 +1,8 @@ + o Minor bugfixes (test networks) + - When self-testing reachability, use ExtendAllowPrivateAddresses + to determine if local/private addresses imply reachability. + The previous fix used TestingTorNetwork, which implies + ExtendAllowPrivateAddresses, but this excluded rare configs where + ExtendAllowPrivateAddresses is set but TestingTorNetwork is not. + Fixes bug 15771; bugfix on 0.2.6.1-alpha, bug #13924. + Patch by "teor", issue discovered by CJ Ess. diff --git a/changes/bug15546 b/changes/bug15546 new file mode 100644 index 0000000000..b33b0aa511 --- /dev/null +++ b/changes/bug15546 @@ -0,0 +1,4 @@ + o Minor bugfixes: + - For correctness, avoid modifying a constant string in + handle_control_postdescriptor. Fixes bug 15546; bugfix on + 0.1.1.16-rc.
\ No newline at end of file diff --git a/changes/bug15745 b/changes/bug15745 new file mode 100644 index 0000000000..6e4bfa4e31 --- /dev/null +++ b/changes/bug15745 @@ -0,0 +1,7 @@ + o Minor feature (HS popularity countermeasure): + - To avoid leaking HS popularity, don't cycle the introduction point + when we've handled a fixed number of INTRODUCE2 cells but instead + cycle it when a random value of introductions is reached thus making + it more difficult for an attacker to find out the amount of clients + that has passed through the introduction point for a specific HS. + Closes ticket 15745. diff --git a/changes/bug15759 b/changes/bug15759 new file mode 100644 index 0000000000..24c5eb0e74 --- /dev/null +++ b/changes/bug15759 @@ -0,0 +1,6 @@ + o Minor bugfixes (testing): + - Set the severity correctly when testing get_interface_addresses_ifaddrs() + and get_interface_addresses_win32(), so that the tests fail gracefully + instead of triggering an assertion. Fixes bug 15759; bugfix on + 0.2.6.3-alpha. Reported by Nicolas Derive. + diff --git a/changes/deprecated-libevents b/changes/deprecated-libevents new file mode 100644 index 0000000000..4ea017581a --- /dev/null +++ b/changes/deprecated-libevents @@ -0,0 +1,3 @@ + o New system requirements: + - Tor no longer includes workarounds for Libevent versions before 1.3e. + Libevent 2.0 or later is recommended. Closes ticket #15248. diff --git a/changes/feature15344 b/changes/feature15344 new file mode 100644 index 0000000000..3bd640a775 --- /dev/null +++ b/changes/feature15344 @@ -0,0 +1,3 @@ + o Minor features (testing): + - Integrate the ntor, backtrace and zero lengths keys tests into the + automake test suite. Closes ticket 15344. diff --git a/changes/feature15652 b/changes/feature15652 new file mode 100644 index 0000000000..61d2b222a6 --- /dev/null +++ b/changes/feature15652 @@ -0,0 +1,9 @@ + o Code simplifications and refactoring: + - Use our own Base64 encoder instead of OpenSSL's, to allow more control + over the output. Part of ticket 15652. + + o Removed code: + - Remove `USE_OPENSSL_BASE64` and the corresponding fallback code and + always use the internal Base64 decoder. The internal decoder has been + part of tor since tor-0.2.0.10-alpha, and no one should be using the + OpenSSL one. Part of ticket 15652. diff --git a/changes/ticket14840 b/changes/ticket14840 new file mode 100644 index 0000000000..a2103f2151 --- /dev/null +++ b/changes/ticket14840 @@ -0,0 +1,5 @@ + o Minor features: + - Add DirAuthority lines for default directory authorities to output + of the GETINFO config/defaults controller command if not already + present. Implements ticket 14840. + diff --git a/changes/ticket14845 b/changes/ticket14845 new file mode 100644 index 0000000000..d771f88bdd --- /dev/null +++ b/changes/ticket14845 @@ -0,0 +1,4 @@ + o Minor features (controller) + - Controllers can now use GETINFO hs/client/desc/id/... to + retrieve items from the client's hidden service descriptor + cache. Closes ticket 14845. diff --git a/configure.ac b/configure.ac index 2c9c7a343f..9c4f02d908 100644 --- a/configure.ac +++ b/configure.ac @@ -438,15 +438,6 @@ AC_SUBST(TOR_LIB_WS32) AC_SUBST(TOR_LIB_GDI) AC_SUBST(TOR_LIB_IPHLPAPI) -dnl We need to do this before we try our disgusting hack below. -AC_CHECK_HEADERS([sys/types.h]) - -dnl This is a disgusting hack so we safely include older libevent headers. -AC_CHECK_TYPE(u_int64_t, unsigned long long) -AC_CHECK_TYPE(u_int32_t, unsigned long) -AC_CHECK_TYPE(u_int16_t, unsigned short) -AC_CHECK_TYPE(u_int8_t, unsigned char) - tor_libevent_pkg_redhat="libevent" tor_libevent_pkg_debian="libevent-dev" tor_libevent_devpkg_redhat="libevent-devel" @@ -487,13 +478,10 @@ save_CPPFLAGS="$CPPFLAGS" LIBS="-levent $STATIC_LIBEVENT_FLAGS $TOR_LIB_WS32 $LIBS" LDFLAGS="$TOR_LDFLAGS_libevent $LDFLAGS" CPPFLAGS="$TOR_CPPFLAGS_libevent $CPPFLAGS" -AC_CHECK_FUNCS([event_get_version \ - event_get_version_number \ - event_get_method \ - event_set_log_callback \ +AC_CHECK_FUNCS([event_get_version_number \ evutil_secure_rng_set_urandom_device_file \ evutil_secure_rng_init \ - event_base_loopexit]) + ]) AC_CHECK_MEMBERS([struct event.min_heap_idx], , , [#include <event.h> ]) @@ -1662,6 +1650,9 @@ AC_CONFIG_FILES([ src/config/torrc.minimal scripts/maint/checkOptionDocs.pl scripts/maint/updateVersions.pl + src/test/test_zero_length_keys.sh + src/test/test_ntor.sh + src/test/test_bt.sh ]) if test x$asciidoc = xtrue && test "$ASCIIDOC" = "none" ; then diff --git a/doc/HACKING b/doc/HACKING index c74e293e0e..a144c4b96a 100644 --- a/doc/HACKING +++ b/doc/HACKING @@ -569,7 +569,7 @@ on dist-master. {blueness} at gentoo dot org {paul} at invizbox dot io {ondrej.mikle} at gmail dot com - {archlinux} at cryptocrack dot de + {lfleischer} at archlinux dot org 10) Add the version number to Trac. To do this, go to Trac, log in, select "Admin" near the top of the screen, then select "Versions" from diff --git a/src/common/compat_libevent.c b/src/common/compat_libevent.c index 15308dd4cb..a366b6c9c6 100644 --- a/src/common/compat_libevent.c +++ b/src/common/compat_libevent.c @@ -56,11 +56,6 @@ typedef uint32_t le_version_t; * it is. */ #define LE_OTHER V(0,0,99) -#if 0 -static le_version_t tor_get_libevent_version(const char **v_out); -#endif - -#if defined(HAVE_EVENT_SET_LOG_CALLBACK) || defined(RUNNING_DOXYGEN) /** A string which, if it appears in a libevent log, should be ignored. */ static const char *suppress_msg = NULL; /** Callback function passed to event_set_log() so we can intercept @@ -107,17 +102,6 @@ suppress_libevent_log_msg(const char *msg) { suppress_msg = msg; } -#else -void -configure_libevent_logging(void) -{ -} -void -suppress_libevent_log_msg(const char *msg) -{ - (void)msg; -} -#endif #ifndef HAVE_EVENT2_EVENT_H /** Work-alike replacement for event_new() on pre-Libevent-2.0 systems. */ @@ -275,19 +259,11 @@ tor_libevent_initialize(tor_libevent_cfg *torcfg) exit(1); } -#if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD) /* Making this a NOTICE for now so we can link bugs to a libevent versions * or methods better. */ log_info(LD_GENERAL, "Initialized libevent version %s using method %s. Good.", event_get_version(), tor_libevent_get_method()); -#else - log_notice(LD_GENERAL, - "Initialized old libevent (version 1.0b or earlier)."); - log_warn(LD_GENERAL, - "You have a *VERY* old version of libevent. It is likely to be buggy; " - "please build Tor with a more recent version."); -#endif #ifdef USE_BUFFEREVENTS tor_libevent_set_tick_timeout(torcfg->msec_per_tick); @@ -301,27 +277,14 @@ tor_libevent_get_base, (void)) return the_event_base; } -#ifndef HAVE_EVENT_BASE_LOOPEXIT -/** Replacement for event_base_loopexit on some very old versions of Libevent - * that we are not yet brave enough to deprecate. */ -int -tor_event_base_loopexit(struct event_base *base, struct timeval *tv) -{ - tor_assert(base == the_event_base); - return event_loopexit(tv); -} -#endif - /** Return the name of the Libevent backend we're using. */ const char * tor_libevent_get_method(void) { #ifdef HAVE_EVENT2_EVENT_H return event_base_get_method(the_event_base); -#elif defined(HAVE_EVENT_GET_METHOD) - return event_get_method(); #else - return "<unknown>"; + return event_get_method(); #endif } @@ -376,54 +339,12 @@ le_versions_compatibility(le_version_t v) return 5; } -#if 0 -/** Return the version number of the currently running version of Libevent. - * See le_version_t for info on the format. - */ -static le_version_t -tor_get_libevent_version(const char **v_out) -{ - const char *v; - le_version_t r; -#if defined(HAVE_EVENT_GET_VERSION_NUMBER) - v = event_get_version(); - r = event_get_version_number(); -#elif defined (HAVE_EVENT_GET_VERSION) - v = event_get_version(); - r = tor_decode_libevent_version(v); -#else - v = "pre-1.0c"; - r = LE_OLD; -#endif - if (v_out) - *v_out = v; - return r; -} -#endif - /** Return a string representation of the version of the currently running * version of Libevent. */ const char * tor_libevent_get_version_str(void) { -#ifdef HAVE_EVENT_GET_VERSION return event_get_version(); -#else - return "pre-1.0c"; -#endif -} - -/** - * Compare the current Libevent method and version to a list of versions - * which are known not to work. Warn the user as appropriate. - */ -void -tor_check_libevent_version(const char *m, int server, - const char **badness_out) -{ - (void) m; - (void) server; - *badness_out = NULL; } #if defined(LIBEVENT_VERSION) @@ -452,7 +373,7 @@ tor_check_libevent_header_compatibility(void) /* In libevent versions before 2.0, it's hard to keep binary compatibility * between upgrades, and unpleasant to detect when the version we compiled * against is unlike the version we have linked against. Here's how. */ -#if defined(HEADER_VERSION) && defined(HAVE_EVENT_GET_VERSION) +#if defined(HEADER_VERSION) /* We have a header-file version and a function-call version. Easy. */ if (strcmp(HEADER_VERSION, event_get_version())) { le_version_t v1, v2; @@ -474,7 +395,7 @@ tor_check_libevent_header_compatibility(void) else log_info(LD_GENERAL, "I think these versions are binary-compatible."); } -#elif defined(HAVE_EVENT_GET_VERSION) +#else /* event_get_version but no _EVENT_VERSION. We might be in 1.4.0-beta or earlier, where that's normal. To see whether we were compiled with an earlier version, let's see whether the struct event defines MIN_HEAP_IDX. @@ -504,9 +425,6 @@ tor_check_libevent_header_compatibility(void) } #endif -#elif defined(HEADER_VERSION) -#warn "_EVENT_VERSION is defined but not get_event_version(): Libevent is odd." -#else /* Your libevent is ancient. */ #endif } diff --git a/src/common/compat_libevent.h b/src/common/compat_libevent.h index 6bbfae0056..39181efb7b 100644 --- a/src/common/compat_libevent.h +++ b/src/common/compat_libevent.h @@ -52,12 +52,7 @@ periodic_timer_t *periodic_timer_new(struct event_base *base, void *data); void periodic_timer_free(periodic_timer_t *); -#ifdef HAVE_EVENT_BASE_LOOPEXIT #define tor_event_base_loopexit event_base_loopexit -#else -struct timeval; -int tor_event_base_loopexit(struct event_base *base, struct timeval *tv); -#endif /** Defines a configuration for using libevent with Tor: passed as an argument * to tor_libevent_initialize() to describe how we want to set up. */ @@ -74,8 +69,6 @@ typedef struct tor_libevent_cfg { void tor_libevent_initialize(tor_libevent_cfg *cfg); MOCK_DECL(struct event_base *, tor_libevent_get_base, (void)); const char *tor_libevent_get_method(void); -void tor_check_libevent_version(const char *m, int server, - const char **badness_out); void tor_check_libevent_header_compatibility(void); const char *tor_libevent_get_version_str(void); const char *tor_libevent_get_header_version_str(void); diff --git a/src/common/crypto.c b/src/common/crypto.c index f05be2e8bf..7857a54951 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -2317,8 +2317,40 @@ crypto_rand_int(unsigned int max) } } +/** Return a pseudorandom integer, chosen uniformly from the values <i>i</i> + * such that <b>min</b> <= <i>i</i> < <b>max</b>. + * + * <b>min</b> MUST be in range [0, <b>max</b>). + * <b>max</b> MUST be in range (min, INT_MAX]. + */ +int +crypto_rand_int_range(unsigned int min, unsigned int max) +{ + tor_assert(min < max); + tor_assert(max <= INT_MAX); + + /* The overflow is avoided here because crypto_rand_int() returns a value + * between 0 and (max - min) inclusive. */ + return min + crypto_rand_int(max - min); +} + +/** As crypto_rand_int_range, but supports uint64_t. */ +uint64_t +crypto_rand_uint64_range(uint64_t min, uint64_t max) +{ + tor_assert(min < max); + return min + crypto_rand_uint64(max - min); +} + +/** As crypto_rand_int_range, but supports time_t. */ +time_t +crypto_rand_time_range(time_t min, time_t max) +{ + return (time_t) crypto_rand_uint64_range(min, max); +} + /** Return a pseudorandom 64-bit integer, chosen uniformly from the values - * between 0 and <b>max</b>-1. */ + * between 0 and <b>max</b>-1 inclusive. */ uint64_t crypto_rand_uint64(uint64_t max) { @@ -2379,7 +2411,7 @@ crypto_random_hostname(int min_rand_len, int max_rand_len, const char *prefix, if (min_rand_len > max_rand_len) min_rand_len = max_rand_len; - randlen = min_rand_len + crypto_rand_int(max_rand_len - min_rand_len + 1); + randlen = crypto_rand_int_range(min_rand_len, max_rand_len+1); prefixlen = strlen(prefix); resultlen = prefixlen + strlen(suffix) + randlen + 16; @@ -2426,36 +2458,163 @@ smartlist_shuffle(smartlist_t *sl) } } +#define BASE64_OPENSSL_LINELEN 64 + +/** Return the Base64 encoded size of <b>srclen</b> bytes of data in + * bytes. + * + * If <b>flags</b>&BASE64_ENCODE_MULTILINE is true, return the size + * of the encoded output as multiline output (64 character, `\n' terminated + * lines). + */ +size_t +base64_encode_size(size_t srclen, int flags) +{ + size_t enclen; + tor_assert(srclen < INT_MAX); + + if (srclen == 0) + return 0; + + enclen = ((srclen - 1) / 3) * 4 + 4; + if (flags & BASE64_ENCODE_MULTILINE) { + size_t remainder = enclen % BASE64_OPENSSL_LINELEN; + enclen += enclen / BASE64_OPENSSL_LINELEN; + if (remainder) + enclen++; + } + tor_assert(enclen < INT_MAX && enclen > srclen); + return enclen; +} + +/** Internal table mapping 6 bit values to the Base64 alphabet. */ +static const char base64_encode_table[64] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '+', '/' +}; + /** Base64 encode <b>srclen</b> bytes of data from <b>src</b>. Write * the result into <b>dest</b>, if it will fit within <b>destlen</b> - * bytes. Return the number of bytes written on success; -1 if + * bytes. Return the number of bytes written on success; -1 if * destlen is too short, or other failure. + * + * If <b>flags</b>&BASE64_ENCODE_MULTILINE is true, return encoded + * output in multiline format (64 character, `\n' terminated lines). */ int -base64_encode(char *dest, size_t destlen, const char *src, size_t srclen) -{ - /* FFFF we might want to rewrite this along the lines of base64_decode, if - * it ever shows up in the profile. */ - EVP_ENCODE_CTX ctx; - int len, ret; - tor_assert(srclen < INT_MAX); +base64_encode(char *dest, size_t destlen, const char *src, size_t srclen, + int flags) +{ + const unsigned char *usrc = (unsigned char *)src; + const unsigned char *eous = usrc + srclen; + char *d = dest; + uint32_t n = 0; + size_t linelen = 0; + size_t enclen; + int n_idx = 0; + + if (!src || !dest) + return -1; - /* 48 bytes of input -> 64 bytes of output plus newline. - Plus one more byte, in case I'm wrong. - */ - if (destlen < ((srclen/48)+1)*66) + /* Ensure that there is sufficient space, including the NUL. */ + enclen = base64_encode_size(srclen, flags); + if (destlen < enclen + 1) return -1; if (destlen > SIZE_T_CEILING) return -1; + if (enclen > INT_MAX) + return -1; + + memset(dest, 0, enclen); + + /* XXX/Yawning: If this ends up being too slow, this can be sped up + * by separating the multiline format case and the normal case, and + * processing 48 bytes of input at a time when newlines are desired. + */ +#define ENCODE_CHAR(ch) \ + STMT_BEGIN \ + *d++ = ch; \ + if (flags & BASE64_ENCODE_MULTILINE) { \ + if (++linelen % BASE64_OPENSSL_LINELEN == 0) { \ + linelen = 0; \ + *d++ = '\n'; \ + } \ + } \ + STMT_END + +#define ENCODE_N(idx) \ + ENCODE_CHAR(base64_encode_table[(n >> ((3 - idx) * 6)) & 0x3f]) + +#define ENCODE_PAD() ENCODE_CHAR('=') + + /* Iterate over all the bytes in src. Each one will add 8 bits to the + * value we're encoding. Accumulate bits in <b>n</b>, and whenever we + * have 24 bits, batch them into 4 bytes and flush those bytes to dest. + */ + for ( ; usrc < eous; ++usrc) { + n = (n << 8) | *usrc; + if ((++n_idx) == 3) { + ENCODE_N(0); + ENCODE_N(1); + ENCODE_N(2); + ENCODE_N(3); + n_idx = 0; + n = 0; + } + } + switch (n_idx) { + case 0: + /* 0 leftover bits, no pading to add. */ + break; + case 1: + /* 8 leftover bits, pad to 12 bits, write the 2 6-bit values followed + * by 2 padding characters. + */ + n <<= 4; + ENCODE_N(2); + ENCODE_N(3); + ENCODE_PAD(); + ENCODE_PAD(); + break; + case 2: + /* 16 leftover bits, pad to 18 bits, write the 3 6-bit values followed + * by 1 padding character. + */ + n <<= 2; + ENCODE_N(1); + ENCODE_N(2); + ENCODE_N(3); + ENCODE_PAD(); + break; + default: + /* Something went catastrophically wrong. */ + tor_fragile_assert(); + return -1; + } - EVP_EncodeInit(&ctx); - EVP_EncodeUpdate(&ctx, (unsigned char*)dest, &len, - (unsigned char*)src, (int)srclen); - EVP_EncodeFinal(&ctx, (unsigned char*)(dest+len), &ret); - ret += len; - return ret; +#undef ENCODE_N +#undef ENCODE_PAD +#undef ENCODE_CHAR + + /* Multiline output always includes at least one newline. */ + if (flags & BASE64_ENCODE_MULTILINE && linelen != 0) + *d++ = '\n'; + + tor_assert(d - dest == (ptrdiff_t)enclen); + + *d++ = '\0'; /* NUL terminate the output. */ + + return (int) enclen; } +#undef BASE64_OPENSSL_LINELEN + /** @{ */ /** Special values used for the base64_decode_table */ #define X 255 @@ -2500,26 +2659,6 @@ static const uint8_t base64_decode_table[256] = { int base64_decode(char *dest, size_t destlen, const char *src, size_t srclen) { -#ifdef USE_OPENSSL_BASE64 - EVP_ENCODE_CTX ctx; - int len, ret; - /* 64 bytes of input -> *up to* 48 bytes of output. - Plus one more byte, in case I'm wrong. - */ - if (destlen < ((srclen/64)+1)*49) - return -1; - if (destlen > SIZE_T_CEILING) - return -1; - - memset(dest, 0, destlen); - - EVP_DecodeInit(&ctx); - EVP_DecodeUpdate(&ctx, (unsigned char*)dest, &len, - (unsigned char*)src, srclen); - EVP_DecodeFinal(&ctx, (unsigned char*)dest, &ret); - ret += len; - return ret; -#else const char *eos = src+srclen; uint32_t n=0; int n_idx=0; @@ -2590,20 +2729,19 @@ base64_decode(char *dest, size_t destlen, const char *src, size_t srclen) tor_assert((dest-dest_orig) <= INT_MAX); return (int)(dest-dest_orig); -#endif } #undef X #undef SP #undef PAD /** Base64 encode DIGEST_LINE bytes from <b>digest</b>, remove the trailing = - * and newline characters, and store the nul-terminated result in the first + * characters, and store the nul-terminated result in the first * BASE64_DIGEST_LEN+1 bytes of <b>d64</b>. */ int digest_to_base64(char *d64, const char *digest) { char buf[256]; - base64_encode(buf, sizeof(buf), digest, DIGEST_LEN); + base64_encode(buf, sizeof(buf), digest, DIGEST_LEN, 0); buf[BASE64_DIGEST_LEN] = '\0'; memcpy(d64, buf, BASE64_DIGEST_LEN+1); return 0; @@ -2615,33 +2753,20 @@ digest_to_base64(char *d64, const char *digest) int digest_from_base64(char *digest, const char *d64) { -#ifdef USE_OPENSSL_BASE64 - char buf_in[BASE64_DIGEST_LEN+3]; - char buf[256]; - if (strlen(d64) != BASE64_DIGEST_LEN) - return -1; - memcpy(buf_in, d64, BASE64_DIGEST_LEN); - memcpy(buf_in+BASE64_DIGEST_LEN, "=\n\0", 3); - if (base64_decode(buf, sizeof(buf), buf_in, strlen(buf_in)) != DIGEST_LEN) - return -1; - memcpy(digest, buf, DIGEST_LEN); - return 0; -#else if (base64_decode(digest, DIGEST_LEN, d64, strlen(d64)) == DIGEST_LEN) return 0; else return -1; -#endif } /** Base64 encode DIGEST256_LINE bytes from <b>digest</b>, remove the - * trailing = and newline characters, and store the nul-terminated result in - * the first BASE64_DIGEST256_LEN+1 bytes of <b>d64</b>. */ + * trailing = characters, and store the nul-terminated result in the first + * BASE64_DIGEST256_LEN+1 bytes of <b>d64</b>. */ int digest256_to_base64(char *d64, const char *digest) { char buf[256]; - base64_encode(buf, sizeof(buf), digest, DIGEST256_LEN); + base64_encode(buf, sizeof(buf), digest, DIGEST256_LEN, 0); buf[BASE64_DIGEST256_LEN] = '\0'; memcpy(d64, buf, BASE64_DIGEST256_LEN+1); return 0; @@ -2653,23 +2778,10 @@ digest256_to_base64(char *d64, const char *digest) int digest256_from_base64(char *digest, const char *d64) { -#ifdef USE_OPENSSL_BASE64 - char buf_in[BASE64_DIGEST256_LEN+3]; - char buf[256]; - if (strlen(d64) != BASE64_DIGEST256_LEN) - return -1; - memcpy(buf_in, d64, BASE64_DIGEST256_LEN); - memcpy(buf_in+BASE64_DIGEST256_LEN, "=\n\0", 3); - if (base64_decode(buf, sizeof(buf), buf_in, strlen(buf_in)) != DIGEST256_LEN) - return -1; - memcpy(digest, buf, DIGEST256_LEN); - return 0; -#else if (base64_decode(digest, DIGEST256_LEN, d64, strlen(d64)) == DIGEST256_LEN) return 0; else return -1; -#endif } /** Implements base32 encoding as in RFC 4648. Limitation: Requires diff --git a/src/common/crypto.h b/src/common/crypto.h index b9c26a4551..1ac02ea7a5 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -254,6 +254,9 @@ int crypto_seed_rng(int startup); MOCK_DECL(int,crypto_rand,(char *to, size_t n)); int crypto_strongest_rand(uint8_t *out, size_t out_len); int crypto_rand_int(unsigned int max); +int crypto_rand_int_range(unsigned int min, unsigned int max); +uint64_t crypto_rand_uint64_range(uint64_t min, uint64_t max); +time_t crypto_rand_time_range(time_t min, time_t max); uint64_t crypto_rand_uint64(uint64_t max); double crypto_rand_double(void); struct tor_weak_rng_t; @@ -267,7 +270,10 @@ struct smartlist_t; void *smartlist_choose(const struct smartlist_t *sl); void smartlist_shuffle(struct smartlist_t *sl); -int base64_encode(char *dest, size_t destlen, const char *src, size_t srclen); +#define BASE64_ENCODE_MULTILINE 1 +size_t base64_encode_size(size_t srclen, int flags); +int base64_encode(char *dest, size_t destlen, const char *src, size_t srclen, + int flags); int base64_decode(char *dest, size_t destlen, const char *src, size_t srclen); /** Characters that can appear (case-insensitively) in a base32 encoding. */ #define BASE32_CHARS "abcdefghijklmnopqrstuvwxyz234567" diff --git a/src/common/crypto_format.c b/src/common/crypto_format.c index 00e0e9ea85..35a7854404 100644 --- a/src/common/crypto_format.c +++ b/src/common/crypto_format.c @@ -19,7 +19,7 @@ curve25519_public_to_base64(char *output, { char buf[128]; base64_encode(buf, sizeof(buf), - (const char*)pkey->public_key, CURVE25519_PUBKEY_LEN); + (const char*)pkey->public_key, CURVE25519_PUBKEY_LEN, 0); buf[CURVE25519_BASE64_PADDED_LEN] = '\0'; memcpy(output, buf, CURVE25519_BASE64_PADDED_LEN+1); return 0; diff --git a/src/common/tortls.c b/src/common/tortls.c index 32106eb2df..bd7e95c033 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -659,7 +659,8 @@ tor_tls_create_certificate(crypto_pk_t *rsa, * than having it start right now. Don't choose quite uniformly, since * then we might pick a time where we're about to expire. Lastly, be * sure to start on a day boundary. */ - start_time = time(NULL) - crypto_rand_int(cert_lifetime) + 2*24*3600; + time_t now = time(NULL); + start_time = crypto_rand_time_range(now - cert_lifetime, now) + 2*24*3600; start_time -= start_time % (24*3600); tor_assert(rsa); diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 985234fded..0688398f6d 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -1400,9 +1400,12 @@ onionskin_answer(or_circuit_t *circ, log_debug(LD_CIRC,"Finished sending '%s' cell.", circ->is_first_hop ? "created_fast" : "created"); - /* Ignore the local bit when testing - many test networks run on local - * addresses */ - if ((!channel_is_local(circ->p_chan) || get_options()->TestingTorNetwork) + /* Ignore the local bit when ExtendAllowPrivateAddresses is set: + * it violates the assumption that private addresses are local. + * Also, many test networks run on local addresses, and + * TestingTorNetwork sets ExtendAllowPrivateAddresses. */ + if ((!channel_is_local(circ->p_chan) + || get_options()->ExtendAllowPrivateAddresses) && !channel_is_outgoing(circ->p_chan)) { /* record that we could process create cells from a non-local conn * that we didn't initiate; presumably this means that create cells diff --git a/src/or/config.c b/src/or/config.c index d7444d52f6..10304482e8 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -545,8 +545,6 @@ static char *get_bindaddr_from_transport_listen_line(const char *line, static int parse_dir_authority_line(const char *line, dirinfo_type_t required_type, int validate_only); -static int parse_dir_fallback_line(const char *line, - int validate_only); static void port_cfg_free(port_cfg_t *port); static int parse_ports(or_options_t *options, int validate_only, char **msg_out, int *n_ports_out); @@ -841,6 +839,41 @@ escaped_safe_str(const char *address) return escaped(address); } +/** List of default directory authorities */ + +static const char *default_authorities[] = { + "moria1 orport=9101 " + "v3ident=D586D18309DED4CD6D57C18FDB97EFA96D330566 " + "128.31.0.39:9131 9695 DFC3 5FFE B861 329B 9F1A B04C 4639 7020 CE31", + "tor26 orport=443 " + "v3ident=14C131DFC5C6F93646BE72FA1401C02A8DF2E8B4 " + "86.59.21.38:80 847B 1F85 0344 D787 6491 A548 92F9 0493 4E4E B85D", + "dizum orport=443 " + "v3ident=E8A9C45EDE6D711294FADF8E7951F4DE6CA56B58 " + "194.109.206.212:80 7EA6 EAD6 FD83 083C 538F 4403 8BBF A077 587D D755", + "Tonga orport=443 bridge " + "82.94.251.203:80 4A0C CD2D DC79 9508 3D73 F5D6 6710 0C8A 5831 F16D", + "gabelmoo orport=443 " + "v3ident=ED03BB616EB2F60BEC80151114BB25CEF515B226 " + "131.188.40.189:80 F204 4413 DAC2 E02E 3D6B CF47 35A1 9BCA 1DE9 7281", + "dannenberg orport=443 " + "v3ident=585769C78764D58426B8B52B6651A5A71137189A " + "193.23.244.244:80 7BE6 83E6 5D48 1413 21C5 ED92 F075 C553 64AC 7123", + "urras orport=80 " + "v3ident=80550987E1D626E3EBA5E5E75A458DE0626D088C " + "208.83.223.34:443 0AD3 FA88 4D18 F89E EA2D 89C0 1937 9E0E 7FD9 4417", + "maatuska orport=80 " + "v3ident=49015F787433103580E3B66A1707A00E60F2D15B " + "171.25.193.9:443 BD6A 8292 55CB 08E6 6FBE 7D37 4836 3586 E46B 3810", + "Faravahar orport=443 " + "v3ident=EFCBE720AB3A82B99F9E953CD5BF50F7EEFC7B97 " + "154.35.175.225:80 CF6D 0AAF B385 BE71 B8E1 11FC 5CFF 4B47 9237 33BC", + "longclaw orport=443 " + "v3ident=23D15D965BC35114467363C165C4F724B64B4F66 " + "199.254.238.52:80 74A9 1064 6BCE EFBC D2E8 74FC 1DC9 9743 0F96 8145", + NULL +}; + /** Add the default directory authorities directly into the trusted dir list, * but only add them insofar as they share bits with <b>type</b>. * Each authority's bits are restricted to the bits shared with <b>type</b>. @@ -849,50 +882,18 @@ static void add_default_trusted_dir_authorities(dirinfo_type_t type) { int i; - const char *authorities[] = { - "moria1 orport=9101 " - "v3ident=D586D18309DED4CD6D57C18FDB97EFA96D330566 " - "128.31.0.39:9131 9695 DFC3 5FFE B861 329B 9F1A B04C 4639 7020 CE31", - "tor26 orport=443 " - "v3ident=14C131DFC5C6F93646BE72FA1401C02A8DF2E8B4 " - "86.59.21.38:80 847B 1F85 0344 D787 6491 A548 92F9 0493 4E4E B85D", - "dizum orport=443 " - "v3ident=E8A9C45EDE6D711294FADF8E7951F4DE6CA56B58 " - "194.109.206.212:80 7EA6 EAD6 FD83 083C 538F 4403 8BBF A077 587D D755", - "Tonga orport=443 bridge " - "82.94.251.203:80 4A0C CD2D DC79 9508 3D73 F5D6 6710 0C8A 5831 F16D", - "gabelmoo orport=443 " - "v3ident=ED03BB616EB2F60BEC80151114BB25CEF515B226 " - "131.188.40.189:80 F204 4413 DAC2 E02E 3D6B CF47 35A1 9BCA 1DE9 7281", - "dannenberg orport=443 " - "v3ident=585769C78764D58426B8B52B6651A5A71137189A " - "193.23.244.244:80 7BE6 83E6 5D48 1413 21C5 ED92 F075 C553 64AC 7123", - "urras orport=80 " - "v3ident=80550987E1D626E3EBA5E5E75A458DE0626D088C " - "208.83.223.34:443 0AD3 FA88 4D18 F89E EA2D 89C0 1937 9E0E 7FD9 4417", - "maatuska orport=80 " - "v3ident=49015F787433103580E3B66A1707A00E60F2D15B " - "171.25.193.9:443 BD6A 8292 55CB 08E6 6FBE 7D37 4836 3586 E46B 3810", - "Faravahar orport=443 " - "v3ident=EFCBE720AB3A82B99F9E953CD5BF50F7EEFC7B97 " - "154.35.175.225:80 CF6D 0AAF B385 BE71 B8E1 11FC 5CFF 4B47 9237 33BC", - "longclaw orport=443 " - "v3ident=23D15D965BC35114467363C165C4F724B64B4F66 " - "199.254.238.52:80 74A9 1064 6BCE EFBC D2E8 74FC 1DC9 9743 0F96 8145", - NULL - }; - for (i=0; authorities[i]; i++) { - if (parse_dir_authority_line(authorities[i], type, 0)<0) { + for (i=0; default_authorities[i]; i++) { + if (parse_dir_authority_line(default_authorities[i], type, 0)<0) { log_err(LD_BUG, "Couldn't parse internal DirAuthority line %s", - authorities[i]); + default_authorities[i]); } } } /** Add the default fallback directory servers into the fallback directory * server list. */ -static void -add_default_fallback_dir_servers(void) +MOCK_IMPL(void, +add_default_fallback_dir_servers,(void)) { int i; const char *fallback[] = { @@ -961,7 +962,7 @@ validate_dir_servers(or_options_t *options, or_options_t *old_options) /** Look at all the config options and assign new dir authorities * as appropriate. */ -static int +int consider_adding_dir_servers(const or_options_t *options, const or_options_t *old_options) { @@ -979,23 +980,36 @@ consider_adding_dir_servers(const or_options_t *options, if (!need_to_update) return 0; /* all done */ + /* "You cannot set both DirAuthority and Alternate*Authority." + * Checking that this restriction holds allows us to simplify + * the unit tests. */ + tor_assert(!(options->DirAuthorities && + (options->AlternateDirAuthority + || options->AlternateBridgeAuthority))); + /* Start from a clean slate. */ clear_dir_servers(); if (!options->DirAuthorities) { /* then we may want some of the defaults */ dirinfo_type_t type = NO_DIRINFO; - if (!options->AlternateBridgeAuthority) + if (!options->AlternateBridgeAuthority) { type |= BRIDGE_DIRINFO; - if (!options->AlternateDirAuthority) + } + if (!options->AlternateDirAuthority) { type |= V3_DIRINFO | EXTRAINFO_DIRINFO | MICRODESC_DIRINFO; + /* Only add the default fallback directories when the DirAuthorities, + * AlternateDirAuthority, and FallbackDir directory config options + * are set to their defaults. */ + if (!options->FallbackDir) { + add_default_fallback_dir_servers(); + } + } /* if type == NO_DIRINFO, we don't want to add any of the * default authorities, because we've replaced them all */ if (type != NO_DIRINFO) add_default_trusted_dir_authorities(type); } - if (!options->FallbackDir) - add_default_fallback_dir_servers(); for (cl = options->DirAuthorities; cl; cl = cl->next) if (parse_dir_authority_line(cl->value, NO_DIRINFO, 0)<0) @@ -5495,7 +5509,7 @@ parse_dir_authority_line(const char *line, dirinfo_type_t required_type, * <b>validate_only</b> is 0, and the line is well-formed, then add the * dirserver described in the line as a fallback directory. Return 0 on * success, or -1 if the line isn't well-formed or if we can't add it. */ -static int +int parse_dir_fallback_line(const char *line, int validate_only) { @@ -6734,7 +6748,6 @@ get_num_cpus(const or_options_t *options) static void init_libevent(const or_options_t *options) { - const char *badness=NULL; tor_libevent_cfg cfg; tor_assert(options); @@ -6755,17 +6768,6 @@ init_libevent(const or_options_t *options) tor_libevent_initialize(&cfg); suppress_libevent_log_msg(NULL); - - tor_check_libevent_version(tor_libevent_get_method(), - server_mode(get_options()), - &badness); - if (badness) { - const char *v = tor_libevent_get_version_str(); - const char *m = tor_libevent_get_method(); - control_event_general_status(LOG_WARN, - "BAD_LIBEVENT VERSION=%s METHOD=%s BADNESS=%s RECOVERED=NO", - v, m, badness); - } } /** Return a newly allocated string holding a filename relative to the data @@ -6966,15 +6968,42 @@ getinfo_helper_config(control_connection_t *conn, smartlist_free(sl); } else if (!strcmp(question, "config/defaults")) { smartlist_t *sl = smartlist_new(); - int i; + int i, dirauth_lines_seen = 0; for (i = 0; option_vars_[i].name; ++i) { const config_var_t *var = &option_vars_[i]; if (var->initvalue != NULL) { - char *val = esc_for_log(var->initvalue); - smartlist_add_asprintf(sl, "%s %s\n",var->name,val); - tor_free(val); + if (strcmp(option_vars_[i].name, "DirAuthority") == 0) { + /* + * Count dirauth lines we have a default for; we'll use the + * count later to decide whether to add the defaults manually + */ + ++dirauth_lines_seen; + } + char *val = esc_for_log(var->initvalue); + smartlist_add_asprintf(sl, "%s %s\n",var->name,val); + tor_free(val); + } + } + + if (dirauth_lines_seen == 0) { + /* + * We didn't see any directory authorities with default values, + * so add the list of default authorities manually. + */ + const char **i; + + /* + * default_authorities is defined earlier in this file and + * is a const char ** NULL-terminated array of dirauth config + * lines. + */ + for (i = default_authorities; *i != NULL; ++i) { + char *val = esc_for_log(*i); + smartlist_add_asprintf(sl, "DirAuthority %s\n", val); + tor_free(val); } } + *answer = smartlist_join_strings(sl, "", 0, NULL); SMARTLIST_FOREACH(sl, char *, c, tor_free(c)); smartlist_free(sl); diff --git a/src/or/config.h b/src/or/config.h index b0b23bcfbd..74b28f45ca 100644 --- a/src/or/config.h +++ b/src/or/config.h @@ -144,6 +144,12 @@ STATIC int options_validate(or_options_t *old_options, STATIC int parse_transport_line(const or_options_t *options, const char *line, int validate_only, int server); +STATIC int consider_adding_dir_servers(const or_options_t *options, + const or_options_t *old_options); +MOCK_DECL(STATIC void, add_default_fallback_dir_servers, (void)); +STATIC int +parse_dir_fallback_line(const char *line, + int validate_only); #endif #endif diff --git a/src/or/connection.c b/src/or/connection.c index 369df67363..5610815589 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -4440,25 +4440,12 @@ alloc_http_authenticator(const char *authenticator) /* an authenticator in Basic authentication * is just the string "username:password" */ const size_t authenticator_length = strlen(authenticator); - /* The base64_encode function needs a minimum buffer length - * of 66 bytes. */ - const size_t base64_authenticator_length = (authenticator_length/48+1)*66; + const size_t base64_authenticator_length = + base64_encode_size(authenticator_length, 0) + 1; char *base64_authenticator = tor_malloc(base64_authenticator_length); if (base64_encode(base64_authenticator, base64_authenticator_length, - authenticator, authenticator_length) < 0) { + authenticator, authenticator_length, 0) < 0) { tor_free(base64_authenticator); /* free and set to null */ - } else { - int i = 0, j = 0; - ssize_t len = strlen(base64_authenticator); - - /* remove all newline occurrences within the string */ - for (i=0; i < len; ++i) { - if ('\n' != base64_authenticator[i]) { - base64_authenticator[j] = base64_authenticator[i]; - ++j; - } - } - base64_authenticator[j]='\0'; } return base64_authenticator; } diff --git a/src/or/control.c b/src/or/control.c index 313532432a..8c95b056b2 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -43,6 +43,8 @@ #include "router.h" #include "routerlist.h" #include "routerparse.h" +#include "rendclient.h" +#include "rendcommon.h" #ifndef _WIN32 #include <pwd.h> @@ -1718,6 +1720,22 @@ getinfo_helper_dir(control_connection_t *control_conn, *answer = smartlist_join_strings(sl, "", 0, NULL); SMARTLIST_FOREACH(sl, char *, c, tor_free(c)); smartlist_free(sl); + } else if (!strcmpstart(question, "hs/client/desc/id/")) { + rend_cache_entry_t *e = NULL; + + question += strlen("hs/client/desc/id/"); + if (strlen(question) != REND_SERVICE_ID_LEN_BASE32) { + *errmsg = "Invalid address"; + return -1; + } + + if (rend_cache_lookup_entry(question, -1, &e) > 0) { + /* Descriptor found in cache */ + *answer = tor_strdup(e->desc); + } else { + *errmsg = "Not found in cache"; + return -1; + } } else if (!strcmpstart(question, "md/id/")) { const node_t *node = node_get_by_hex_id(question+strlen("md/id/")); const microdesc_t *md = NULL; @@ -2221,6 +2239,8 @@ static const getinfo_item_t getinfo_items[] = { PREFIX("md/id/", dir, "Microdescriptors by ID"), PREFIX("md/name/", dir, "Microdescriptors by name"), PREFIX("extra-info/digest/", dir, "Extra-info documents by digest."), + PREFIX("hs/client/desc/id", dir, + "Hidden Service descriptor in client's cache by onion."), PREFIX("net/listeners/", listeners, "Bound addresses by type"), ITEM("ns/all", networkstatus, "Brief summary of router status (v2 directory format)"), @@ -2780,12 +2800,14 @@ handle_control_postdescriptor(control_connection_t *conn, uint32_t len, uint8_t purpose = ROUTER_PURPOSE_GENERAL; int cache = 0; /* eventually, we may switch this to 1 */ - char *cp = memchr(body, '\n', len); + const char *cp = memchr(body, '\n', len); smartlist_t *args = smartlist_new(); tor_assert(cp); - *cp++ = '\0'; + ++cp; - smartlist_split_string(args, body, " ", + char *cmdline = tor_memdup_nulterm(body, cp-body); + + smartlist_split_string(args, cmdline, " ", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); SMARTLIST_FOREACH_BEGIN(args, char *, option) { if (!strcasecmpstart(option, "purpose=")) { @@ -2834,6 +2856,7 @@ handle_control_postdescriptor(control_connection_t *conn, uint32_t len, done: SMARTLIST_FOREACH(args, char *, arg, tor_free(arg)); smartlist_free(args); + tor_free(cmdline); return 0; } diff --git a/src/or/dirvote.c b/src/or/dirvote.c index 7a5154dae5..3009026ee7 100644 --- a/src/or/dirvote.c +++ b/src/or/dirvote.c @@ -2244,7 +2244,8 @@ networkstatus_format_signatures(networkstatus_t *consensus, for_detached_signatures ? flavor_name : "", digest_name, id, sk); } - base64_encode(buf, sizeof(buf), sig->signature, sig->signature_len); + base64_encode(buf, sizeof(buf), sig->signature, sig->signature_len, + BASE64_ENCODE_MULTILINE); strlcat(buf, "-----END SIGNATURE-----\n", sizeof(buf)); smartlist_add(elements, tor_strdup(buf)); } SMARTLIST_FOREACH_END(sig); @@ -3459,7 +3460,7 @@ dirvote_create_microdescriptor(const routerinfo_t *ri, int consensus_method) char kbuf[128]; base64_encode(kbuf, sizeof(kbuf), (const char*)ri->onion_curve25519_pkey->public_key, - CURVE25519_PUBKEY_LEN); + CURVE25519_PUBKEY_LEN, BASE64_ENCODE_MULTILINE); smartlist_add_asprintf(chunks, "ntor-onion-key %s", kbuf); } diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c index 9663f34002..ebf675166b 100644 --- a/src/or/entrynodes.c +++ b/src/or/entrynodes.c @@ -440,7 +440,8 @@ add_an_entry_guard(const node_t *chosen, int reset_status, int prepend, * don't all select them on the same day, and b) avoid leaving a * precise timestamp in the state file about when we first picked * this guard. For details, see the Jan 2010 or-dev thread. */ - entry->chosen_on_date = time(NULL) - crypto_rand_int(3600*24*30); + time_t now = time(NULL); + entry->chosen_on_date = crypto_rand_time_range(now - 3600*24*30, now); entry->chosen_by_version = tor_strdup(VERSION); /* Are we picking this guard because all of our current guards are @@ -1439,8 +1440,9 @@ entry_guards_parse_state(or_state_t *state, int set, char **msg) } } else { if (state_version) { + time_t now = time(NULL); + e->chosen_on_date = crypto_rand_time_range(now - 3600*24*30, now); e->chosen_by_version = tor_strdup(state_version); - e->chosen_on_date = time(NULL) - crypto_rand_int(3600*24*30); } } if (e->path_bias_disabled && !e->bad_since) diff --git a/src/or/main.c b/src/or/main.c index 39c0f5c89e..3fb7de6f6c 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -1623,7 +1623,8 @@ run_scheduled_events(time_t now) time_to.check_for_correct_dns < now && ! router_my_exit_policy_is_reject_star()) { if (!time_to.check_for_correct_dns) { - time_to.check_for_correct_dns = now + 60 + crypto_rand_int(120); + time_to.check_for_correct_dns = + crypto_rand_time_range(now + 60, now + 180); } else { dns_launch_correctness_checks(); time_to.check_for_correct_dns = now + 12*3600 + diff --git a/src/or/or.h b/src/or/or.h index 39c5ed6023..1c00423166 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -4809,12 +4809,13 @@ typedef struct rend_encoded_v2_service_descriptor_t { * introduction point. See also rend_intro_point_t.unreachable_count. */ #define MAX_INTRO_POINT_REACHABILITY_FAILURES 5 -/** The maximum number of distinct INTRODUCE2 cells which a hidden - * service's introduction point will receive before it begins to - * expire. - * - * XXX023 Is this number at all sane? */ -#define INTRO_POINT_LIFETIME_INTRODUCTIONS 16384 +/** The minimum and maximum number of distinct INTRODUCE2 cells which a + * hidden service's introduction point will receive before it begins to + * expire. */ +#define INTRO_POINT_MIN_LIFETIME_INTRODUCTIONS 16384 +/* Double the minimum value so the interval is [min, min * 2]. */ +#define INTRO_POINT_MAX_LIFETIME_INTRODUCTIONS \ + (INTRO_POINT_MIN_LIFETIME_INTRODUCTIONS * 2) /** The minimum number of seconds that an introduction point will last * before expiring due to old age. (If it receives @@ -4868,6 +4869,12 @@ typedef struct rend_intro_point_t { */ int accepted_introduce2_count; + /** (Service side only) Number of maximum INTRODUCE2 cells that this IP + * will accept. This is a random value between + * INTRO_POINT_MIN_LIFETIME_INTRODUCTIONS and + * INTRO_POINT_MAX_LIFETIME_INTRODUCTIONS. */ + int max_introductions; + /** (Service side only) The time at which this intro point was first * published, or -1 if this intro point has not yet been * published. */ diff --git a/src/or/rendclient.c b/src/or/rendclient.c index d64907522e..0854d9371e 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -714,12 +714,13 @@ directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query, if (rend_query->auth_type != REND_NO_AUTH) { if (base64_encode(descriptor_cookie_base64, sizeof(descriptor_cookie_base64), - rend_query->descriptor_cookie, REND_DESC_COOKIE_LEN)<0) { + rend_query->descriptor_cookie, REND_DESC_COOKIE_LEN, + 0)<0) { log_warn(LD_BUG, "Could not base64-encode descriptor cookie."); return 0; } - /* Remove == signs and newline. */ - descriptor_cookie_base64[strlen(descriptor_cookie_base64)-3] = '\0'; + /* Remove == signs. */ + descriptor_cookie_base64[strlen(descriptor_cookie_base64)-2] = '\0'; } else { strlcpy(descriptor_cookie_base64, "(none)", sizeof(descriptor_cookie_base64)); diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c index 49827459be..03dd757921 100644 --- a/src/or/rendcommon.c +++ b/src/or/rendcommon.c @@ -529,7 +529,8 @@ rend_encode_v2_descriptors(smartlist_t *descs_out, } /* Base64-encode introduction points. */ ipos_base64 = tor_calloc(ipos_len, 2); - if (base64_encode(ipos_base64, ipos_len * 2, ipos, ipos_len)<0) { + if (base64_encode(ipos_base64, ipos_len * 2, ipos, ipos_len, + BASE64_ENCODE_MULTILINE)<0) { log_warn(LD_REND, "Could not encode introduction point string to " "base64. length=%d", (int)ipos_len); tor_free(ipos_base64); diff --git a/src/or/rendservice.c b/src/or/rendservice.c index c1c0c46d17..41bbd69c93 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -941,7 +941,7 @@ rend_service_load_auth_keys(rend_service_t *s, const char *hfname) } if (base64_encode(desc_cook_out, 3*REND_DESC_COOKIE_LEN_BASE64+1, client->descriptor_cookie, - REND_DESC_COOKIE_LEN) < 0) { + REND_DESC_COOKIE_LEN, 0) < 0) { log_warn(LD_BUG, "Could not base64-encode descriptor cookie."); goto err; } @@ -968,7 +968,6 @@ rend_service_load_auth_keys(rend_service_t *s, const char *hfname) client->client_key = prkey; } /* Add entry to client_keys file. */ - desc_cook_out[strlen(desc_cook_out)-1] = '\0'; /* Remove newline. */ written = tor_snprintf(buf, sizeof(buf), "client-name %s\ndescriptor-cookie %s\n", client->client_name, desc_cook_out); @@ -1023,12 +1022,11 @@ rend_service_load_auth_keys(rend_service_t *s, const char *hfname) ((int)s->auth_type - 1) << 4; if (base64_encode(desc_cook_out, 3*REND_DESC_COOKIE_LEN_BASE64+1, extended_desc_cookie, - REND_DESC_COOKIE_LEN+1) < 0) { + REND_DESC_COOKIE_LEN+1, 0) < 0) { log_warn(LD_BUG, "Could not base64-encode descriptor cookie."); goto err; } - desc_cook_out[strlen(desc_cook_out)-3] = '\0'; /* Remove A= and - newline. */ + desc_cook_out[strlen(desc_cook_out)-2] = '\0'; /* Remove A=. */ tor_snprintf(buf, sizeof(buf),"%s.onion %s # client: %s\n", service_id, desc_cook_out, client->client_name); } @@ -1124,7 +1122,7 @@ rend_check_authorization(rend_service_t *service, if (!auth_client) { char descriptor_cookie_base64[3*REND_DESC_COOKIE_LEN_BASE64]; base64_encode(descriptor_cookie_base64, sizeof(descriptor_cookie_base64), - descriptor_cookie, REND_DESC_COOKIE_LEN); + descriptor_cookie, REND_DESC_COOKIE_LEN, 0); log_info(LD_REND, "No authorization found for descriptor cookie '%s'! " "Dropping cell!", descriptor_cookie_base64); @@ -1158,16 +1156,17 @@ rend_service_note_removing_intro_point(rend_service_t *service, /* This intro point was never used. Don't change * n_intro_points_wanted. */ } else { + /* We want to increase the number of introduction points service * operates if intro was heavily used, or decrease the number of * intro points if intro was lightly used. * * We consider an intro point's target 'usage' to be - * INTRO_POINT_LIFETIME_INTRODUCTIONS introductions in + * maximum of INTRODUCE2 cells divided by * INTRO_POINT_LIFETIME_MIN_SECONDS seconds. To calculate intro's - * fraction of target usage, we divide the fraction of - * _LIFETIME_INTRODUCTIONS introductions that it has handled by - * the fraction of _LIFETIME_MIN_SECONDS for which it existed. + * fraction of target usage, we divide the amount of INTRODUCE2 cells + * that it has handled by the fraction of _LIFETIME_MIN_SECONDS for + * which it existed. * * Then we multiply that fraction of desired usage by a fudge * factor of 1.5, to decide how many new introduction points @@ -1189,7 +1188,7 @@ rend_service_note_removing_intro_point(rend_service_t *service, intro_point_accepted_intro_count(intro) / (double)(now - intro->time_published); const double intro_point_target_usage = - INTRO_POINT_LIFETIME_INTRODUCTIONS / + intro->max_introductions / (double)INTRO_POINT_LIFETIME_MIN_SECONDS; const double fractional_n_intro_points_wanted_to_replace_this_one = (1.5 * (intro_point_usage / intro_point_target_usage)); @@ -3123,7 +3122,7 @@ intro_point_should_expire_now(rend_intro_point_t *intro, } if (intro_point_accepted_intro_count(intro) >= - INTRO_POINT_LIFETIME_INTRODUCTIONS) { + intro->max_introductions) { /* This intro point has been used too many times. Expire it now. */ return 1; } @@ -3132,9 +3131,8 @@ intro_point_should_expire_now(rend_intro_point_t *intro, /* This intro point has been published, but we haven't picked an * expiration time for it. Pick one now. */ int intro_point_lifetime_seconds = - INTRO_POINT_LIFETIME_MIN_SECONDS + - crypto_rand_int(INTRO_POINT_LIFETIME_MAX_SECONDS - - INTRO_POINT_LIFETIME_MIN_SECONDS); + crypto_rand_int_range(INTRO_POINT_LIFETIME_MIN_SECONDS, + INTRO_POINT_LIFETIME_MAX_SECONDS); /* Start the expiration timer now, rather than when the intro * point was first published. There shouldn't be much of a time @@ -3335,6 +3333,9 @@ rend_services_introduce(void) intro->time_published = -1; intro->time_to_expire = -1; intro->time_expiring = -1; + intro->max_introductions = + crypto_rand_int_range(INTRO_POINT_MIN_LIFETIME_INTRODUCTIONS, + INTRO_POINT_MAX_LIFETIME_INTRODUCTIONS); smartlist_add(service->intro_nodes, intro); log_info(LD_REND, "Picked router %s as an intro point for %s.", safe_str_client(node_describe(node)), diff --git a/src/or/router.c b/src/or/router.c index b8bfd3cf6f..24b7c750f6 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -683,7 +683,9 @@ router_initialize_tls_context(void) if (!lifetime) { /* we should guess a good ssl cert lifetime */ /* choose between 5 and 365 days, and round to the day */ - lifetime = 5*24*3600 + crypto_rand_int(361*24*3600); + unsigned int five_days = 5*24*3600; + unsigned int one_year = 365*24*3600; + lifetime = crypto_rand_int_range(five_days, one_year); lifetime -= lifetime % (24*3600); if (crypto_rand_int(2)) { @@ -2453,7 +2455,7 @@ router_dump_router_to_string(routerinfo_t *router, char kbuf[128]; base64_encode(kbuf, sizeof(kbuf), (const char *)router->onion_curve25519_pkey->public_key, - CURVE25519_PUBKEY_LEN); + CURVE25519_PUBKEY_LEN, BASE64_ENCODE_MULTILINE); smartlist_add_asprintf(chunks, "ntor-onion-key %s", kbuf); } diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 14d5f75e35..f15aeeb0cf 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -664,7 +664,8 @@ router_get_dirobj_signature(const char *digest, goto truncated; i = strlen(buf); - if (base64_encode(buf+i, buf_len-i, signature, siglen) < 0) { + if (base64_encode(buf+i, buf_len-i, signature, siglen, + BASE64_ENCODE_MULTILINE) < 0) { log_warn(LD_BUG,"couldn't base64-encode signature"); goto err; } @@ -3360,7 +3361,9 @@ router_parse_addr_policy_item_from_string,(const char *s, int assume_action)) { directory_token_t *tok = NULL; const char *cp, *eos; - /* Longest possible policy is "accept ffff:ffff:..255/ffff:...255:0-65535". + /* Longest possible policy is + * "accept6 ffff:ffff:..255/ffff:...255:10000-65535", + * which contains 2 max-length IPv6 addresses, plus 21 characters. * But note that there can be an arbitrary amount of space between the * accept and the address:mask/port element. */ char line[TOR_ADDR_BUF_LEN*2 + 32]; diff --git a/src/test/bt_test.py b/src/test/bt_test.py index 0afe797a6d..e694361703 100755 --- a/src/test/bt_test.py +++ b/src/test/bt_test.py @@ -36,7 +36,7 @@ LINES = sys.stdin.readlines() for I in range(len(LINES)): if matches(LINES[I:], FUNCNAMES): print("OK") - break + sys.exit(0) else: print("BAD") - + sys.exit(1) diff --git a/src/test/include.am b/src/test/include.am index c857ec2f89..3c9eed886f 100644 --- a/src/test/include.am +++ b/src/test/include.am @@ -1,4 +1,12 @@ -TESTS += src/test/test src/test/test-slow src/test/test-memwipe +TESTS += src/test/test src/test/test-slow src/test/test-memwipe \ + src/test/test_zero_length_keys.sh + +if USEPYTHON +TESTS += src/test/test_ntor.sh src/test/test_bt.sh +endif + +TEST_EXTENSIONS = .sh +SH_LOG_COMPILER = $(SHELL) noinst_PROGRAMS+= src/test/bench if UNITTESTS_ENABLED @@ -146,13 +154,6 @@ src_test_test_ntor_cl_LDADD = src/or/libtor.a src/common/libor.a \ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ src_test_test_ntor_cl_AM_CPPFLAGS = \ -I"$(top_srcdir)/src/or" -NTOR_TEST_DEPS=src/test/test-ntor-cl - -if COVERAGE_ENABLED -CMDLINE_TEST_TOR = $(top_builddir)/src/or/tor-cov -else -CMDLINE_TEST_TOR = $(top_builddir)/src/or/tor -endif noinst_PROGRAMS += src/test/test-bt-cl src_test_test_bt_cl_SOURCES = src/test/test_bt_cl.c @@ -162,16 +163,6 @@ src_test_test_bt_cl_LDADD = src/common/libor-testing.a \ src_test_test_bt_cl_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) src_test_test_bt_cl_CPPFLAGS= $(src_test_AM_CPPFLAGS) $(TEST_CPPFLAGS) - -check-local: $(NTOR_TEST_DEPS) $(CMDLINE_TEST_TOR) -if USEPYTHON - $(PYTHON) $(top_srcdir)/src/test/ntor_ref.py test-tor - $(PYTHON) $(top_srcdir)/src/test/ntor_ref.py self-test - $(top_builddir)/src/test/test-bt-cl assert | $(PYTHON) $(top_srcdir)/src/test/bt_test.py - $(top_builddir)/src/test/test-bt-cl crash | $(PYTHON) $(top_srcdir)/src/test/bt_test.py -endif - $(SHELL) $(top_srcdir)/src/test/zero_length_keys.sh - EXTRA_DIST += \ src/test/bt_test.py \ src/test/ntor_ref.py \ diff --git a/src/test/test_address.c b/src/test/test_address.c index 52361624e5..d13d678f3d 100644 --- a/src/test/test_address.c +++ b/src/test/test_address.c @@ -222,7 +222,7 @@ test_address_get_if_addrs_ifaddrs(void *arg) (void)arg; - results = get_interface_addresses_ifaddrs(0); + results = get_interface_addresses_ifaddrs(LOG_ERR); tt_int_op(smartlist_len(results),>=,1); tt_assert(smartlist_contains_localhost_tor_addr(results)); @@ -245,7 +245,7 @@ test_address_get_if_addrs_win32(void *arg) (void)arg; - results = get_interface_addresses_win32(0); + results = get_interface_addresses_win32(LOG_ERR); tt_int_op(smartlist_len(results),>=,1); tt_assert(smartlist_contains_localhost_tor_addr(results)); diff --git a/src/test/test_bt.sh.in b/src/test/test_bt.sh.in new file mode 100644 index 0000000000..d2498751cb --- /dev/null +++ b/src/test/test_bt.sh.in @@ -0,0 +1,9 @@ +#!/bin/sh +# Test backtrace functionality. + +exitcode=0 + +@builddir@/src/test/test-bt-cl assert | @PYTHON@ @abs_top_srcdir@/src/test/bt_test.py || exitcode=1 +@builddir@/src/test/test-bt-cl crash | @PYTHON@ @abs_top_srcdir@/src/test/bt_test.py || exitcode=1 + +exit ${exitcode} diff --git a/src/test/test_bt_cl.c b/src/test/test_bt_cl.c index 0fa0cd5c0a..01c621eb0e 100644 --- a/src/test/test_bt_cl.c +++ b/src/test/test_bt_cl.c @@ -5,6 +5,8 @@ #include <stdio.h> #include <stdlib.h> +/* To prevent 'assert' from going away. */ +#undef TOR_COVERAGE #include "or.h" #include "util.h" #include "backtrace.h" diff --git a/src/test/test_config.c b/src/test/test_config.c index 0444062722..28e9fa0f32 100644 --- a/src/test/test_config.c +++ b/src/test/test_config.c @@ -17,6 +17,7 @@ #include "address.h" #include "entrynodes.h" #include "transports.h" +#include "routerlist.h" static void test_config_addressmap(void *arg) @@ -1036,7 +1037,7 @@ static int n_get_interface_address6_failure = 0; /** * This mock function is meant to replace get_interface_addres6(). - * It will pretent to fail by return -1. + * It will pretend to fail by return -1. * <b>n_get_interface_address6_failure</b> is incremented by one * every time this function is called and <b>last_address6_family</b> * is assigned the value of <b>family</b> argument. @@ -1405,7 +1406,7 @@ test_config_resolve_my_address(void *arg) /* CASE 12: * Suppose the following happens: - * 1. options->Address is NULL AND options->DirAuthorities is 1. + * 1. options->Address is NULL AND options->DirAuthorities is non-NULL * 2. tor_gethostname() succeeds in getting hostname of a machine ... * 3. ... which is successfully parsed by tor_inet_aton() ... * 4. into IPv4 address that tor_addr_is_inernal() considers to be @@ -1443,10 +1444,1776 @@ test_config_resolve_my_address(void *arg) UNMOCK(tor_gethostname); } +static int n_add_default_fallback_dir_servers_known_default = 0; + +/** + * This mock function is meant to replace add_default_fallback_dir_servers(). + * It will parse and add one known default fallback dir server, + * which has a dir_port of 99. + * <b>n_add_default_fallback_dir_servers_known_default</b> is incremented by + * one every time this function is called. + */ +static void +add_default_fallback_dir_servers_known_default(void) +{ + int i; + const char *fallback[] = { + "127.0.0.1:60099 orport=9009 " + "id=0923456789012345678901234567890123456789", + NULL + }; + for (i=0; fallback[i]; i++) { + if (parse_dir_fallback_line(fallback[i], 0)<0) { + log_err(LD_BUG, "Couldn't parse internal FallbackDir line %s", + fallback[i]); + } + } + n_add_default_fallback_dir_servers_known_default++; +} + +static void +test_config_adding_dir_servers(void *arg) +{ + (void)arg; + + /* allocate options */ + or_options_t *options = tor_malloc(sizeof(or_options_t)); + + /* Allocate and populate configuration lines: + * + * Use the same format as the hard-coded directories in + * add_default_trusted_dir_authorities(). + * Zeroing the structure has the same effect as initialising to: + * { NULL, NULL, NULL, CONFIG_LINE_NORMAL, 0}; + */ + config_line_t *test_dir_authority = tor_malloc(sizeof(config_line_t)); + memset(test_dir_authority, 0, sizeof(config_line_t)); + test_dir_authority->key = tor_strdup("DirAuthority"); + test_dir_authority->value = tor_strdup( + "D0 orport=9000 " + "v3ident=0023456789012345678901234567890123456789 " + "127.0.0.1:60090 0123 4567 8901 2345 6789 0123 4567 8901 2345 6789" + ); + + config_line_t *test_alt_bridge_authority = tor_malloc(sizeof(config_line_t)); + memset(test_alt_bridge_authority, 0, sizeof(config_line_t)); + test_alt_bridge_authority->key = tor_strdup("AlternateBridgeAuthority"); + test_alt_bridge_authority->value = tor_strdup( + "B1 orport=9001 bridge " + "127.0.0.1:60091 1123 4567 8901 2345 6789 0123 4567 8901 2345 6789" + ); + + config_line_t *test_alt_dir_authority = tor_malloc(sizeof(config_line_t)); + memset(test_alt_dir_authority, 0, sizeof(config_line_t)); + test_alt_dir_authority->key = tor_strdup("AlternateDirAuthority"); + test_alt_dir_authority->value = tor_strdup( + "A2 orport=9002 " + "v3ident=0223456789012345678901234567890123456789 " + "127.0.0.1:60092 2123 4567 8901 2345 6789 0123 4567 8901 2345 6789" + ); + + /* Use the format specified in the manual page */ + config_line_t *test_fallback_directory = tor_malloc(sizeof(config_line_t)); + memset(test_fallback_directory, 0, sizeof(config_line_t)); + test_fallback_directory->key = tor_strdup("FallbackDir"); + test_fallback_directory->value = tor_strdup( + "127.0.0.1:60093 orport=9003 id=0323456789012345678901234567890123456789" + ); + + /* We need to know if add_default_fallback_dir_servers is called, + * so we use a version of add_default_fallback_dir_servers that adds + * one known default fallback directory. + * There doesn't appear to be any need to test it unmocked. */ + MOCK(add_default_fallback_dir_servers, + add_default_fallback_dir_servers_known_default); + + /* There are 16 different cases, covering each combination of set/NULL for: + * DirAuthorities, AlternateBridgeAuthority, AlternateDirAuthority & + * FallbackDir. + * But validate_dir_servers() ensures that: + * "You cannot set both DirAuthority and Alternate*Authority." + * This reduces the number of cases to 10. + * + * Let's count these cases using binary, with 1 meaning set & 0 meaning NULL + * So 1001 or case 9 is: + * DirAuthorities set, + * AlternateBridgeAuthority NULL, + * AlternateDirAuthority NULL + * FallbackDir set + * The valid cases are cases 0-9 counting using this method, as every case + * greater than or equal to 10 = 1010 is invalid. + * + * After #15642 - Disable default fallback dirs when any custom dirs set + * + * 1. Outcome: Use Set Directory Authorities + * - No Default Authorities + * - Use AlternateBridgeAuthority, AlternateDirAuthority, and FallbackDir + * if they are set + * Cases expected to yield this outcome: + * 8 & 9 (the 2 valid cases where DirAuthorities is set) + * 6 & 7 (the 2 cases where DirAuthorities is NULL, and + * AlternateBridgeAuthority and AlternateDirAuthority are both set) + * + * 2. Outcome: Use Set Bridge Authority + * - Use Default Non-Bridge Directory Authorities + * - Use FallbackDir if it is set, otherwise use default FallbackDir + * Cases expected to yield this outcome: + * 4 & 5 (the 2 cases where DirAuthorities is NULL, + * AlternateBridgeAuthority is set, and + * AlternateDirAuthority is NULL) + * + * 3. Outcome: Use Set Alternate Directory Authority + * - Use Default Bridge Authorities + * - Use FallbackDir if it is set, otherwise No Default Fallback Directories + * Cases expected to yield this outcome: + * 2 & 3 (the 2 cases where DirAuthorities and AlternateBridgeAuthority + * are both NULL, but AlternateDirAuthority is set) + * + * 4. Outcome: Use Set Custom Fallback Directory + * - Use Default Bridge & Directory Authorities + * Cases expected to yield this outcome: + * 1 (DirAuthorities, AlternateBridgeAuthority and AlternateDirAuthority + * are all NULL, but FallbackDir is set) + * + * 5. Outcome: Use All Defaults + * - Use Default Bridge & Directory Authorities, and + * Default Fallback Directories + * Cases expected to yield this outcome: + * 0 (DirAuthorities, AlternateBridgeAuthority, AlternateDirAuthority + * and FallbackDir are all NULL) + * + * Before #15642 but after #13163 - Stop using default authorities when both + * Alternate Dir and Bridge Authority are set + * (#13163 was committed in 0.2.6 as c1dd43d823c7) + * + * The behaviour is different in the following cases + * where FallbackDir is NULL: + * 2, 6, 8 + * + * In these cases, the Default Fallback Directories are applied, even when + * DirAuthorities or AlternateDirAuthority are set. + * + * However, as the list of default fallback directories is currently empty, + * this change doesn't modify any user-visible behaviour. + */ + + /* + * Find out how many default Bridge, Non-Bridge and Fallback Directories + * are hard-coded into this build. + * This code makes some assumptions about the implementation. + * If they are wrong, one or more of cases 0-5 could fail. + */ + int n_default_alt_bridge_authority = 0; + int n_default_alt_dir_authority = 0; + int n_default_fallback_dir = 0; +#define n_default_authorities ((n_default_alt_bridge_authority) \ + + (n_default_alt_dir_authority)) + + /* Pre-Count Number of Authorities of Each Type + * Use 0000: No Directory Authorities or Fallback Directories Set + */ + { + /* clear fallback dirs counter */ + n_add_default_fallback_dir_servers_known_default = 0; + + /* clear options*/ + memset(options, 0, sizeof(or_options_t)); + + /* clear any previous dir servers: + consider_adding_dir_servers() should do this anyway */ + clear_dir_servers(); + + /* assign options: 0000 */ + options->DirAuthorities = NULL; + options->AlternateBridgeAuthority = NULL; + options->AlternateDirAuthority = NULL; + options->FallbackDir = NULL; + + /* parse options - ensure we always update by passing NULL old_options */ + consider_adding_dir_servers(options, NULL); + + /* check outcome */ + + /* we must have added the default fallback dirs */ + tt_assert(n_add_default_fallback_dir_servers_known_default == 1); + + { + /* fallback_dir_servers */ + const smartlist_t *fallback_servers = router_get_fallback_dir_servers(); + + /* Count Bridge Authorities */ + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if it's a bridge auth */ + n_default_alt_bridge_authority += + ((ds->is_authority && (ds->type & BRIDGE_DIRINFO)) ? + 1 : 0) + ); + /* If we have no default bridge authority, something has gone wrong */ + tt_assert(n_default_alt_bridge_authority >= 1); + + /* Count v3 Authorities */ + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment found counter if it's a v3 auth */ + n_default_alt_dir_authority += + ((ds->is_authority && (ds->type & V3_DIRINFO)) ? + 1 : 0) + ); + /* If we have no default authorities, something has gone really wrong */ + tt_assert(n_default_alt_dir_authority >= 1); + + /* Calculate Fallback Directory Count */ + n_default_fallback_dir = (smartlist_len(fallback_servers) - + n_default_alt_bridge_authority - + n_default_alt_dir_authority); + /* If we have a negative count, something has gone really wrong */ + tt_assert(n_default_fallback_dir >= 0); + } + } + + /* + * 1. Outcome: Use Set Directory Authorities + * - No Default Authorities + * - Use AlternateBridgeAuthority, AlternateDirAuthority, and FallbackDir + * if they are set + * Cases expected to yield this outcome: + * 8 & 9 (the 2 valid cases where DirAuthorities is set) + * 6 & 7 (the 2 cases where DirAuthorities is NULL, and + * AlternateBridgeAuthority and AlternateDirAuthority are both set) + */ + + /* Case 9: 1001 - DirAuthorities Set, AlternateBridgeAuthority Not Set, + AlternateDirAuthority Not Set, FallbackDir Set */ + { + /* clear fallback dirs counter */ + n_add_default_fallback_dir_servers_known_default = 0; + + /* clear options*/ + memset(options, 0, sizeof(or_options_t)); + + /* clear any previous dir servers: + consider_adding_dir_servers() should do this anyway */ + clear_dir_servers(); + + /* assign options: 1001 */ + options->DirAuthorities = test_dir_authority; + options->AlternateBridgeAuthority = NULL; + options->AlternateDirAuthority = NULL; + options->FallbackDir = test_fallback_directory; + + /* parse options - ensure we always update by passing NULL old_options */ + consider_adding_dir_servers(options, NULL); + + /* check outcome */ + + /* we must not have added the default fallback dirs */ + tt_assert(n_add_default_fallback_dir_servers_known_default == 0); + + { + /* trusted_dir_servers */ + const smartlist_t *dir_servers = router_get_trusted_dir_servers(); + /* D0, (No B1), (No A2) */ + tt_assert(smartlist_len(dir_servers) == 1); + + /* DirAuthority - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 1); + + /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 0); + + /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 0); + } + + { + /* fallback_dir_servers */ + const smartlist_t *fallback_servers = router_get_fallback_dir_servers(); + /* D0, (No B1), (No A2), Custom Fallback */ + tt_assert(smartlist_len(fallback_servers) == 2); + + /* DirAuthority - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 1); + + /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 0); + + /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 0); + + /* Custom FallbackDir - No Nickname - dir_port: 60093 */ + int found_non_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_non_default_fallback += + (ds->dir_port == 60093 ? + 1 : 0) + ); + tt_assert(found_non_default_fallback == 1); + + /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */ + int found_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_default_fallback += + (ds->dir_port == 60099 ? + 1 : 0) + ); + tt_assert(found_default_fallback == 0); + } + } + + /* Case 8: 1000 - DirAuthorities Set, Others Not Set */ + { + /* clear fallback dirs counter */ + n_add_default_fallback_dir_servers_known_default = 0; + + /* clear options*/ + memset(options, 0, sizeof(or_options_t)); + + /* clear any previous dir servers: + consider_adding_dir_servers() should do this anyway */ + clear_dir_servers(); + + /* assign options: 1000 */ + options->DirAuthorities = test_dir_authority; + options->AlternateBridgeAuthority = NULL; + options->AlternateDirAuthority = NULL; + options->FallbackDir = NULL; + + /* parse options - ensure we always update by passing NULL old_options */ + consider_adding_dir_servers(options, NULL); + + /* check outcome */ + + /* we must not have added the default fallback dirs */ + tt_assert(n_add_default_fallback_dir_servers_known_default == 0); + + { + /* trusted_dir_servers */ + const smartlist_t *dir_servers = router_get_trusted_dir_servers(); + /* D0, (No B1), (No A2) */ + tt_assert(smartlist_len(dir_servers) == 1); + + /* DirAuthority - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 1); + + /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 0); + + /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 0); + } + + { + /* fallback_dir_servers */ + const smartlist_t *fallback_servers = router_get_fallback_dir_servers(); + /* D0, (No B1), (No A2), (No Fallback) */ + tt_assert(smartlist_len(fallback_servers) == 1); + + /* DirAuthority - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 1); + + /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 0); + + /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 0); + + /* (No Custom FallbackDir) - No Nickname - dir_port: 60093 */ + int found_non_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_non_default_fallback += + (ds->dir_port == 60093 ? + 1 : 0) + ); + tt_assert(found_non_default_fallback == 0); + + /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */ + int found_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_default_fallback += + (ds->dir_port == 60099 ? + 1 : 0) + ); + tt_assert(found_default_fallback == 0); + } + } + + /* Case 7: 0111 - DirAuthorities Not Set, Others Set */ + { + /* clear fallback dirs counter */ + n_add_default_fallback_dir_servers_known_default = 0; + + /* clear options*/ + memset(options, 0, sizeof(or_options_t)); + + /* clear any previous dir servers: + consider_adding_dir_servers() should do this anyway */ + clear_dir_servers(); + + /* assign options: 0111 */ + options->DirAuthorities = NULL; + options->AlternateBridgeAuthority = test_alt_bridge_authority; + options->AlternateDirAuthority = test_alt_dir_authority; + options->FallbackDir = test_fallback_directory; + + /* parse options - ensure we always update by passing NULL old_options */ + consider_adding_dir_servers(options, NULL); + + /* check outcome */ + + /* we must not have added the default fallback dirs */ + tt_assert(n_add_default_fallback_dir_servers_known_default == 0); + + { + /* trusted_dir_servers */ + const smartlist_t *dir_servers = router_get_trusted_dir_servers(); + /* (No D0), B1, A2 */ + tt_assert(smartlist_len(dir_servers) == 2); + + /* (No DirAuthority) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* AlternateBridgeAuthority - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 1); + + /* AlternateDirAuthority - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 1); + } + + { + /* fallback_dir_servers */ + const smartlist_t *fallback_servers = router_get_fallback_dir_servers(); + /* (No D0), B1, A2, Custom Fallback */ + tt_assert(smartlist_len(fallback_servers) == 3); + + /* (No DirAuthority) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* AlternateBridgeAuthority - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 1); + + /* AlternateDirAuthority - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 1); + + /* Custom FallbackDir - No Nickname - dir_port: 60093 */ + int found_non_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_non_default_fallback += + (ds->dir_port == 60093 ? + 1 : 0) + ); + tt_assert(found_non_default_fallback == 1); + + /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */ + int found_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_default_fallback += + (ds->dir_port == 60099 ? + 1 : 0) + ); + tt_assert(found_default_fallback == 0); + } + } + + /* Case 6: 0110 - DirAuthorities Not Set, AlternateBridgeAuthority & + AlternateDirAuthority Set, FallbackDir Not Set */ + { + /* clear fallback dirs counter */ + n_add_default_fallback_dir_servers_known_default = 0; + + /* clear options*/ + memset(options, 0, sizeof(or_options_t)); + + /* clear any previous dir servers: + consider_adding_dir_servers() should do this anyway */ + clear_dir_servers(); + + /* assign options: 0110 */ + options->DirAuthorities = NULL; + options->AlternateBridgeAuthority = test_alt_bridge_authority; + options->AlternateDirAuthority = test_alt_dir_authority; + options->FallbackDir = NULL; + + /* parse options - ensure we always update by passing NULL old_options */ + consider_adding_dir_servers(options, NULL); + + /* check outcome */ + + /* we must not have added the default fallback dirs */ + tt_assert(n_add_default_fallback_dir_servers_known_default == 0); + + { + /* trusted_dir_servers */ + const smartlist_t *dir_servers = router_get_trusted_dir_servers(); + /* (No D0), B1, A2 */ + tt_assert(smartlist_len(dir_servers) == 2); + + /* (No DirAuthority) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* AlternateBridgeAuthority - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 1); + + /* AlternateDirAuthority - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 1); + } + + { + /* fallback_dir_servers */ + const smartlist_t *fallback_servers = router_get_fallback_dir_servers(); + /* (No D0), B1, A2, (No Fallback) */ + tt_assert(smartlist_len(fallback_servers) == 2); + + /* (No DirAuthority) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* AlternateBridgeAuthority - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 1); + + /* AlternateDirAuthority - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 1); + + /* (No Custom FallbackDir) - No Nickname - dir_port: 60093 */ + int found_non_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_non_default_fallback += + (ds->dir_port == 60093 ? + 1 : 0) + ); + tt_assert(found_non_default_fallback == 0); + + /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */ + int found_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_default_fallback += + (ds->dir_port == 60099 ? + 1 : 0) + ); + tt_assert(found_default_fallback == 0); + } + } + + /* + 2. Outcome: Use Set Bridge Authority + - Use Default Non-Bridge Directory Authorities + - Use FallbackDir if it is set, otherwise use default FallbackDir + Cases expected to yield this outcome: + 4 & 5 (the 2 cases where DirAuthorities is NULL, + AlternateBridgeAuthority is set, and + AlternateDirAuthority is NULL) + */ + + /* Case 5: 0101 - DirAuthorities Not Set, AlternateBridgeAuthority Set, + AlternateDirAuthority Not Set, FallbackDir Set */ + { + /* clear fallback dirs counter */ + n_add_default_fallback_dir_servers_known_default = 0; + + /* clear options*/ + memset(options, 0, sizeof(or_options_t)); + + /* clear any previous dir servers: + consider_adding_dir_servers() should do this anyway */ + clear_dir_servers(); + + /* assign options: 0101 */ + options->DirAuthorities = NULL; + options->AlternateBridgeAuthority = test_alt_bridge_authority; + options->AlternateDirAuthority = NULL; + options->FallbackDir = test_fallback_directory; + + /* parse options - ensure we always update by passing NULL old_options */ + consider_adding_dir_servers(options, NULL); + + /* check outcome */ + + /* we must not have added the default fallback dirs */ + tt_assert(n_add_default_fallback_dir_servers_known_default == 0); + + { + /* trusted_dir_servers */ + const smartlist_t *dir_servers = router_get_trusted_dir_servers(); + /* (No D0), B1, (No A2), Default v3 Non-Bridge Authorities */ + tt_assert(smartlist_len(dir_servers) == 1 + n_default_alt_dir_authority); + + /* (No DirAuthorities) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* AlternateBridgeAuthority - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 1); + + /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 0); + + /* There's no easy way of checking that we have included all the + * default v3 non-Bridge directory authorities, so let's assume that + * if the total count above is correct, we have the right ones. + */ + } + + { + /* fallback_dir_servers */ + const smartlist_t *fallback_servers = router_get_fallback_dir_servers(); + /* (No D0), B1, (No A2), Default v3 Non-Bridge Authorities, + * Custom Fallback */ + tt_assert(smartlist_len(fallback_servers) == + 2 + n_default_alt_dir_authority); + + /* (No DirAuthorities) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* AlternateBridgeAuthority - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 1); + + /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 0); + + /* Custom FallbackDir - No Nickname - dir_port: 60093 */ + int found_non_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_non_default_fallback += + (ds->dir_port == 60093 ? + 1 : 0) + ); + tt_assert(found_non_default_fallback == 1); + + /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */ + int found_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_default_fallback += + (ds->dir_port == 60099 ? + 1 : 0) + ); + tt_assert(found_default_fallback == 0); + + /* There's no easy way of checking that we have included all the + * default v3 non-Bridge directory authorities, so let's assume that + * if the total count above is correct, we have the right ones. + */ + } + } + + /* Case 4: 0100 - DirAuthorities Not Set, AlternateBridgeAuthority Set, + AlternateDirAuthority & FallbackDir Not Set */ + { + /* clear fallback dirs counter */ + n_add_default_fallback_dir_servers_known_default = 0; + + /* clear options*/ + memset(options, 0, sizeof(or_options_t)); + + /* clear any previous dir servers: + consider_adding_dir_servers() should do this anyway */ + clear_dir_servers(); + + /* assign options: 0100 */ + options->DirAuthorities = NULL; + options->AlternateBridgeAuthority = test_alt_bridge_authority; + options->AlternateDirAuthority = NULL; + options->FallbackDir = NULL; + + /* parse options - ensure we always update by passing NULL old_options */ + consider_adding_dir_servers(options, NULL); + + /* check outcome */ + + /* we must have added the default fallback dirs */ + tt_assert(n_add_default_fallback_dir_servers_known_default == 1); + + { + /* trusted_dir_servers */ + const smartlist_t *dir_servers = router_get_trusted_dir_servers(); + /* (No D0), B1, (No A2), Default v3 Non-Bridge Authorities */ + tt_assert(smartlist_len(dir_servers) == 1 + n_default_alt_dir_authority); + + /* (No DirAuthorities) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* AlternateBridgeAuthority - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 1); + + /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 0); + + /* There's no easy way of checking that we have included all the + * default v3 non-Bridge directory authorities, so let's assume that + * if the total count above is correct, we have the right ones. + */ + } + + { + /* fallback_dir_servers */ + const smartlist_t *fallback_servers = router_get_fallback_dir_servers(); + /* (No D0), B1, (No A2), Default v3 Non-Bridge Authorities, + * Default Fallback */ + tt_assert(smartlist_len(fallback_servers) == + 2 + n_default_alt_dir_authority); + + /* (No DirAuthorities) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* AlternateBridgeAuthority - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 1); + + /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 0); + + /* (No Custom FallbackDir) - No Nickname - dir_port: 60093 */ + int found_non_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_non_default_fallback += + (ds->dir_port == 60093 ? + 1 : 0) + ); + tt_assert(found_non_default_fallback == 0); + + /* Default FallbackDir - No Nickname - dir_port: 60099 */ + int found_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_default_fallback += + (ds->dir_port == 60099 ? + 1 : 0) + ); + tt_assert(found_default_fallback == 1); + + /* There's no easy way of checking that we have included all the + * default v3 non-Bridge directory authorities, so let's assume that + * if the total count above is correct, we have the right ones. + */ + } + } + + /* + 3. Outcome: Use Set Alternate Directory Authority + - Use Default Bridge Authorities + - Use FallbackDir if it is set, otherwise No Default Fallback Directories + Cases expected to yield this outcome: + 2 & 3 (the 2 cases where DirAuthorities and AlternateBridgeAuthority + are both NULL, but AlternateDirAuthority is set) + */ + + /* Case 3: 0011 - DirAuthorities & AlternateBridgeAuthority Not Set, + AlternateDirAuthority & FallbackDir Set */ + { + /* clear fallback dirs counter */ + n_add_default_fallback_dir_servers_known_default = 0; + + /* clear options*/ + memset(options, 0, sizeof(or_options_t)); + + /* clear any previous dir servers: + consider_adding_dir_servers() should do this anyway */ + clear_dir_servers(); + + /* assign options: 0011 */ + options->DirAuthorities = NULL; + options->AlternateBridgeAuthority = NULL; + options->AlternateDirAuthority = test_alt_dir_authority; + options->FallbackDir = test_fallback_directory; + + /* parse options - ensure we always update by passing NULL old_options */ + consider_adding_dir_servers(options, NULL); + + /* check outcome */ + + /* we must not have added the default fallback dirs */ + tt_assert(n_add_default_fallback_dir_servers_known_default == 0); + + { + /* trusted_dir_servers */ + const smartlist_t *dir_servers = router_get_trusted_dir_servers(); + /* (No D0), (No B1), Default Bridge Authorities, A2 */ + tt_assert(smartlist_len(dir_servers) == + 1 + n_default_alt_bridge_authority); + + /* (No DirAuthorities) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 0); + + /* AlternateDirAuthority - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 1); + + /* There's no easy way of checking that we have included all the + * default Bridge authorities (except for hard-coding tonga's details), + * so let's assume that if the total count above is correct, + * we have the right ones. + */ + } + + { + /* fallback_dir_servers */ + const smartlist_t *fallback_servers = router_get_fallback_dir_servers(); + /* (No D0), (No B1), Default Bridge Authorities, A2, + * Custom Fallback Directory, (No Default Fallback Directories) */ + tt_assert(smartlist_len(fallback_servers) == + 2 + n_default_alt_bridge_authority); + + /* (No DirAuthorities) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 0); + + /* AlternateDirAuthority - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 1); + + /* Custom FallbackDir - No Nickname - dir_port: 60093 */ + int found_non_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_non_default_fallback += + (ds->dir_port == 60093 ? + 1 : 0) + ); + tt_assert(found_non_default_fallback == 1); + + /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */ + int found_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_default_fallback += + (ds->dir_port == 60099 ? + 1 : 0) + ); + tt_assert(found_default_fallback == 0); + + /* There's no easy way of checking that we have included all the + * default Bridge authorities (except for hard-coding tonga's details), + * so let's assume that if the total count above is correct, + * we have the right ones. + */ + } + } + + /* Case 2: 0010 - DirAuthorities & AlternateBridgeAuthority Not Set, + AlternateDirAuthority Set, FallbackDir Not Set */ + { + /* clear fallback dirs counter */ + n_add_default_fallback_dir_servers_known_default = 0; + + /* clear options*/ + memset(options, 0, sizeof(or_options_t)); + + /* clear any previous dir servers: + consider_adding_dir_servers() should do this anyway */ + clear_dir_servers(); + + /* assign options: 0010 */ + options->DirAuthorities = NULL; + options->AlternateBridgeAuthority = NULL; + options->AlternateDirAuthority = test_alt_dir_authority; + options->FallbackDir = NULL; + + /* parse options - ensure we always update by passing NULL old_options */ + consider_adding_dir_servers(options, NULL); + + /* check outcome */ + + /* we must not have added the default fallback dirs */ + tt_assert(n_add_default_fallback_dir_servers_known_default == 0); + + { + /* trusted_dir_servers */ + const smartlist_t *dir_servers = router_get_trusted_dir_servers(); + /* (No D0), (No B1), Default Bridge Authorities, A2, + * No Default or Custom Fallback Directories */ + tt_assert(smartlist_len(dir_servers) == + 1 + n_default_alt_bridge_authority); + + /* (No DirAuthorities) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 0); + + /* AlternateDirAuthority - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 1); + + /* There's no easy way of checking that we have included all the + * default Bridge authorities (except for hard-coding tonga's details), + * so let's assume that if the total count above is correct, + * we have the right ones. + */ + } + + { + /* fallback_dir_servers */ + const smartlist_t *fallback_servers = router_get_fallback_dir_servers(); + /* (No D0), (No B1), Default Bridge Authorities, A2, + * No Custom or Default Fallback Directories */ + tt_assert(smartlist_len(fallback_servers) == + 1 + n_default_alt_bridge_authority); + + /* (No DirAuthorities) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 0); + + /* AlternateDirAuthority - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 1); + + /* (No Custom FallbackDir) - No Nickname - dir_port: 60093 */ + int found_non_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_non_default_fallback += + (ds->dir_port == 60093 ? + 1 : 0) + ); + tt_assert(found_non_default_fallback == 0); + + /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */ + int found_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_default_fallback += + (ds->dir_port == 60099 ? + 1 : 0) + ); + tt_assert(found_default_fallback == 0); + + /* There's no easy way of checking that we have included all the + * default Bridge authorities (except for hard-coding tonga's details), + * so let's assume that if the total count above is correct, + * we have the right ones. + */ + } + } + + /* + 4. Outcome: Use Set Custom Fallback Directory + - Use Default Bridge & Directory Authorities + Cases expected to yield this outcome: + 1 (DirAuthorities, AlternateBridgeAuthority and AlternateDirAuthority + are all NULL, but FallbackDir is set) + */ + + /* Case 1: 0001 - DirAuthorities, AlternateBridgeAuthority + & AlternateDirAuthority Not Set, FallbackDir Set */ + { + /* clear fallback dirs counter */ + n_add_default_fallback_dir_servers_known_default = 0; + + /* clear options*/ + memset(options, 0, sizeof(or_options_t)); + + /* clear any previous dir servers: + consider_adding_dir_servers() should do this anyway */ + clear_dir_servers(); + + /* assign options: 0001 */ + options->DirAuthorities = NULL; + options->AlternateBridgeAuthority = NULL; + options->AlternateDirAuthority = NULL; + options->FallbackDir = test_fallback_directory; + + /* parse options - ensure we always update by passing NULL old_options */ + consider_adding_dir_servers(options, NULL); + + /* check outcome */ + + /* we must not have added the default fallback dirs */ + tt_assert(n_add_default_fallback_dir_servers_known_default == 0); + + { + /* trusted_dir_servers */ + const smartlist_t *dir_servers = router_get_trusted_dir_servers(); + /* (No D0), (No B1), Default Bridge Authorities, + * (No A2), Default v3 Directory Authorities */ + tt_assert(smartlist_len(dir_servers) == n_default_authorities); + + /* (No DirAuthorities) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 0); + + /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 0); + + /* There's no easy way of checking that we have included all the + * default Bridge & V3 Directory authorities, so let's assume that + * if the total count above is correct, we have the right ones. + */ + } + + { + /* fallback_dir_servers */ + const smartlist_t *fallback_servers = router_get_fallback_dir_servers(); + /* (No D0), (No B1), Default Bridge Authorities, + * (No A2), Default v3 Directory Authorities, + * Custom Fallback Directory, (No Default Fallback Directories) */ + tt_assert(smartlist_len(fallback_servers) == + 1 + n_default_authorities); + + /* (No DirAuthorities) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 0); + + /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 0); + + /* Custom FallbackDir - No Nickname - dir_port: 60093 */ + int found_non_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_non_default_fallback += + (ds->dir_port == 60093 ? + 1 : 0) + ); + tt_assert(found_non_default_fallback == 1); + + /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */ + int found_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_default_fallback += + (ds->dir_port == 60099 ? + 1 : 0) + ); + tt_assert(found_default_fallback == 0); + + /* There's no easy way of checking that we have included all the + * default Bridge & V3 Directory authorities, so let's assume that + * if the total count above is correct, we have the right ones. + */ + } + } + + /* + 5. Outcome: Use All Defaults + - Use Default Bridge & Directory Authorities, Default Fallback Directories + Cases expected to yield this outcome: + 0 (DirAuthorities, AlternateBridgeAuthority, AlternateDirAuthority + and FallbackDir are all NULL) + */ + + /* Case 0: 0000 - All Not Set */ + { + /* clear fallback dirs counter */ + n_add_default_fallback_dir_servers_known_default = 0; + + /* clear options*/ + memset(options, 0, sizeof(or_options_t)); + + /* clear any previous dir servers: + consider_adding_dir_servers() should do this anyway */ + clear_dir_servers(); + + /* assign options: 0001 */ + options->DirAuthorities = NULL; + options->AlternateBridgeAuthority = NULL; + options->AlternateDirAuthority = NULL; + options->FallbackDir = NULL; + + /* parse options - ensure we always update by passing NULL old_options */ + consider_adding_dir_servers(options, NULL); + + /* check outcome */ + + /* we must have added the default fallback dirs */ + tt_assert(n_add_default_fallback_dir_servers_known_default == 1); + + { + /* trusted_dir_servers */ + const smartlist_t *dir_servers = router_get_trusted_dir_servers(); + /* (No D0), (No B1), Default Bridge Authorities, + * (No A2), Default v3 Directory Authorities */ + tt_assert(smartlist_len(dir_servers) == n_default_authorities); + + /* (No DirAuthorities) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 0); + + /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 0); + + /* There's no easy way of checking that we have included all the + * default Bridge & V3 Directory authorities, so let's assume that + * if the total count above is correct, we have the right ones. + */ + } + + { + /* fallback_dir_servers */ + const smartlist_t *fallback_servers = router_get_fallback_dir_servers(); + /* (No D0), (No B1), Default Bridge Authorities, + * (No A2), Default v3 Directory Authorities, + * (No Custom Fallback Directory), Default Fallback Directories */ + tt_assert(smartlist_len(fallback_servers) == + n_default_authorities + n_default_fallback_dir); + + /* (No DirAuthorities) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 0); + + /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 0); + + /* Custom FallbackDir - No Nickname - dir_port: 60093 */ + int found_non_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_non_default_fallback += + (ds->dir_port == 60093 ? + 1 : 0) + ); + tt_assert(found_non_default_fallback == 0); + + /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */ + int found_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_default_fallback += + (ds->dir_port == 60099 ? + 1 : 0) + ); + tt_assert(found_default_fallback == 1); + + /* There's no easy way of checking that we have included all the + * default Bridge & V3 Directory authorities, and the default + * Fallback Directories, so let's assume that if the total count + * above is correct, we have the right ones. + */ + } + } + + done: + clear_dir_servers(); + + tor_free(test_dir_authority->key); + tor_free(test_dir_authority->value); + tor_free(test_dir_authority); + + tor_free(test_alt_dir_authority->key); + tor_free(test_alt_dir_authority->value); + tor_free(test_alt_dir_authority); + + tor_free(test_alt_bridge_authority->key); + tor_free(test_alt_bridge_authority->value); + tor_free(test_alt_bridge_authority); + + tor_free(test_fallback_directory->key); + tor_free(test_fallback_directory->value); + tor_free(test_fallback_directory); + + options->DirAuthorities = NULL; + options->AlternateBridgeAuthority = NULL; + options->AlternateDirAuthority = NULL; + options->FallbackDir = NULL; + or_options_free(options); + + UNMOCK(add_default_fallback_dir_servers); +} + #define CONFIG_TEST(name, flags) \ { #name, test_config_ ## name, flags, NULL, NULL } struct testcase_t config_tests[] = { + CONFIG_TEST(adding_dir_servers, TT_FORK), CONFIG_TEST(resolve_my_address, TT_FORK), CONFIG_TEST(addressmap, 0), CONFIG_TEST(parse_bridge_line, 0), diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c index e9fb8bf084..bcd7069b9d 100644 --- a/src/test/test_crypto.c +++ b/src/test/test_crypto.c @@ -14,6 +14,8 @@ #include "crypto_ed25519.h" #include "ed25519_vectors.inc" +#include <openssl/evp.h> + extern const char AUTHORITY_SIGNKEY_3[]; extern const char AUTHORITY_SIGNKEY_A_DIGEST[]; extern const char AUTHORITY_SIGNKEY_A_DIGEST256[]; @@ -105,6 +107,30 @@ test_crypto_rng(void *arg) ; } +static void +test_crypto_rng_range(void *arg) +{ + int got_smallest = 0, got_largest = 0; + int i; + + (void)arg; + for (i = 0; i < 1000; ++i) { + int x = crypto_rand_int_range(5,9); + tt_int_op(x, OP_GE, 5); + tt_int_op(x, OP_LT, 9); + if (x == 5) + got_smallest = 1; + if (x == 8) + got_largest = 1; + } + + /* These fail with probability 1/10^603. */ + tt_assert(got_smallest); + tt_assert(got_largest); + done: + ; +} + /** Run unit tests for our AES functionality */ static void test_crypto_aes(void *arg) @@ -601,6 +627,22 @@ test_crypto_digests(void *arg) crypto_pk_free(k); } +/** Encode src into dest with OpenSSL's EVP Encode interface, returning the + * length of the encoded data in bytes. + */ +static int +base64_encode_evp(char *dest, char *src, size_t srclen) +{ + const unsigned char *s = (unsigned char*)src; + EVP_ENCODE_CTX ctx; + int len, ret; + + EVP_EncodeInit(&ctx); + EVP_EncodeUpdate(&ctx, (unsigned char *)dest, &len, s, (int)srclen); + EVP_EncodeFinal(&ctx, (unsigned char *)(dest + len), &ret); + return ret+ len; +} + /** Run unit tests for misc crypto formatting functionality (base64, base32, * fingerprints, etc) */ static void @@ -618,7 +660,7 @@ test_crypto_formats(void *arg) /* Base64 tests */ memset(data1, 6, 1024); for (idx = 0; idx < 10; ++idx) { - i = base64_encode(data2, 1024, data1, idx); + i = base64_encode(data2, 1024, data1, idx, 0); tt_int_op(i, OP_GE, 0); j = base64_decode(data3, 1024, data2, i); tt_int_op(j,OP_EQ, idx); @@ -628,7 +670,7 @@ test_crypto_formats(void *arg) strlcpy(data1, "Test string that contains 35 chars.", 1024); strlcat(data1, " 2nd string that contains 35 chars.", 1024); - i = base64_encode(data2, 1024, data1, 71); + i = base64_encode(data2, 1024, data1, 71, 0); tt_int_op(i, OP_GE, 0); j = base64_decode(data3, 1024, data2, i); tt_int_op(j,OP_EQ, 71); @@ -647,6 +689,20 @@ test_crypto_formats(void *arg) tt_assert(digest_from_base64(data3, "###") < 0); + for (i = 0; i < 256; i++) { + /* Test the multiline format Base64 encoder with 0 .. 256 bytes of + * output against OpenSSL. + */ + const size_t enclen = base64_encode_size(i, BASE64_ENCODE_MULTILINE); + data1[i] = i; + j = base64_encode(data2, 1024, data1, i, BASE64_ENCODE_MULTILINE); + tt_int_op(j, OP_EQ, enclen); + j = base64_encode_evp(data3, data1, i); + tt_int_op(j, OP_EQ, enclen); + tt_mem_op(data2, OP_EQ, data3, enclen); + tt_int_op(j, OP_EQ, strlen(data2)); + } + /* Encoding SHA256 */ crypto_rand(data2, DIGEST256_LEN); memset(data2, 100, 1024); @@ -1605,6 +1661,7 @@ test_crypto_siphash(void *arg) struct testcase_t crypto_tests[] = { CRYPTO_LEGACY(formats), CRYPTO_LEGACY(rng), + { "rng_range", test_crypto_rng_range, 0, NULL, NULL }, { "aes_AES", test_crypto_aes, TT_FORK, &passthrough_setup, (void*)"aes" }, { "aes_EVP", test_crypto_aes, TT_FORK, &passthrough_setup, (void*)"evp" }, CRYPTO_LEGACY(sha), diff --git a/src/test/test_ntor.sh.in b/src/test/test_ntor.sh.in new file mode 100644 index 0000000000..5fea8ce31a --- /dev/null +++ b/src/test/test_ntor.sh.in @@ -0,0 +1,9 @@ +#!/bin/sh +# Validate Tor's ntor implementation. + +exitcode=0 + +@PYTHON@ @abs_top_srcdir@/src/test/ntor_ref.py test-tor || exitcode=1 +@PYTHON@ @abs_top_srcdir@/src/test/ntor_ref.py self-test || exitcode=1 + +exit ${exitcode} diff --git a/src/test/test_zero_length_keys.sh.in b/src/test/test_zero_length_keys.sh.in new file mode 100644 index 0000000000..47467baa44 --- /dev/null +++ b/src/test/test_zero_length_keys.sh.in @@ -0,0 +1,10 @@ +#!/bin/sh +# Check that tor regenerates keys when key files are zero-length + +exitcode=0 + +@SHELL@ @abs_top_srcdir@/src/test/zero_length_keys.sh "@builddir@/src/or/tor" -z || exitcode=1 +@SHELL@ @abs_top_srcdir@/src/test/zero_length_keys.sh "@builddir@/src/or/tor" -d || exitcode=1 +@SHELL@ @abs_top_srcdir@/src/test/zero_length_keys.sh "@builddir@/src/or/tor" -e || exitcode=1 + +exit ${exitcode} diff --git a/src/test/zero_length_keys.sh b/src/test/zero_length_keys.sh index 2fd11d38bd..3c61f8d465 100755 --- a/src/test/zero_length_keys.sh +++ b/src/test/zero_length_keys.sh @@ -3,13 +3,13 @@ # Test for bug #13111 - Tor fails to start if onion keys are zero length # # Usage: -# ./zero_length_keys.sh +# ./zero_length_keys.sh PATH_TO_TOR # Run all the tests below -# ./zero_length_keys.sh -z +# ./zero_length_keys.sh PATH_TO_TOR -z # Check tor will launch and regenerate zero-length keys -# ./zero_length_keys.sh -d +# ./zero_length_keys.sh PATH_TO_TOR -d # Check tor regenerates deleted keys (existing behaviour) -# ./zero_length_keys.sh -e +# ./zero_length_keys.sh PATH_TO_TOR -e # Check tor does not overwrite existing keys (existing behaviour) # # Exit Statuses: @@ -19,10 +19,16 @@ # 3: a command failed - the test could not be completed # -if [ $# -lt 1 ]; then +if [ $# -eq 0 ] || [ ! -f ${1} ] || [ ! -x ${1} ]; then + echo "Usage: ${0} PATH_TO_TOR [-z|-d|-e]" + exit 1 +elif [ $# -eq 1 ]; then echo "Testing that tor correctly handles zero-length keys" - "$0" -z && "$0" -d && "$0" -e + "$0" "${1}" -z && "$0" "${1}" -d && "$0" "${1}" -e exit $? +else #[$# -gt 1 ]; then + TOR_BINARY="${1}" + shift fi DATA_DIR=`mktemp -d -t tor_zero_length_keys.XXXXXX` @@ -40,7 +46,7 @@ touch "$DATA_DIR"/empty_torrc # DisableNetwork means that the ORPort won't actually be opened. # 'ExitRelay 0' suppresses a warning. -TOR="./src/or/tor --hush --DisableNetwork 1 --ShutdownWaitLength 0 --ORPort 12345 --ExitRelay 0 -f $DATA_DIR/empty_torrc" +TOR="${TOR_BINARY} --hush --DisableNetwork 1 --ShutdownWaitLength 0 --ORPort 12345 --ExitRelay 0 -f $DATA_DIR/empty_torrc" if [ -s "$DATA_DIR"/keys/secret_id_key ] && [ -s "$DATA_DIR"/keys/secret_onion_key ] && [ -s "$DATA_DIR"/keys/secret_onion_key_ntor ]; then diff --git a/src/tools/tor-gencert.c b/src/tools/tor-gencert.c index 5ae155609a..c0cab7efe7 100644 --- a/src/tools/tor-gencert.c +++ b/src/tools/tor-gencert.c @@ -486,7 +486,8 @@ generate_certificate(void) EVP_PKEY_get1_RSA(signing_key), RSA_PKCS1_PADDING); signed_len = strlen(buf); - base64_encode(buf+signed_len, sizeof(buf)-signed_len, signature, r); + base64_encode(buf+signed_len, sizeof(buf)-signed_len, signature, r, + BASE64_ENCODE_MULTILINE); strlcat(buf, "-----END ID SIGNATURE-----\n" @@ -501,7 +502,8 @@ generate_certificate(void) RSA_PKCS1_PADDING); strlcat(buf, "-----BEGIN SIGNATURE-----\n", sizeof(buf)); signed_len = strlen(buf); - base64_encode(buf+signed_len, sizeof(buf)-signed_len, signature, r); + base64_encode(buf+signed_len, sizeof(buf)-signed_len, signature, r, + BASE64_ENCODE_MULTILINE); strlcat(buf, "-----END SIGNATURE-----\n", sizeof(buf)); if (!(f = fopen(certificate_file, "w"))) { |