diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/or/circuitbuild.c | 2 | ||||
-rw-r--r-- | src/or/config.c | 5 | ||||
-rw-r--r-- | src/or/entrynodes.c | 157 | ||||
-rw-r--r-- | src/or/entrynodes.h | 6 | ||||
-rw-r--r-- | src/or/nodelist.c | 8 | ||||
-rw-r--r-- | src/or/or.h | 4 | ||||
-rw-r--r-- | src/or/policies.c | 95 | ||||
-rw-r--r-- | src/or/policies.h | 3 | ||||
-rw-r--r-- | src/test/fuzz/fuzz_vrs.c | 2 | ||||
-rw-r--r-- | src/test/test_policy.c | 534 | ||||
-rw-r--r-- | src/test/test_tortls.c | 43 |
11 files changed, 768 insertions, 91 deletions
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index f11c865ad0..88445f9248 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -2369,7 +2369,7 @@ onion_extend_cpath(origin_circuit_t *circ) int client = (server_mode(get_options()) == 0); info = extend_info_from_node(r, client); /* Clients can fail to find an allowed address */ - tor_assert(info || client); + tor_assert_nonfatal(info || client); } } else { const node_t *r = diff --git a/src/or/config.c b/src/or/config.c index 1ea8712379..a07719ecb8 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -358,7 +358,7 @@ static config_var_t option_vars_[] = { VAR("HiddenServiceMaxStreams",LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceMaxStreamsCloseCircuit",LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceNumIntroductionPoints", LINELIST_S, RendConfigLines, NULL), - V(HiddenServiceStatistics, BOOL, "1"), + VAR("HiddenServiceStatistics", BOOL, HiddenServiceStatistics_option, "1"), V(HidServAuth, LINELIST, NULL), V(CloseHSClientCircuitsImmediatelyOnTimeout, BOOL, "0"), V(CloseHSServiceRendCircuitsImmediatelyOnTimeout, BOOL, "0"), @@ -2004,6 +2004,8 @@ options_act(const or_options_t *old_options) /* Only collect directory-request statistics on relays and bridges. */ options->DirReqStatistics = options->DirReqStatistics_option && server_mode(options); + options->HiddenServiceStatistics = + options->HiddenServiceStatistics_option && server_mode(options); if (options->CellStatistics || options->DirReqStatistics || options->EntryStatistics || options->ExitPortStatistics || @@ -2018,7 +2020,6 @@ options_act(const or_options_t *old_options) options->CellStatistics = 0; options->EntryStatistics = 0; options->ConnDirectionStatistics = 0; - options->HiddenServiceStatistics = 0; options->ExitPortStatistics = 0; } diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c index c5fb92e35a..b7c05f1930 100644 --- a/src/or/entrynodes.c +++ b/src/or/entrynodes.c @@ -185,6 +185,16 @@ should_apply_guardfraction(const networkstatus_t *ns) return options->UseGuardFraction; } +/** Return true iff we know a descriptor for <b>guard</b> */ +static int +guard_has_descriptor(const entry_guard_t *guard) +{ + const node_t *node = node_get_by_id(guard->identity); + if (!node) + return 0; + return node_has_descriptor(node); +} + /** * Try to determine the correct type for a selection named "name", * if <b>type</b> is GS_TYPE_INFER. @@ -521,6 +531,52 @@ get_extreme_restriction_threshold(void) 1, INT32_MAX); return pct / 100.0; } + +/* Mark <b>guard</b> as maybe reachable again. */ +static void +mark_guard_maybe_reachable(entry_guard_t *guard) +{ + if (guard->is_reachable != GUARD_REACHABLE_NO) { + return; + } + + /* Note that we do not clear failing_since: this guard is now only + * _maybe-reachable_. */ + guard->is_reachable = GUARD_REACHABLE_MAYBE; + if (guard->is_filtered_guard) + guard->is_usable_filtered_guard = 1; +} + +/** + * Called when the network comes up after having seemed to be down for + * a while: Mark the primary guards as maybe-reachable so that we'll + * try them again. + */ +STATIC void +mark_primary_guards_maybe_reachable(guard_selection_t *gs) +{ + tor_assert(gs); + + if (!gs->primary_guards_up_to_date) + entry_guards_update_primary(gs); + + SMARTLIST_FOREACH_BEGIN(gs->primary_entry_guards, entry_guard_t *, guard) { + mark_guard_maybe_reachable(guard); + } SMARTLIST_FOREACH_END(guard); +} + +/* Called when we exhaust all guards in our sampled set: Marks all guards as + maybe-reachable so that we 'll try them again. */ +static void +mark_all_guards_maybe_reachable(guard_selection_t *gs) +{ + tor_assert(gs); + + SMARTLIST_FOREACH_BEGIN(gs->sampled_entry_guards, entry_guard_t *, guard) { + mark_guard_maybe_reachable(guard); + } SMARTLIST_FOREACH_END(guard); +} + /**@}*/ /** @@ -1112,18 +1168,7 @@ remove_guard_from_confirmed_and_primary_lists(guard_selection_t *gs, } if (guard->confirmed_idx >= 0) { - entry_guard_t *found_guard = NULL; - if (guard->confirmed_idx < smartlist_len(gs->confirmed_entry_guards)) - found_guard = smartlist_get(gs->confirmed_entry_guards, - guard->confirmed_idx); - if (BUG(guard != found_guard)) { - // LCOV_EXCL_START - smartlist_remove_keeporder(gs->confirmed_entry_guards, guard); - // LCOV_EXCL_STOP - } else { - smartlist_del_keeporder(gs->confirmed_entry_guards, - guard->confirmed_idx); - } + smartlist_remove_keeporder(gs->confirmed_entry_guards, guard); guard->confirmed_idx = -1; guard->confirmed_on_date = 0; } else { @@ -1447,6 +1492,7 @@ sample_reachable_filtered_entry_guards(guard_selection_t *gs, const unsigned exclude_primary = flags & SAMPLE_EXCLUDE_PRIMARY; const unsigned exclude_pending = flags & SAMPLE_EXCLUDE_PENDING; const unsigned no_update_primary = flags & SAMPLE_NO_UPDATE_PRIMARY; + const unsigned need_descriptor = flags & SAMPLE_EXCLUDE_NO_DESCRIPTOR; SMARTLIST_FOREACH_BEGIN(gs->sampled_entry_guards, entry_guard_t *, guard) { entry_guard_consider_retry(guard); @@ -1480,6 +1526,8 @@ sample_reachable_filtered_entry_guards(guard_selection_t *gs, continue; if (exclude_pending && guard->is_pending) continue; + if (need_descriptor && !guard_has_descriptor(guard)) + continue; smartlist_add(reachable_filtered_sample, guard); } SMARTLIST_FOREACH_END(guard); @@ -1777,6 +1825,7 @@ select_entry_guard_for_circuit(guard_selection_t *gs, const entry_guard_restriction_t *rst, unsigned *state_out) { + const int need_descriptor = (usage == GUARD_USAGE_TRAFFIC); tor_assert(gs); tor_assert(state_out); @@ -1793,6 +1842,9 @@ select_entry_guard_for_circuit(guard_selection_t *gs, if (! entry_guard_obeys_restriction(guard, rst)) continue; if (guard->is_reachable != GUARD_REACHABLE_NO) { + if (need_descriptor && BUG(!guard_has_descriptor(guard))) { + continue; + } *state_out = GUARD_CIRC_STATE_USABLE_ON_COMPLETION; guard->last_tried_to_connect = approx_time(); smartlist_add(usable_primary_guards, guard); @@ -1821,6 +1873,8 @@ select_entry_guard_for_circuit(guard_selection_t *gs, continue; entry_guard_consider_retry(guard); if (guard->is_usable_filtered_guard && ! guard->is_pending) { + if (need_descriptor && !guard_has_descriptor(guard)) + continue; /* not a bug */ guard->is_pending = 1; guard->last_tried_to_connect = approx_time(); *state_out = GUARD_CIRC_STATE_USABLE_IF_NO_BETTER_GUARD; @@ -1836,13 +1890,19 @@ select_entry_guard_for_circuit(guard_selection_t *gs, random from {USABLE_FILTERED_GUARDS}." */ { entry_guard_t *guard; + unsigned flags = 0; + if (need_descriptor) + flags |= SAMPLE_EXCLUDE_NO_DESCRIPTOR; guard = sample_reachable_filtered_entry_guards(gs, rst, SAMPLE_EXCLUDE_CONFIRMED | SAMPLE_EXCLUDE_PRIMARY | - SAMPLE_EXCLUDE_PENDING); + SAMPLE_EXCLUDE_PENDING | + flags); if (guard == NULL) { - log_info(LD_GUARD, "Absolutely no sampled guards were available."); + log_info(LD_GUARD, "Absolutely no sampled guards were available. " + "Marking all guards for retry and starting from top again."); + mark_all_guards_maybe_reachable(gs); return NULL; } guard->is_pending = 1; @@ -1880,30 +1940,6 @@ entry_guards_note_guard_failure(guard_selection_t *gs, } /** - * Called when the network comes up after having seemed to be down for - * a while: Mark the primary guards as maybe-reachable so that we'll - * try them again. - */ -STATIC void -mark_primary_guards_maybe_reachable(guard_selection_t *gs) -{ - if (!gs->primary_guards_up_to_date) - entry_guards_update_primary(gs); - - SMARTLIST_FOREACH_BEGIN(gs->primary_entry_guards, entry_guard_t *, guard) { - if (guard->is_reachable != GUARD_REACHABLE_NO) - continue; - - /* Note that we do not clear failing_since: this guard is now only - * _maybe-reachable_. */ - guard->is_reachable = GUARD_REACHABLE_MAYBE; - if (guard->is_filtered_guard) - guard->is_usable_filtered_guard = 1; - - } SMARTLIST_FOREACH_END(guard); -} - -/** * Note that we successfully connected to, and built a circuit through * <b>guard</b>. Given the old guard-state of the circuit in <b>old_state</b>, * return the new guard-state of the circuit. @@ -2068,6 +2104,8 @@ entry_guard_pick_for_circuit(guard_selection_t *gs, // XXXX prop271 check Ed ID. if (! node) goto fail; + if (BUG(usage != GUARD_USAGE_DIRGUARD && !node_has_descriptor(node))) + goto fail; *chosen_node_out = node; *guard_state_out = tor_malloc_zero(sizeof(circuit_guard_state_t)); @@ -2172,7 +2210,11 @@ entry_guard_chan_failed(channel_t *chan) continue; origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ); - entry_guard_failed(&origin_circ->guard_state); + if (origin_circ->guard_state) { + /* We might have no guard state if we didn't use a guard on this + * circuit (eg it's for a fallback directory). */ + entry_guard_failed(&origin_circ->guard_state); + } } SMARTLIST_FOREACH_END(circ); smartlist_free(pending); } @@ -3310,6 +3352,43 @@ guards_retry_optimistic(const or_options_t *options) return 1; } +/** + * Return true iff we know enough directory information to construct + * circuits through all of the primary guards we'd currently use. + */ +int +guard_selection_have_enough_dir_info_to_build_circuits(guard_selection_t *gs) +{ + if (!gs->primary_guards_up_to_date) + entry_guards_update_primary(gs); + + const int num_primary = get_n_primary_guards_to_use(GUARD_USAGE_TRAFFIC); + int n_missing_descriptors = 0; + int n_considered = 0; + + SMARTLIST_FOREACH_BEGIN(gs->primary_entry_guards, entry_guard_t *, guard) { + entry_guard_consider_retry(guard); + if (guard->is_reachable == GUARD_REACHABLE_NO) + continue; + n_considered++; + if (!guard_has_descriptor(guard)) + n_missing_descriptors++; + if (n_considered >= num_primary) + break; + } SMARTLIST_FOREACH_END(guard); + + return n_missing_descriptors == 0; +} + +/** As guard_selection_have_enough_dir_info_to_build_circuits, but uses + * the default guard selection. */ +int +entry_guards_have_enough_dir_info_to_build_circuits(void) +{ + return guard_selection_have_enough_dir_info_to_build_circuits( + get_guard_selection_info()); +} + /** Free one guard selection context */ STATIC void guard_selection_free(guard_selection_t *gs) diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h index d469df7e3d..f02901f5d7 100644 --- a/src/or/entrynodes.h +++ b/src/or/entrynodes.h @@ -482,6 +482,7 @@ STATIC entry_guard_t *get_sampled_guard_with_id(guard_selection_t *gs, const uint8_t *rsa_id); MOCK_DECL(STATIC time_t, randomize_time, (time_t now, time_t max_backdate)); + STATIC entry_guard_t *entry_guard_add_to_sample(guard_selection_t *gs, const node_t *node); STATIC entry_guard_t *entry_guards_expand_sample(guard_selection_t *gs); @@ -498,6 +499,7 @@ STATIC int entry_guards_all_primary_guards_are_down(guard_selection_t *gs); #define SAMPLE_EXCLUDE_PRIMARY (1u<<1) #define SAMPLE_EXCLUDE_PENDING (1u<<2) #define SAMPLE_NO_UPDATE_PRIMARY (1u<<3) +#define SAMPLE_EXCLUDE_NO_DESCRIPTOR (1u<<4) /**@}*/ STATIC entry_guard_t *sample_reachable_filtered_entry_guards( guard_selection_t *gs, @@ -565,6 +567,10 @@ int getinfo_helper_entry_guards(control_connection_t *conn, int entries_known_but_down(const or_options_t *options); void entries_retry_all(const or_options_t *options); +int guard_selection_have_enough_dir_info_to_build_circuits( + guard_selection_t *gs); +int entry_guards_have_enough_dir_info_to_build_circuits(void); + void entry_guards_free_all(void); double pathbias_get_close_success_count(entry_guard_t *guard); diff --git a/src/or/nodelist.c b/src/or/nodelist.c index 804af297ba..96e95baf5a 100644 --- a/src/or/nodelist.c +++ b/src/or/nodelist.c @@ -43,6 +43,7 @@ #include "config.h" #include "control.h" #include "dirserv.h" +#include "entrynodes.h" #include "geoip.h" #include "main.h" #include "microdesc.h" @@ -1991,6 +1992,13 @@ update_router_have_minimum_dir_info(void) using_md = consensus->flavor == FLAV_MICRODESC; + if (! entry_guards_have_enough_dir_info_to_build_circuits()) { + strlcpy(dir_info_status, "We're missing descriptors for some of our " + "primary entry guards", sizeof(dir_info_status)); + res = 0; + goto done; + } + /* Check fraction of available paths */ { char *status = NULL; diff --git a/src/or/or.h b/src/or/or.h index 18fff78942..0db9f23604 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -4168,6 +4168,10 @@ typedef struct { /** If true, the user wants us to collect statistics as hidden service * directory, introduction point, or rendezvous point. */ + int HiddenServiceStatistics_option; + /** Internal variable to remember whether we're actually acting on + * HiddenServiceStatistics_option -- yes if it's set and we're a server, + * else no. */ int HiddenServiceStatistics; /** If true, include statistics file contents in extra-info documents. */ diff --git a/src/or/policies.c b/src/or/policies.c index aea1b11829..150e52721a 100644 --- a/src/or/policies.c +++ b/src/or/policies.c @@ -2353,7 +2353,26 @@ policy_summary_item_split(policy_summary_item_t* old, uint16_t new_starts) * my immortal soul, he can clean it up himself. */ #define AT(x) ((policy_summary_item_t*)smartlist_get(summary, x)) -#define REJECT_CUTOFF_COUNT (1<<25) +#define IPV4_BITS (32) +/* Every IPv4 address is counted as one rejection */ +#define REJECT_CUTOFF_SCALE_IPV4 (0) +/* Ports are rejected in an IPv4 summary if they are rejected in more than two + * IPv4 /8 address blocks */ +#define REJECT_CUTOFF_COUNT_IPV4 (U64_LITERAL(1) << \ + (IPV4_BITS - REJECT_CUTOFF_SCALE_IPV4 - 7)) + +#define IPV6_BITS (128) +/* IPv6 /64s are counted as one rejection, anything smaller is ignored */ +#define REJECT_CUTOFF_SCALE_IPV6 (64) +/* Ports are rejected in an IPv6 summary if they are rejected in more than one + * IPv6 /16 address block. + * This is rougly equivalent to the IPv4 cutoff, as only five IPv6 /12s (and + * some scattered smaller blocks) have been allocated to the RIRs. + * Network providers are typically allocated one or more IPv6 /32s. + */ +#define REJECT_CUTOFF_COUNT_IPV6 (U64_LITERAL(1) << \ + (IPV6_BITS - REJECT_CUTOFF_SCALE_IPV6 - 16)) + /** Split an exit policy summary so that prt_min and prt_max * fall at exactly the start and end of an item respectively. */ @@ -2386,35 +2405,82 @@ policy_summary_split(smartlist_t *summary, return start_at_index; } -/** Mark port ranges as accepted if they are below the reject_count */ +/** Mark port ranges as accepted if they are below the reject_count for family + */ static void policy_summary_accept(smartlist_t *summary, - uint16_t prt_min, uint16_t prt_max) + uint16_t prt_min, uint16_t prt_max, + sa_family_t family) { + tor_assert_nonfatal_once(family == AF_INET || family == AF_INET6); + uint64_t family_reject_count = ((family == AF_INET) ? + REJECT_CUTOFF_COUNT_IPV4 : + REJECT_CUTOFF_COUNT_IPV6); + int i = policy_summary_split(summary, prt_min, prt_max); while (i < smartlist_len(summary) && AT(i)->prt_max <= prt_max) { if (!AT(i)->accepted && - AT(i)->reject_count <= REJECT_CUTOFF_COUNT) + AT(i)->reject_count <= family_reject_count) AT(i)->accepted = 1; i++; } tor_assert(i < smartlist_len(summary) || prt_max==65535); } -/** Count the number of addresses in a network with prefixlen maskbits - * against the given portrange. */ +/** Count the number of addresses in a network in family with prefixlen + * maskbits against the given portrange. */ static void policy_summary_reject(smartlist_t *summary, maskbits_t maskbits, - uint16_t prt_min, uint16_t prt_max) + uint16_t prt_min, uint16_t prt_max, + sa_family_t family) { + tor_assert_nonfatal_once(family == AF_INET || family == AF_INET6); + int i = policy_summary_split(summary, prt_min, prt_max); - /* XXX: ipv4 specific */ - uint64_t count = (U64_LITERAL(1) << (32-maskbits)); + + /* The length of a single address mask */ + int addrbits = (family == AF_INET) ? IPV4_BITS : IPV6_BITS; + tor_assert_nonfatal_once(addrbits >= maskbits); + + /* We divide IPv6 address counts by (1 << scale) to keep them in a uint64_t + */ + int scale = ((family == AF_INET) ? + REJECT_CUTOFF_SCALE_IPV4 : + REJECT_CUTOFF_SCALE_IPV6); + + tor_assert_nonfatal_once(addrbits >= scale); + if (maskbits > (addrbits - scale)) { + tor_assert_nonfatal_once(family == AF_INET6); + /* The address range is so small, we'd need billions of them to reach the + * rejection limit. So we ignore this range in the reject count. */ + return; + } + + uint64_t count = 0; + if (addrbits - scale - maskbits >= 64) { + tor_assert_nonfatal_once(family == AF_INET6); + /* The address range is so large, it's an automatic rejection for all ports + * in the range. */ + count = UINT64_MAX; + } else { + count = (U64_LITERAL(1) << (addrbits - scale - maskbits)); + } + tor_assert_nonfatal_once(count > 0); while (i < smartlist_len(summary) && AT(i)->prt_max <= prt_max) { - AT(i)->reject_count += count; + if (AT(i)->reject_count <= UINT64_MAX - count) { + AT(i)->reject_count += count; + } else { + /* IPv4 would require a 4-billion address redundant policy to get here, + * but IPv6 just needs to have ::/0 */ + if (family == AF_INET) { + tor_assert_nonfatal_unreached_once(); + } + /* If we do get here, use saturating arithmetic */ + AT(i)->reject_count = UINT64_MAX; + } i++; } tor_assert(i < smartlist_len(summary) || prt_max==65535); @@ -2434,7 +2500,7 @@ policy_summary_add_item(smartlist_t *summary, addr_policy_t *p) { if (p->policy_type == ADDR_POLICY_ACCEPT) { if (p->maskbits == 0) { - policy_summary_accept(summary, p->prt_min, p->prt_max); + policy_summary_accept(summary, p->prt_min, p->prt_max, p->addr.family); } } else if (p->policy_type == ADDR_POLICY_REJECT) { @@ -2455,7 +2521,8 @@ policy_summary_add_item(smartlist_t *summary, addr_policy_t *p) } if (!is_private) { - policy_summary_reject(summary, p->maskbits, p->prt_min, p->prt_max); + policy_summary_reject(summary, p->maskbits, p->prt_min, p->prt_max, + p->addr.family); } } else tor_assert(0); @@ -2489,7 +2556,6 @@ policy_summarize(smartlist_t *policy, sa_family_t family) } if (f != family) continue; - /* XXXX-ipv6 More family work is needed */ policy_summary_add_item(summary, p); } SMARTLIST_FOREACH_END(p); @@ -2678,8 +2744,7 @@ parse_short_policy(const char *summary) return result; } -/** Write <b>policy</b> back out into a string. Used only for unit tests - * currently. */ +/** Write <b>policy</b> back out into a string. */ char * write_short_policy(const short_policy_t *policy) { diff --git a/src/or/policies.h b/src/or/policies.h index 20f58f2beb..850fa863d6 100644 --- a/src/or/policies.h +++ b/src/or/policies.h @@ -22,6 +22,9 @@ #define EXIT_POLICY_REJECT_PRIVATE (1 << 1) #define EXIT_POLICY_ADD_DEFAULT (1 << 2) #define EXIT_POLICY_REJECT_LOCAL_INTERFACES (1 << 3) +#define EXIT_POLICY_OPTION_MAX EXIT_POLICY_REJECT_LOCAL_INTERFACES +/* All options set: used for unit testing */ +#define EXIT_POLICY_OPTION_ALL ((EXIT_POLICY_OPTION_MAX << 1) - 1) typedef enum firewall_connection_t { FIREWALL_OR_CONNECTION = 0, diff --git a/src/test/fuzz/fuzz_vrs.c b/src/test/fuzz/fuzz_vrs.c index d2c0369f27..9301a9bcc8 100644 --- a/src/test/fuzz/fuzz_vrs.c +++ b/src/test/fuzz/fuzz_vrs.c @@ -38,6 +38,8 @@ fuzz_init(void) int fuzz_cleanup(void) { + SMARTLIST_FOREACH(dummy_vote->known_flags, char *, cp, tor_free(cp)); + smartlist_free(dummy_vote->known_flags); tor_free(dummy_vote); return 0; } diff --git a/src/test/test_policy.c b/src/test/test_policy.c index 71a31118a1..c7a5fb199d 100644 --- a/src/test/test_policy.c +++ b/src/test/test_policy.c @@ -32,12 +32,14 @@ test_short_policy_parse(const char *input, short_policy_free(short_policy); } -/** Helper: Parse the exit policy string in <b>policy_str</b>, and make sure - * that policies_summarize() produces the string <b>expected_summary</b> from - * it. */ +/** Helper: Parse the exit policy string in <b>policy_str</b> with + * <b>options</b>, and make sure that policies_summarize() produces the string + * <b>expected_summary</b> from it when called with family. */ static void -test_policy_summary_helper(const char *policy_str, - const char *expected_summary) +test_policy_summary_helper_family_flags(const char *policy_str, + const char *expected_summary, + sa_family_t family, + exit_policy_parser_cfg_t options) { config_line_t line; smartlist_t *policy = smartlist_new(); @@ -45,17 +47,17 @@ test_policy_summary_helper(const char *policy_str, char *summary_after = NULL; int r; short_policy_t *short_policy = NULL; + int success = 0; line.key = (char*)"foo"; line.value = (char *)policy_str; line.next = NULL; r = policies_parse_exit_policy(&line, &policy, - EXIT_POLICY_IPV6_ENABLED | - EXIT_POLICY_ADD_DEFAULT, NULL); + options, NULL); tt_int_op(r,OP_EQ, 0); - summary = policy_summarize(policy, AF_INET); + summary = policy_summarize(policy, family); tt_assert(summary != NULL); tt_str_op(summary,OP_EQ, expected_summary); @@ -65,7 +67,12 @@ test_policy_summary_helper(const char *policy_str, summary_after = write_short_policy(short_policy); tt_str_op(summary,OP_EQ, summary_after); + success = 1; done: + /* If we don't print the flags on failure, it's very hard to diagnose bugs */ + if (!success) + TT_DECLARE("CTXT", ("\n IPv%d\n Options: %x\n Policy: %s", + family == AF_INET ? 4 : 6, options, policy_str)); tor_free(summary_after); tor_free(summary); if (policy) @@ -73,6 +80,50 @@ test_policy_summary_helper(const char *policy_str, short_policy_free(short_policy); } +/** Like test_policy_summary_helper_family_flags, but tries all the different + * flag combinations */ +static void +test_policy_summary_helper_family(const char *policy_str, + const char *expected_summary, + sa_family_t family) +{ + for (exit_policy_parser_cfg_t opt = 0; + opt <= EXIT_POLICY_OPTION_ALL; + opt++) { + if (family == AF_INET6 && !(opt & EXIT_POLICY_IPV6_ENABLED)) + /* Skip the test: IPv6 addresses need IPv6 enabled */ + continue; + + if (opt & EXIT_POLICY_REJECT_LOCAL_INTERFACES) + /* Skip the test: local interfaces are machine-specific */ + continue; + + test_policy_summary_helper_family_flags(policy_str, expected_summary, + family, opt); + } +} + +/** Like test_policy_summary_helper_family, but uses expected_summary for + * both IPv4 and IPv6. */ +static void +test_policy_summary_helper(const char *policy_str, + const char *expected_summary) +{ + test_policy_summary_helper_family(policy_str, expected_summary, AF_INET); + test_policy_summary_helper_family(policy_str, expected_summary, AF_INET6); +} + +/** Like test_policy_summary_helper_family, but uses expected_summary4 for + * IPv4 and expected_summary6 for IPv6. */ +static void +test_policy_summary_helper6(const char *policy_str, + const char *expected_summary4, + const char *expected_summary6) +{ + test_policy_summary_helper_family(policy_str, expected_summary4, AF_INET); + test_policy_summary_helper_family(policy_str, expected_summary6, AF_INET6); +} + /** Run unit tests for generating summary lines of exit policies */ static void test_policies_general(void *arg) @@ -394,13 +445,14 @@ test_policies_general(void *arg) "reject 14.0.0.0/9:80," "reject 15.0.0.0:81," "accept *:*", "accept 1-65535"); - test_policy_summary_helper("reject 11.0.0.0/9:80," - "reject 12.0.0.0/9:80," - "reject 13.0.0.0/9:80," - "reject 14.0.0.0/9:80," - "reject 15.0.0.0:80," - "accept *:*", - "reject 80"); + test_policy_summary_helper6("reject 11.0.0.0/9:80," + "reject 12.0.0.0/9:80," + "reject 13.0.0.0/9:80," + "reject 14.0.0.0/9:80," + "reject 15.0.0.0:80," + "accept *:*", + "reject 80", + "accept 1-65535"); /* no exits */ test_policy_summary_helper("accept 11.0.0.0/9:80," "reject *:*", @@ -431,6 +483,458 @@ test_policies_general(void *arg) "reject *:7," "accept *:*", "reject 1,3,5,7"); + /* long policies */ + /* standard long policy on many exits */ + test_policy_summary_helper("accept *:20-23," + "accept *:43," + "accept *:53," + "accept *:79-81," + "accept *:88," + "accept *:110," + "accept *:143," + "accept *:194," + "accept *:220," + "accept *:389," + "accept *:443," + "accept *:464," + "accept *:531," + "accept *:543-544," + "accept *:554," + "accept *:563," + "accept *:636," + "accept *:706," + "accept *:749," + "accept *:873," + "accept *:902-904," + "accept *:981," + "accept *:989-995," + "accept *:1194," + "accept *:1220," + "accept *:1293," + "accept *:1500," + "accept *:1533," + "accept *:1677," + "accept *:1723," + "accept *:1755," + "accept *:1863," + "accept *:2082," + "accept *:2083," + "accept *:2086-2087," + "accept *:2095-2096," + "accept *:2102-2104," + "accept *:3128," + "accept *:3389," + "accept *:3690," + "accept *:4321," + "accept *:4643," + "accept *:5050," + "accept *:5190," + "accept *:5222-5223," + "accept *:5228," + "accept *:5900," + "accept *:6660-6669," + "accept *:6679," + "accept *:6697," + "accept *:8000," + "accept *:8008," + "accept *:8074," + "accept *:8080," + "accept *:8087-8088," + "accept *:8332-8333," + "accept *:8443," + "accept *:8888," + "accept *:9418," + "accept *:9999," + "accept *:10000," + "accept *:11371," + "accept *:12350," + "accept *:19294," + "accept *:19638," + "accept *:23456," + "accept *:33033," + "accept *:64738," + "reject *:*", + "accept 20-23,43,53,79-81,88,110,143,194,220,389," + "443,464,531,543-544,554,563,636,706,749,873," + "902-904,981,989-995,1194,1220,1293,1500,1533," + "1677,1723,1755,1863,2082-2083,2086-2087," + "2095-2096,2102-2104,3128,3389,3690,4321,4643," + "5050,5190,5222-5223,5228,5900,6660-6669,6679," + "6697,8000,8008,8074,8080,8087-8088,8332-8333," + "8443,8888,9418,9999-10000,11371,12350,19294," + "19638,23456,33033,64738"); + /* short policy with configured addresses */ + test_policy_summary_helper("reject 149.56.1.1:*," + "reject [2607:5300:1:1::1:0]:*," + "accept *:80," + "accept *:443," + "reject *:*", + "accept 80,443"); + /* short policy with configured and local interface addresses */ + test_policy_summary_helper("reject 149.56.1.0:*," + "reject 149.56.1.1:*," + "reject 149.56.1.2:*," + "reject 149.56.1.3:*," + "reject 149.56.1.4:*," + "reject 149.56.1.5:*," + "reject 149.56.1.6:*," + "reject 149.56.1.7:*," + "reject [2607:5300:1:1::1:0]:*," + "reject [2607:5300:1:1::1:1]:*," + "reject [2607:5300:1:1::1:2]:*," + "reject [2607:5300:1:1::1:3]:*," + "reject [2607:5300:1:1::2:0]:*," + "reject [2607:5300:1:1::2:1]:*," + "reject [2607:5300:1:1::2:2]:*," + "reject [2607:5300:1:1::2:3]:*," + "accept *:80," + "accept *:443," + "reject *:*", + "accept 80,443"); + /* short policy with configured netblocks */ + test_policy_summary_helper("reject 149.56.0.0/16," + "reject6 2607:5300::/32," + "reject6 2608:5300::/64," + "reject6 2609:5300::/96," + "accept *:80," + "accept *:443," + "reject *:*", + "accept 80,443"); + /* short policy with large netblocks that do not count as a rejection */ + test_policy_summary_helper("reject 148.0.0.0/7," + "reject6 2600::/16," + "accept *:80," + "accept *:443," + "reject *:*", + "accept 80,443"); + /* short policy with large netblocks that count as a rejection */ + test_policy_summary_helper("reject 148.0.0.0/6," + "reject6 2600::/15," + "accept *:80," + "accept *:443," + "reject *:*", + "reject 1-65535"); + /* short policy with huge netblocks that count as a rejection */ + test_policy_summary_helper("reject 128.0.0.0/1," + "reject6 8000::/1," + "accept *:80," + "accept *:443," + "reject *:*", + "reject 1-65535"); + /* short policy which blocks everything using netblocks */ + test_policy_summary_helper("reject 0.0.0.0/0," + "reject6 ::/0," + "accept *:80," + "accept *:443," + "reject *:*", + "reject 1-65535"); + /* short policy which has repeated redundant netblocks */ + test_policy_summary_helper("reject 0.0.0.0/0," + "reject 0.0.0.0/0," + "reject 0.0.0.0/0," + "reject 0.0.0.0/0," + "reject 0.0.0.0/0," + "reject6 ::/0," + "reject6 ::/0," + "reject6 ::/0," + "reject6 ::/0," + "reject6 ::/0," + "accept *:80," + "accept *:443," + "reject *:*", + "reject 1-65535"); + + /* longest possible policy + * (1-2,4-5,... is longer, but gets reduced to 3,6,... ) + * Going all the way to 65535 is incredibly slow, so we just go slightly + * more than the expected length */ + test_policy_summary_helper("accept *:1," + "accept *:3," + "accept *:5," + "accept *:7," + "accept *:9," + "accept *:11," + "accept *:13," + "accept *:15," + "accept *:17," + "accept *:19," + "accept *:21," + "accept *:23," + "accept *:25," + "accept *:27," + "accept *:29," + "accept *:31," + "accept *:33," + "accept *:35," + "accept *:37," + "accept *:39," + "accept *:41," + "accept *:43," + "accept *:45," + "accept *:47," + "accept *:49," + "accept *:51," + "accept *:53," + "accept *:55," + "accept *:57," + "accept *:59," + "accept *:61," + "accept *:63," + "accept *:65," + "accept *:67," + "accept *:69," + "accept *:71," + "accept *:73," + "accept *:75," + "accept *:77," + "accept *:79," + "accept *:81," + "accept *:83," + "accept *:85," + "accept *:87," + "accept *:89," + "accept *:91," + "accept *:93," + "accept *:95," + "accept *:97," + "accept *:99," + "accept *:101," + "accept *:103," + "accept *:105," + "accept *:107," + "accept *:109," + "accept *:111," + "accept *:113," + "accept *:115," + "accept *:117," + "accept *:119," + "accept *:121," + "accept *:123," + "accept *:125," + "accept *:127," + "accept *:129," + "accept *:131," + "accept *:133," + "accept *:135," + "accept *:137," + "accept *:139," + "accept *:141," + "accept *:143," + "accept *:145," + "accept *:147," + "accept *:149," + "accept *:151," + "accept *:153," + "accept *:155," + "accept *:157," + "accept *:159," + "accept *:161," + "accept *:163," + "accept *:165," + "accept *:167," + "accept *:169," + "accept *:171," + "accept *:173," + "accept *:175," + "accept *:177," + "accept *:179," + "accept *:181," + "accept *:183," + "accept *:185," + "accept *:187," + "accept *:189," + "accept *:191," + "accept *:193," + "accept *:195," + "accept *:197," + "accept *:199," + "accept *:201," + "accept *:203," + "accept *:205," + "accept *:207," + "accept *:209," + "accept *:211," + "accept *:213," + "accept *:215," + "accept *:217," + "accept *:219," + "accept *:221," + "accept *:223," + "accept *:225," + "accept *:227," + "accept *:229," + "accept *:231," + "accept *:233," + "accept *:235," + "accept *:237," + "accept *:239," + "accept *:241," + "accept *:243," + "accept *:245," + "accept *:247," + "accept *:249," + "accept *:251," + "accept *:253," + "accept *:255," + "accept *:257," + "accept *:259," + "accept *:261," + "accept *:263," + "accept *:265," + "accept *:267," + "accept *:269," + "accept *:271," + "accept *:273," + "accept *:275," + "accept *:277," + "accept *:279," + "accept *:281," + "accept *:283," + "accept *:285," + "accept *:287," + "accept *:289," + "accept *:291," + "accept *:293," + "accept *:295," + "accept *:297," + "accept *:299," + "accept *:301," + "accept *:303," + "accept *:305," + "accept *:307," + "accept *:309," + "accept *:311," + "accept *:313," + "accept *:315," + "accept *:317," + "accept *:319," + "accept *:321," + "accept *:323," + "accept *:325," + "accept *:327," + "accept *:329," + "accept *:331," + "accept *:333," + "accept *:335," + "accept *:337," + "accept *:339," + "accept *:341," + "accept *:343," + "accept *:345," + "accept *:347," + "accept *:349," + "accept *:351," + "accept *:353," + "accept *:355," + "accept *:357," + "accept *:359," + "accept *:361," + "accept *:363," + "accept *:365," + "accept *:367," + "accept *:369," + "accept *:371," + "accept *:373," + "accept *:375," + "accept *:377," + "accept *:379," + "accept *:381," + "accept *:383," + "accept *:385," + "accept *:387," + "accept *:389," + "accept *:391," + "accept *:393," + "accept *:395," + "accept *:397," + "accept *:399," + "accept *:401," + "accept *:403," + "accept *:405," + "accept *:407," + "accept *:409," + "accept *:411," + "accept *:413," + "accept *:415," + "accept *:417," + "accept *:419," + "accept *:421," + "accept *:423," + "accept *:425," + "accept *:427," + "accept *:429," + "accept *:431," + "accept *:433," + "accept *:435," + "accept *:437," + "accept *:439," + "accept *:441," + "accept *:443," + "accept *:445," + "accept *:447," + "accept *:449," + "accept *:451," + "accept *:453," + "accept *:455," + "accept *:457," + "accept *:459," + "accept *:461," + "accept *:463," + "accept *:465," + "accept *:467," + "accept *:469," + "accept *:471," + "accept *:473," + "accept *:475," + "accept *:477," + "accept *:479," + "accept *:481," + "accept *:483," + "accept *:485," + "accept *:487," + "accept *:489," + "accept *:491," + "accept *:493," + "accept *:495," + "accept *:497," + "accept *:499," + "accept *:501," + "accept *:503," + "accept *:505," + "accept *:507," + "accept *:509," + "accept *:511," + "accept *:513," + "accept *:515," + "accept *:517," + "accept *:519," + "accept *:521," + "accept *:523," + "accept *:525," + "accept *:527," + "accept *:529," + "reject *:*", + "accept 1,3,5,7,9,11,13,15,17,19,21,23,25,27,29," + "31,33,35,37,39,41,43,45,47,49,51,53,55,57,59,61," + "63,65,67,69,71,73,75,77,79,81,83,85,87,89,91,93," + "95,97,99,101,103,105,107,109,111,113,115,117," + "119,121,123,125,127,129,131,133,135,137,139,141," + "143,145,147,149,151,153,155,157,159,161,163,165," + "167,169,171,173,175,177,179,181,183,185,187,189," + "191,193,195,197,199,201,203,205,207,209,211,213," + "215,217,219,221,223,225,227,229,231,233,235,237," + "239,241,243,245,247,249,251,253,255,257,259,261," + "263,265,267,269,271,273,275,277,279,281,283,285," + "287,289,291,293,295,297,299,301,303,305,307,309," + "311,313,315,317,319,321,323,325,327,329,331,333," + "335,337,339,341,343,345,347,349,351,353,355,357," + "359,361,363,365,367,369,371,373,375,377,379,381," + "383,385,387,389,391,393,395,397,399,401,403,405," + "407,409,411,413,415,417,419,421,423,425,427,429," + "431,433,435,437,439,441,443,445,447,449,451,453," + "455,457,459,461,463,465,467,469,471,473,475,477," + "479,481,483,485,487,489,491,493,495,497,499,501," + "503,505,507,509,511,513,515,517,519,521,523"); /* Short policies with unrecognized formats should get accepted. */ test_short_policy_parse("accept fred,2,3-5", "accept 2,3-5"); diff --git a/src/test/test_tortls.c b/src/test/test_tortls.c index e2fee813bf..4bfcea211d 100644 --- a/src/test/test_tortls.c +++ b/src/test/test_tortls.c @@ -38,9 +38,11 @@ ENABLE_GCC_WARNING(redundant-decls) #include "log_test_helpers.h" #define NS_MODULE tortls -#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) \ - && !defined(LIBRESSL_VERSION_NUMBER) +#ifndef HAVE_SSL_STATE #define OPENSSL_OPAQUE +#endif + +#if defined(OPENSSL_OPAQUE) && !defined(LIBRESSL_VERSION_NUMBER) #define SSL_STATE_STR "before SSL initialization" #else #define SSL_STATE_STR "before/accept initialization" @@ -723,6 +725,26 @@ test_tortls_get_my_certs(void *ignored) (void)1; } +#ifndef HAVE_SSL_GET_CLIENT_CIPHERS +static SSL_CIPHER * +get_cipher_by_name(const char *name) +{ + int i; + const SSL_METHOD *method = SSLv23_method(); + int num = method->num_ciphers(); + + for (i = 0; i < num; ++i) { + const SSL_CIPHER *cipher = method->get_cipher(i); + const char *ciphername = SSL_CIPHER_get_name(cipher); + if (!strcmp(ciphername, name)) { + return (SSL_CIPHER *)cipher; + } + } + + return NULL; +} +#endif + #ifndef OPENSSL_OPAQUE static void test_tortls_get_ciphersuite_name(void *ignored) @@ -742,23 +764,6 @@ test_tortls_get_ciphersuite_name(void *ignored) } static SSL_CIPHER * -get_cipher_by_name(const char *name) -{ - int i; - const SSL_METHOD *method = SSLv23_method(); - int num = method->num_ciphers(); - for (i = 0; i < num; ++i) { - const SSL_CIPHER *cipher = method->get_cipher(i); - const char *ciphername = SSL_CIPHER_get_name(cipher); - if (!strcmp(ciphername, name)) { - return (SSL_CIPHER *)cipher; - } - } - - return NULL; -} - -static SSL_CIPHER * get_cipher_by_id(uint16_t id) { int i; |