diff options
34 files changed, 2461 insertions, 286 deletions
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/bug14784 b/changes/bug14784 new file mode 100644 index 0000000000..1f5014235e --- /dev/null +++ b/changes/bug14784 @@ -0,0 +1,4 @@ + o Minor features: + - Implement a new controller command "status/fresh-relay-descs" to + fetch a descriptor/extrainfo pair that was generated on demand + just for the controller's use. Implements ticket 14784. 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/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/changes/ticket8766 b/changes/ticket8766 new file mode 100644 index 0000000000..33bfc33a57 --- /dev/null +++ b/changes/ticket8766 @@ -0,0 +1,7 @@ + o Minor features: + - Recover better when our clock jumps back many hours, like might + happen for Tails or Whonix users who start with a very wrong + hardware clock, use Tor to discover a more accurate time, and then + fix their clock. Resolves part of ticket 8766. + [I'd call this a major feature if it actually fixed all of the issues.] + 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/crypto.c b/src/common/crypto.c index f05be2e8bf..f338114d76 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -2317,6 +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 - 1) with max being <= INT_MAX and min <= max. + * This is why we add 1 to the maximum value so we can actually get max as + * a return value. */ + 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. */ uint64_t @@ -2379,7 +2413,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 +2460,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 +2661,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 +2731,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 +2755,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 +2780,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 946c002735..0688398f6d 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -1053,6 +1053,10 @@ circuit_note_clock_jumped(int seconds_elapsed) "CLOCK_JUMPED"); circuit_mark_all_unused_circs(); circuit_mark_all_dirty_circs_as_unusable(); + if (seconds_elapsed < 0) { + /* Restart all the timers in case we jumped a long way into the past. */ + reset_all_main_loop_timers(); + } } /** Take the 'extend' <b>cell</b>, pull out addr/port plus the onion @@ -1396,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..8888358fd8 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) { @@ -6966,15 +6980,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 9b0981d84a..b2706bc18a 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -41,6 +41,8 @@ #include "router.h" #include "routerlist.h" #include "routerparse.h" +#include "rendclient.h" +#include "rendcommon.h" #ifndef _WIN32 #include <pwd.h> @@ -1713,6 +1715,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; @@ -2100,6 +2118,46 @@ getinfo_helper_events(control_connection_t *control_conn, return -1; } *answer = bridge_stats; + } else if (!strcmp(question, "status/fresh-relay-descs")) { + if (!server_mode(get_options())) { + *errmsg = "Only relays have descriptors"; + return -1; + } + routerinfo_t *r; + extrainfo_t *e; + if (router_build_fresh_descriptor(&r, &e) < 0) { + *errmsg = "Error generating descriptor"; + return -1; + } + size_t size = r->cache_info.signed_descriptor_len + 1; + if (e) { + size += e->cache_info.signed_descriptor_len + 1; + } + tor_assert(r->cache_info.signed_descriptor_len); + char *descs = tor_malloc(size); + char *cp = descs; + memcpy(cp, signed_descriptor_get_body(&r->cache_info), + r->cache_info.signed_descriptor_len); + cp += r->cache_info.signed_descriptor_len - 1; + if (e) { + if (cp[0] == '\0') { + cp[0] = '\n'; + } else if (cp[0] != '\n') { + cp[1] = '\n'; + cp++; + } + memcpy(cp, signed_descriptor_get_body(&e->cache_info), + e->cache_info.signed_descriptor_len); + cp += e->cache_info.signed_descriptor_len - 1; + } + if (cp[0] == '\n') { + cp[0] = '\0'; + } else if (cp[0] != '\0') { + cp[1] = '\0'; + } + *answer = descs; + routerinfo_free(r); + extrainfo_free(e); } else { return 0; } @@ -2176,6 +2234,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)"), @@ -2210,6 +2270,8 @@ static const getinfo_item_t getinfo_items[] = { "The last bootstrap phase status event that Tor sent."), DOC("status/clients-seen", "Breakdown of client countries seen by a bridge."), + DOC("status/fresh-relay-descs", + "A fresh relay/ei descriptor pair for Tor's current state. Not stored."), DOC("status/version/recommended", "List of currently recommended versions."), DOC("status/version/current", "Status of the current version."), DOC("status/version/num-versioning", "Number of versioning authorities."), 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 07d5ba883f..3fb7de6f6c 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -131,8 +131,6 @@ static uint64_t stats_n_bytes_written = 0; time_t time_of_process_start = 0; /** How many seconds have we been running? */ long stats_n_seconds_working = 0; -/** When do we next launch DNS wildcarding checks? */ -static time_t time_to_check_for_correct_dns = 0; /** How often will we honor SIGNEWNYM requests? */ #define MAX_SIGNEWNYM_RATE 10 @@ -1202,7 +1200,46 @@ get_signewnym_epoch(void) return newnym_epoch; } -static time_t time_to_check_descriptor = 0; +typedef struct { + time_t last_rotated_x509_certificate; + time_t check_v3_certificate; + time_t check_listeners; + time_t download_networkstatus; + time_t try_getting_descriptors; + time_t reset_descriptor_failures; + time_t add_entropy; + time_t write_bridge_status_file; + time_t downrate_stability; + time_t save_stability; + time_t clean_caches; + time_t recheck_bandwidth; + time_t check_for_expired_networkstatus; + time_t write_stats_files; + time_t write_bridge_stats; + time_t check_port_forwarding; + time_t launch_reachability_tests; + time_t retry_dns_init; + time_t next_heartbeat; + time_t check_descriptor; + /** When do we next launch DNS wildcarding checks? */ + time_t check_for_correct_dns; +} time_to_t; + +static time_to_t time_to = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/** Reset all the time_to's so we'll do all our actions again as if we + * just started up. + * Useful if our clock just moved back a long time from the future, + * so we don't wait until that future arrives again before acting. + */ +void +reset_all_main_loop_timers(void) +{ + memset(&time_to, 0, sizeof(time_to)); +} + /** * Update our schedule so that we'll check whether we need to update our * descriptor immediately, rather than after up to CHECK_DESCRIPTOR_INTERVAL @@ -1211,7 +1248,7 @@ static time_t time_to_check_descriptor = 0; void reschedule_descriptor_update_check(void) { - time_to_check_descriptor = 0; + time_to.check_descriptor = 0; } /** Perform regular maintenance tasks. This function gets run once per @@ -1220,26 +1257,7 @@ reschedule_descriptor_update_check(void) static void run_scheduled_events(time_t now) { - static time_t last_rotated_x509_certificate = 0; - static time_t time_to_check_v3_certificate = 0; - static time_t time_to_check_listeners = 0; - static time_t time_to_download_networkstatus = 0; - static time_t time_to_try_getting_descriptors = 0; - static time_t time_to_reset_descriptor_failures = 0; - static time_t time_to_add_entropy = 0; - static time_t time_to_write_bridge_status_file = 0; - static time_t time_to_downrate_stability = 0; - static time_t time_to_save_stability = 0; - static time_t time_to_clean_caches = 0; - static time_t time_to_recheck_bandwidth = 0; - static time_t time_to_check_for_expired_networkstatus = 0; - static time_t time_to_write_stats_files = 0; - static time_t time_to_write_bridge_stats = 0; - static time_t time_to_check_port_forwarding = 0; - static time_t time_to_launch_reachability_tests = 0; static int should_init_bridge_stats = 1; - static time_t time_to_retry_dns_init = 0; - static time_t time_to_next_heartbeat = 0; const or_options_t *options = get_options(); int is_server = server_mode(options); @@ -1280,18 +1298,18 @@ run_scheduled_events(time_t now) } if (!should_delay_dir_fetches(options, NULL) && - time_to_try_getting_descriptors < now) { + time_to.try_getting_descriptors < now) { update_all_descriptor_downloads(now); update_extrainfo_downloads(now); if (router_have_minimum_dir_info()) - time_to_try_getting_descriptors = now + LAZY_DESCRIPTOR_RETRY_INTERVAL; + time_to.try_getting_descriptors = now + LAZY_DESCRIPTOR_RETRY_INTERVAL; else - time_to_try_getting_descriptors = now + GREEDY_DESCRIPTOR_RETRY_INTERVAL; + time_to.try_getting_descriptors = now + GREEDY_DESCRIPTOR_RETRY_INTERVAL; } - if (time_to_reset_descriptor_failures < now) { + if (time_to.reset_descriptor_failures < now) { router_reset_descriptor_download_failures(); - time_to_reset_descriptor_failures = + time_to.reset_descriptor_failures = now + DESCRIPTOR_FAILURE_RESET_INTERVAL; } @@ -1300,28 +1318,29 @@ run_scheduled_events(time_t now) /* 1b. Every MAX_SSL_KEY_LIFETIME_INTERNAL seconds, we change our * TLS context. */ - if (!last_rotated_x509_certificate) - last_rotated_x509_certificate = now; - if (last_rotated_x509_certificate+MAX_SSL_KEY_LIFETIME_INTERNAL < now) { + if (!time_to.last_rotated_x509_certificate) + time_to.last_rotated_x509_certificate = now; + if (time_to.last_rotated_x509_certificate + + MAX_SSL_KEY_LIFETIME_INTERNAL < now) { log_info(LD_GENERAL,"Rotating tls context."); if (router_initialize_tls_context() < 0) { log_warn(LD_BUG, "Error reinitializing TLS context"); /* XXX is it a bug here, that we just keep going? -RD */ } - last_rotated_x509_certificate = now; + time_to.last_rotated_x509_certificate = now; /* We also make sure to rotate the TLS connections themselves if they've * been up for too long -- but that's done via is_bad_for_new_circs in * connection_run_housekeeping() above. */ } - if (time_to_add_entropy < now) { - if (time_to_add_entropy) { + if (time_to.add_entropy < now) { + if (time_to.add_entropy) { /* We already seeded once, so don't die on failure. */ crypto_seed_rng(0); } /** How often do we add more entropy to OpenSSL's RNG pool? */ #define ENTROPY_INTERVAL (60*60) - time_to_add_entropy = now + ENTROPY_INTERVAL; + time_to.add_entropy = now + ENTROPY_INTERVAL; } /* 1c. If we have to change the accounting interval or record @@ -1329,10 +1348,10 @@ run_scheduled_events(time_t now) if (accounting_is_enabled(options)) accounting_run_housekeeping(now); - if (time_to_launch_reachability_tests < now && + if (time_to.launch_reachability_tests < now && (authdir_mode_tests_reachability(options)) && !net_is_disabled()) { - time_to_launch_reachability_tests = now + REACHABILITY_TEST_INTERVAL; + time_to.launch_reachability_tests = now + REACHABILITY_TEST_INTERVAL; /* try to determine reachability of the other Tor relays */ dirserv_test_reachability(now); } @@ -1340,29 +1359,29 @@ run_scheduled_events(time_t now) /* 1d. Periodically, we discount older stability information so that new * stability info counts more, and save the stability information to disk as * appropriate. */ - if (time_to_downrate_stability < now) - time_to_downrate_stability = rep_hist_downrate_old_runs(now); + if (time_to.downrate_stability < now) + time_to.downrate_stability = rep_hist_downrate_old_runs(now); if (authdir_mode_tests_reachability(options)) { - if (time_to_save_stability < now) { - if (time_to_save_stability && rep_hist_record_mtbf_data(now, 1)<0) { + if (time_to.save_stability < now) { + if (time_to.save_stability && rep_hist_record_mtbf_data(now, 1)<0) { log_warn(LD_GENERAL, "Couldn't store mtbf data."); } #define SAVE_STABILITY_INTERVAL (30*60) - time_to_save_stability = now + SAVE_STABILITY_INTERVAL; + time_to.save_stability = now + SAVE_STABILITY_INTERVAL; } } /* 1e. Periodically, if we're a v3 authority, we check whether our cert is * close to expiring and warn the admin if it is. */ - if (time_to_check_v3_certificate < now) { + if (time_to.check_v3_certificate < now) { v3_authority_check_key_expiry(); #define CHECK_V3_CERTIFICATE_INTERVAL (5*60) - time_to_check_v3_certificate = now + CHECK_V3_CERTIFICATE_INTERVAL; + time_to.check_v3_certificate = now + CHECK_V3_CERTIFICATE_INTERVAL; } /* 1f. Check whether our networkstatus has expired. */ - if (time_to_check_for_expired_networkstatus < now) { + if (time_to.check_for_expired_networkstatus < now) { networkstatus_t *ns = networkstatus_get_latest_consensus(); /*XXXX RD: This value needs to be the same as REASONABLY_LIVE_TIME in * networkstatus_get_reasonably_live_consensus(), but that value is way @@ -1373,68 +1392,68 @@ run_scheduled_events(time_t now) router_dir_info_changed(); } #define CHECK_EXPIRED_NS_INTERVAL (2*60) - time_to_check_for_expired_networkstatus = now + CHECK_EXPIRED_NS_INTERVAL; + time_to.check_for_expired_networkstatus = now + CHECK_EXPIRED_NS_INTERVAL; } /* 1g. Check whether we should write statistics to disk. */ - if (time_to_write_stats_files < now) { + if (time_to.write_stats_files < now) { #define CHECK_WRITE_STATS_INTERVAL (60*60) - time_t next_time_to_write_stats_files = (time_to_write_stats_files > 0 ? - time_to_write_stats_files : now) + CHECK_WRITE_STATS_INTERVAL; + time_t next_time_to_write_stats_files = (time_to.write_stats_files > 0 ? + time_to.write_stats_files : now) + CHECK_WRITE_STATS_INTERVAL; if (options->CellStatistics) { time_t next_write = - rep_hist_buffer_stats_write(time_to_write_stats_files); + rep_hist_buffer_stats_write(time_to.write_stats_files); if (next_write && next_write < next_time_to_write_stats_files) next_time_to_write_stats_files = next_write; } if (options->DirReqStatistics) { - time_t next_write = geoip_dirreq_stats_write(time_to_write_stats_files); + time_t next_write = geoip_dirreq_stats_write(time_to.write_stats_files); if (next_write && next_write < next_time_to_write_stats_files) next_time_to_write_stats_files = next_write; } if (options->EntryStatistics) { - time_t next_write = geoip_entry_stats_write(time_to_write_stats_files); + time_t next_write = geoip_entry_stats_write(time_to.write_stats_files); if (next_write && next_write < next_time_to_write_stats_files) next_time_to_write_stats_files = next_write; } if (options->HiddenServiceStatistics) { - time_t next_write = rep_hist_hs_stats_write(time_to_write_stats_files); + time_t next_write = rep_hist_hs_stats_write(time_to.write_stats_files); if (next_write && next_write < next_time_to_write_stats_files) next_time_to_write_stats_files = next_write; } if (options->ExitPortStatistics) { - time_t next_write = rep_hist_exit_stats_write(time_to_write_stats_files); + time_t next_write = rep_hist_exit_stats_write(time_to.write_stats_files); if (next_write && next_write < next_time_to_write_stats_files) next_time_to_write_stats_files = next_write; } if (options->ConnDirectionStatistics) { - time_t next_write = rep_hist_conn_stats_write(time_to_write_stats_files); + time_t next_write = rep_hist_conn_stats_write(time_to.write_stats_files); if (next_write && next_write < next_time_to_write_stats_files) next_time_to_write_stats_files = next_write; } if (options->BridgeAuthoritativeDir) { - time_t next_write = rep_hist_desc_stats_write(time_to_write_stats_files); + time_t next_write = rep_hist_desc_stats_write(time_to.write_stats_files); if (next_write && next_write < next_time_to_write_stats_files) next_time_to_write_stats_files = next_write; } - time_to_write_stats_files = next_time_to_write_stats_files; + time_to.write_stats_files = next_time_to_write_stats_files; } /* 1h. Check whether we should write bridge statistics to disk. */ if (should_record_bridge_info(options)) { - if (time_to_write_bridge_stats < now) { + if (time_to.write_bridge_stats < now) { if (should_init_bridge_stats) { /* (Re-)initialize bridge statistics. */ geoip_bridge_stats_init(now); - time_to_write_bridge_stats = now + WRITE_STATS_INTERVAL; + time_to.write_bridge_stats = now + WRITE_STATS_INTERVAL; should_init_bridge_stats = 0; } else { /* Possibly write bridge statistics to disk and ask when to write * them next time. */ - time_to_write_bridge_stats = geoip_bridge_stats_write( - time_to_write_bridge_stats); + time_to.write_bridge_stats = geoip_bridge_stats_write( + time_to.write_bridge_stats); } } } else if (!should_init_bridge_stats) { @@ -1444,19 +1463,19 @@ run_scheduled_events(time_t now) } /* Remove old information from rephist and the rend cache. */ - if (time_to_clean_caches < now) { + if (time_to.clean_caches < now) { rep_history_clean(now - options->RephistTrackTime); rend_cache_clean(now); rend_cache_clean_v2_descs_as_dir(now, 0); microdesc_cache_rebuild(NULL, 0); #define CLEAN_CACHES_INTERVAL (30*60) - time_to_clean_caches = now + CLEAN_CACHES_INTERVAL; + time_to.clean_caches = now + CLEAN_CACHES_INTERVAL; } #define RETRY_DNS_INTERVAL (10*60) /* If we're a server and initializing dns failed, retry periodically. */ - if (time_to_retry_dns_init < now) { - time_to_retry_dns_init = now + RETRY_DNS_INTERVAL; + if (time_to.retry_dns_init < now) { + time_to.retry_dns_init = now + RETRY_DNS_INTERVAL; if (is_server && has_dns_init_failed()) dns_init(); } @@ -1471,9 +1490,9 @@ run_scheduled_events(time_t now) /* 2b. Once per minute, regenerate and upload the descriptor if the old * one is inaccurate. */ - if (time_to_check_descriptor < now && !options->DisableNetwork) { + if (time_to.check_descriptor < now && !options->DisableNetwork) { static int dirport_reachability_count = 0; - time_to_check_descriptor = now + CHECK_DESCRIPTOR_INTERVAL; + time_to.check_descriptor = now + CHECK_DESCRIPTOR_INTERVAL; check_descriptor_bandwidth_changed(now); check_descriptor_ipaddress_changed(now); mark_my_descriptor_dirty_if_too_old(now); @@ -1487,18 +1506,18 @@ run_scheduled_events(time_t now) consider_testing_reachability(1, dirport_reachability_count==0); if (++dirport_reachability_count > 5) dirport_reachability_count = 0; - } else if (time_to_recheck_bandwidth < now) { + } else if (time_to.recheck_bandwidth < now) { /* If we haven't checked for 12 hours and our bandwidth estimate is * low, do another bandwidth test. This is especially important for * bridges, since they might go long periods without much use. */ const routerinfo_t *me = router_get_my_routerinfo(); - if (time_to_recheck_bandwidth && me && + if (time_to.recheck_bandwidth && me && me->bandwidthcapacity < me->bandwidthrate && me->bandwidthcapacity < 51200) { reset_bandwidth_test(); } #define BANDWIDTH_RECHECK_INTERVAL (12*60*60) - time_to_recheck_bandwidth = now + BANDWIDTH_RECHECK_INTERVAL; + time_to.recheck_bandwidth = now + BANDWIDTH_RECHECK_INTERVAL; } } @@ -1516,8 +1535,8 @@ run_scheduled_events(time_t now) #define networkstatus_dl_check_interval(o) ((o)->TestingTorNetwork ? 1 : 60) if (!should_delay_dir_fetches(options, NULL) && - time_to_download_networkstatus < now) { - time_to_download_networkstatus = + time_to.download_networkstatus < now) { + time_to.download_networkstatus = now + networkstatus_dl_check_interval(options); update_networkstatus_downloads(now); } @@ -1547,9 +1566,9 @@ run_scheduled_events(time_t now) connection_expire_held_open(); /* 3d. And every 60 seconds, we relaunch listeners if any died. */ - if (!net_is_disabled() && time_to_check_listeners < now) { + if (!net_is_disabled() && time_to.check_listeners < now) { retry_all_listeners(NULL, NULL, 0); - time_to_check_listeners = now+60; + time_to.check_listeners = now+60; } /* 4. Every second, we try a new circuit if there are no valid @@ -1601,28 +1620,29 @@ run_scheduled_events(time_t now) * to us. */ if (!net_is_disabled() && public_server_mode(options) && - time_to_check_for_correct_dns < 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); + if (!time_to.check_for_correct_dns) { + 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 + + time_to.check_for_correct_dns = now + 12*3600 + crypto_rand_int(12*3600); } } /* 10. write bridge networkstatus file to disk */ if (options->BridgeAuthoritativeDir && - time_to_write_bridge_status_file < now) { + time_to.write_bridge_status_file < now) { networkstatus_dump_bridge_status_to_file(now); #define BRIDGE_STATUSFILE_INTERVAL (30*60) - time_to_write_bridge_status_file = now+BRIDGE_STATUSFILE_INTERVAL; + time_to.write_bridge_status_file = now+BRIDGE_STATUSFILE_INTERVAL; } /* 11. check the port forwarding app */ if (!net_is_disabled() && - time_to_check_port_forwarding < now && + time_to.check_port_forwarding < now && options->PortForwarding && is_server) { #define PORT_FORWARDING_CHECK_INTERVAL 5 @@ -1635,7 +1655,7 @@ run_scheduled_events(time_t now) SMARTLIST_FOREACH(ports_to_forward, char *, cp, tor_free(cp)); smartlist_free(ports_to_forward); } - time_to_check_port_forwarding = now+PORT_FORWARDING_CHECK_INTERVAL; + time_to.check_port_forwarding = now+PORT_FORWARDING_CHECK_INTERVAL; } /* 11b. check pending unconfigured managed proxies */ @@ -1644,10 +1664,10 @@ run_scheduled_events(time_t now) /* 12. write the heartbeat message */ if (options->HeartbeatPeriod && - time_to_next_heartbeat <= now) { - if (time_to_next_heartbeat) /* don't log the first heartbeat */ + time_to.next_heartbeat <= now) { + if (time_to.next_heartbeat) /* don't log the first heartbeat */ log_heartbeat(now); - time_to_next_heartbeat = now+options->HeartbeatPeriod; + time_to.next_heartbeat = now+options->HeartbeatPeriod; } } @@ -1747,8 +1767,6 @@ second_elapsed_callback(periodic_timer_t *timer, void *arg) if (seconds_elapsed < -NUM_JUMPED_SECONDS_BEFORE_WARN || seconds_elapsed >= NUM_JUMPED_SECONDS_BEFORE_WARN) { circuit_note_clock_jumped(seconds_elapsed); - /* XXX if the time jumps *back* many months, do our events in - * run_scheduled_events() recover? I don't think they do. -RD */ } else if (seconds_elapsed > 0) stats_n_seconds_working += seconds_elapsed; @@ -1872,7 +1890,7 @@ dns_servers_relaunch_checks(void) { if (server_mode(get_options())) { dns_reset_correctness_checks(); - time_to_check_for_correct_dns = 0; + time_to.check_for_correct_dns = 0; } } diff --git a/src/or/main.h b/src/or/main.h index f77b4711c5..542eab6565 100644 --- a/src/or/main.h +++ b/src/or/main.h @@ -52,6 +52,7 @@ void directory_info_has_arrived(time_t now, int from_cache); void ip_address_changed(int at_interface); void dns_servers_relaunch_checks(void); +void reset_all_main_loop_timers(void); void reschedule_descriptor_update_check(void); MOCK_DECL(long,get_uptime,(void)); diff --git a/src/or/or.h b/src/or/or.h index d548aeabb6..2f6890a9ef 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -4805,12 +4805,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 @@ -4864,6 +4865,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 14f311c1d5..84d0ccef55 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -690,12 +690,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 3fea07f52a..371c6bf9b8 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 2ddaa895fc..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)) { @@ -1802,12 +1804,15 @@ router_pick_published_address(const or_options_t *options, uint32_t *addr) return 0; } -/** If <b>force</b> is true, or our descriptor is out-of-date, rebuild a fresh - * routerinfo, signed server descriptor, and extra-info document for this OR. - * Return 0 on success, -1 on temporary error. +/** Build a fresh routerinfo, signed server descriptor, and extra-info document + * for this OR. Set r to the generated routerinfo, e to the generated + * extra-info document. Return 0 on success, -1 on temporary error. Failure to + * generate an extra-info document is not an error and is indicated by setting + * e to NULL. Caller is responsible for freeing generated documents if 0 is + * returned. */ int -router_rebuild_descriptor(int force) +router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e) { routerinfo_t *ri; extrainfo_t *ei; @@ -1816,20 +1821,11 @@ router_rebuild_descriptor(int force) int hibernating = we_are_hibernating(); const or_options_t *options = get_options(); - if (desc_clean_since && !force) - return 0; - - if (router_pick_published_address(options, &addr) < 0 || - router_get_advertised_or_port(options) == 0) { - /* Stop trying to rebuild our descriptor every second. We'll - * learn that it's time to try again when ip_address_changed() - * marks it dirty. */ - desc_clean_since = time(NULL); + if (router_pick_published_address(options, &addr) < 0) { + log_warn(LD_CONFIG, "Don't know my address while generating descriptor"); return -1; } - log_info(LD_OR, "Rebuilding relay descriptor%s", force ? " (forced)" : ""); - ri = tor_malloc_zero(sizeof(routerinfo_t)); ri->cache_info.routerlist_index = -1; ri->nickname = tor_strdup(options->Nickname); @@ -2024,6 +2020,41 @@ router_rebuild_descriptor(int force) tor_assert(! routerinfo_incompatible_with_extrainfo(ri, ei, NULL, NULL)); } + *r = ri; + *e = ei; + return 0; +} + +/** If <b>force</b> is true, or our descriptor is out-of-date, rebuild a fresh + * routerinfo, signed server descriptor, and extra-info document for this OR. + * Return 0 on success, -1 on temporary error. + */ +int +router_rebuild_descriptor(int force) +{ + routerinfo_t *ri; + extrainfo_t *ei; + uint32_t addr; + const or_options_t *options = get_options(); + + if (desc_clean_since && !force) + return 0; + + if (router_pick_published_address(options, &addr) < 0 || + router_get_advertised_or_port(options) == 0) { + /* Stop trying to rebuild our descriptor every second. We'll + * learn that it's time to try again when ip_address_changed() + * marks it dirty. */ + desc_clean_since = time(NULL); + return -1; + } + + log_info(LD_OR, "Rebuilding relay descriptor%s", force ? " (forced)" : ""); + + if (router_build_fresh_descriptor(&ri, &ei) < 0) { + return -1; + } + routerinfo_free(desc_routerinfo); desc_routerinfo = ri; extrainfo_free(desc_extrainfo); @@ -2424,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/router.h b/src/or/router.h index 8108ffb22f..73b43bc751 100644 --- a/src/or/router.h +++ b/src/or/router.h @@ -89,6 +89,7 @@ const uint8_t *router_get_my_id_digest(void); int router_extrainfo_digest_is_me(const char *digest); int router_is_me(const routerinfo_t *router); int router_pick_published_address(const or_options_t *options, uint32_t *addr); +int router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e); int router_rebuild_descriptor(int force); char *router_dump_router_to_string(routerinfo_t *router, crypto_pk_t *ident_key); diff --git a/src/or/routerparse.c b/src/or/routerparse.c index fd3971c587..b9a36a3eb1 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; } 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_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/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"))) { |