diff options
author | Nick Mathewson <nickm@torproject.org> | 2020-06-09 15:44:58 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2020-06-09 15:44:58 -0400 |
commit | 354f085e5f14c2bb4918b015e36cdc72748e0ea6 (patch) | |
tree | 0467dc89507ca7e7cc6a5f109332d693ed6a139a /src/core/or | |
parent | eaae5625cb1c5fdd26c766157742725aa4b7ad9e (diff) | |
parent | 1df451aba116f77a5a24e4e54cf343ec46d55f9a (diff) | |
download | tor-354f085e5f14c2bb4918b015e36cdc72748e0ea6.tar.gz tor-354f085e5f14c2bb4918b015e36cdc72748e0ea6.zip |
Merge remote-tracking branch 'tor-github/pr/1888/head'
Diffstat (limited to 'src/core/or')
-rw-r--r-- | src/core/or/circuitbuild.c | 190 | ||||
-rw-r--r-- | src/core/or/circuitbuild.h | 4 | ||||
-rw-r--r-- | src/core/or/circuitlist.c | 2 | ||||
-rw-r--r-- | src/core/or/circuituse.c | 22 | ||||
-rw-r--r-- | src/core/or/circuituse.h | 16 | ||||
-rw-r--r-- | src/core/or/cpath_build_state_st.h | 2 | ||||
-rw-r--r-- | src/core/or/or.h | 21 | ||||
-rw-r--r-- | src/core/or/protover.c | 11 | ||||
-rw-r--r-- | src/core/or/protover.h | 24 | ||||
-rw-r--r-- | src/core/or/versions.c | 55 |
10 files changed, 239 insertions, 108 deletions
diff --git a/src/core/or/circuitbuild.c b/src/core/or/circuitbuild.c index 83ce9f882b..be8ec6f3cb 100644 --- a/src/core/or/circuitbuild.c +++ b/src/core/or/circuitbuild.c @@ -439,7 +439,8 @@ onion_populate_cpath(origin_circuit_t *circ) /** Create and return a new origin circuit. Initialize its purpose and * build-state based on our arguments. The <b>flags</b> argument is a - * bitfield of CIRCLAUNCH_* flags. */ + * bitfield of CIRCLAUNCH_* flags, see circuit_launch_by_extend_info() for + * more details. */ origin_circuit_t * origin_circuit_init(uint8_t purpose, int flags) { @@ -455,13 +456,16 @@ origin_circuit_init(uint8_t purpose, int flags) ((flags & CIRCLAUNCH_NEED_CAPACITY) ? 1 : 0); circ->build_state->is_internal = ((flags & CIRCLAUNCH_IS_INTERNAL) ? 1 : 0); + circ->build_state->is_ipv6_selftest = + ((flags & CIRCLAUNCH_IS_IPV6_SELFTEST) ? 1 : 0); circ->base_.purpose = purpose; return circ; } -/** Build a new circuit for <b>purpose</b>. If <b>exit</b> - * is defined, then use that as your exit router, else choose a suitable - * exit node. +/** Build a new circuit for <b>purpose</b>. If <b>exit</b> is defined, then use + * that as your exit router, else choose a suitable exit node. The <b>flags</b> + * argument is a bitfield of CIRCLAUNCH_* flags, see + * circuit_launch_by_extend_info() for more details. * * Also launch a connection to the first OR in the chosen path, if * it's not open already. @@ -1050,7 +1054,8 @@ circuit_build_no_more_hops(origin_circuit_t *circ) control_event_bootstrap(BOOTSTRAP_STATUS_DONE, 0); control_event_client_status(LOG_NOTICE, "CIRCUIT_ESTABLISHED"); clear_broken_connection_map(1); - if (server_mode(options) && !check_whether_orport_reachable(options)) { + if (server_mode(options) && + !router_should_skip_orport_reachability_check(options)) { inform_testing_reachability(); router_do_reachability_checks(1, 1); } @@ -1074,14 +1079,25 @@ circuit_send_intermediate_onion_skin(origin_circuit_t *circ, crypt_path_t *hop) { int len; + int family = tor_addr_family(&hop->extend_info->addr); extend_cell_t ec; memset(&ec, 0, sizeof(ec)); log_debug(LD_CIRC,"starting to send subsequent skin."); - if (tor_addr_family(&hop->extend_info->addr) != AF_INET) { - log_warn(LD_BUG, "Trying to extend to a non-IPv4 address."); - return - END_CIRC_REASON_INTERNAL; + /* Relays and bridges can send IPv6 extends. But for clients, it's an + * obvious version distinguisher. */ + if (server_mode(get_options())) { + if (family != AF_INET && family != AF_INET6) { + log_warn(LD_BUG, "Server trying to extend to an invalid address " + "family."); + return - END_CIRC_REASON_INTERNAL; + } + } else { + if (family != AF_INET) { + log_warn(LD_BUG, "Client trying to extend to a non-IPv4 address."); + return - END_CIRC_REASON_INTERNAL; + } } circuit_pick_extend_handshake(&ec.cell_type, @@ -1089,9 +1105,17 @@ circuit_send_intermediate_onion_skin(origin_circuit_t *circ, &ec.create_cell.handshake_type, hop->extend_info); - tor_addr_copy(&ec.orport_ipv4.addr, &hop->extend_info->addr); - ec.orport_ipv4.port = hop->extend_info->port; - tor_addr_make_unspec(&ec.orport_ipv6.addr); + /* At the moment, extend_info only has one ORPort address. We'll add a + * second address in #34069, to support dual-stack extend cells. */ + if (family == AF_INET) { + tor_addr_copy(&ec.orport_ipv4.addr, &hop->extend_info->addr); + ec.orport_ipv4.port = hop->extend_info->port; + tor_addr_make_unspec(&ec.orport_ipv6.addr); + } else { + tor_addr_copy(&ec.orport_ipv6.addr, &hop->extend_info->addr); + ec.orport_ipv6.port = hop->extend_info->port; + tor_addr_make_unspec(&ec.orport_ipv4.addr); + } memcpy(ec.node_id, hop->extend_info->identity_digest, DIGEST_LEN); /* Set the ED25519 identity too -- it will only get included * in the extend2 cell if we're configured to use it, though. */ @@ -1539,7 +1563,23 @@ choose_good_exit_server_general(router_crn_flags_t flags) const node_t *selected_node=NULL; const int need_uptime = (flags & CRN_NEED_UPTIME) != 0; const int need_capacity = (flags & CRN_NEED_CAPACITY) != 0; - const int direct_conn = (flags & CRN_DIRECT_CONN) != 0; + + /* We should not require guard flags on exits. */ + IF_BUG_ONCE(flags & CRN_NEED_GUARD) + return NULL; + + /* We reject single-hop exits for all node positions. */ + IF_BUG_ONCE(flags & CRN_DIRECT_CONN) + return NULL; + + /* This isn't the function for picking rendezvous nodes. */ + IF_BUG_ONCE(flags & CRN_RENDEZVOUS_V3) + return NULL; + + /* We only want exits to extend if we cannibalize the circuit. + * But we don't require IPv6 extends yet. */ + IF_BUG_ONCE(flags & CRN_INITIATE_IPV6_EXTEND) + return NULL; connections = get_connection_array(); @@ -1572,19 +1612,14 @@ choose_good_exit_server_general(router_crn_flags_t flags) */ continue; } - if (!node_has_preferred_descriptor(node, direct_conn)) { + if (!router_can_choose_node(node, flags)) { n_supported[i] = -1; continue; } - if (!node->is_running || node->is_bad_exit) { + if (node->is_bad_exit) { n_supported[i] = -1; continue; /* skip routers that are known to be down or bad exits */ } - if (node_get_purpose(node) != ROUTER_PURPOSE_GENERAL) { - /* never pick a non-general node as a random exit. */ - n_supported[i] = -1; - continue; - } if (routerset_contains_node(options->ExcludeExitNodesUnion_, node)) { n_supported[i] = -1; continue; /* user asked us not to use it, no matter what */ @@ -1594,27 +1629,6 @@ choose_good_exit_server_general(router_crn_flags_t flags) n_supported[i] = -1; continue; /* not one of our chosen exit nodes */ } - - if (node_is_unreliable(node, need_uptime, need_capacity, 0)) { - n_supported[i] = -1; - continue; /* skip routers that are not suitable. Don't worry if - * this makes us reject all the possible routers: if so, - * we'll retry later in this function with need_update and - * need_capacity set to 0. */ - } - if (!(node->is_valid)) { - /* if it's invalid and we don't want it */ - n_supported[i] = -1; -// log_fn(LOG_DEBUG,"Skipping node %s (index %d) -- invalid router.", -// router->nickname, i); - continue; /* skip invalid routers */ - } - /* We do not allow relays that allow single hop exits by default. Option - * was deprecated in 0.2.9.2-alpha and removed in 0.3.1.0-alpha. */ - if (node_allows_single_hop_exits(node)) { - n_supported[i] = -1; - continue; - } if (node_exit_policy_rejects_all(node)) { n_supported[i] = -1; // log_fn(LOG_DEBUG,"Skipping node %s (index %d) -- it rejects all.", @@ -1771,13 +1785,7 @@ pick_restricted_middle_node(router_crn_flags_t flags, tor_assert(pick_from); /* Add all running nodes to all_live_nodes */ - router_add_running_nodes_to_smartlist(all_live_nodes, - (flags & CRN_NEED_UPTIME) != 0, - (flags & CRN_NEED_CAPACITY) != 0, - (flags & CRN_NEED_GUARD) != 0, - (flags & CRN_NEED_DESC) != 0, - (flags & CRN_PREF_ADDR) != 0, - (flags & CRN_DIRECT_CONN) != 0); + router_add_running_nodes_to_smartlist(all_live_nodes, flags); /* Filter all_live_nodes to only add live *and* whitelisted middles * to the list whitelisted_live_middles. */ @@ -1957,6 +1965,43 @@ warn_if_last_router_excluded(origin_circuit_t *circ, return; } +/* Return a set of generic CRN_* flags based on <b>state</b>. + * + * Called for every position in the circuit. */ +STATIC int +cpath_build_state_to_crn_flags(const cpath_build_state_t *state) +{ + router_crn_flags_t flags = 0; + /* These flags apply to entry, middle, and exit nodes. + * If a flag only applies to a specific position, it should be checked in + * that function. */ + if (state->need_uptime) + flags |= CRN_NEED_UPTIME; + if (state->need_capacity) + flags |= CRN_NEED_CAPACITY; + return flags; +} + +/* Return the CRN_INITIATE_IPV6_EXTEND flag, based on <b>state</b> and + * <b>cur_len</b>. + * + * Only called for middle nodes (for now). Must not be called on single-hop + * circuits. */ +STATIC int +cpath_build_state_to_crn_ipv6_extend_flag(const cpath_build_state_t *state, + int cur_len) +{ + IF_BUG_ONCE(state->desired_path_len < 2) + return 0; + + /* The last node is the relay doing the self-test. So we want to extend over + * IPv6 from the second-last node. */ + if (state->is_ipv6_selftest && cur_len == state->desired_path_len - 2) + return CRN_INITIATE_IPV6_EXTEND; + else + return 0; +} + /** Decide a suitable length for circ's cpath, and pick an exit * router (or use <b>exit</b> if provided). Store these in the * cpath. @@ -1990,14 +2035,13 @@ onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit_ei, exit_ei = extend_info_dup(exit_ei); } else { /* we have to decide one */ router_crn_flags_t flags = CRN_NEED_DESC; - if (state->need_uptime) - flags |= CRN_NEED_UPTIME; - if (state->need_capacity) - flags |= CRN_NEED_CAPACITY; - if (is_hs_v3_rp_circuit) - flags |= CRN_RENDEZVOUS_V3; + flags |= cpath_build_state_to_crn_flags(state); + /* Some internal exits are one hop, for example directory connections. + * (Guards are always direct, middles are never direct.) */ if (state->onehop_tunnel) flags |= CRN_DIRECT_CONN; + if (is_hs_v3_rp_circuit) + flags |= CRN_RENDEZVOUS_V3; const node_t *node = choose_good_exit_server(circ, flags, state->is_internal); if (!node) { @@ -2059,32 +2103,27 @@ circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *exit_ei) return 0; } -/** Return the number of routers in <b>routers</b> that are currently up - * and available for building circuits through. +/** Return the number of routers in <b>nodes</b> that are currently up and + * available for building circuits through. * - * (Note that this function may overcount or undercount, if we have - * descriptors that are not the type we would prefer to use for some - * particular router. See bug #25885.) + * If <b>direct</b> is true, only count nodes that are suitable for direct + * connections. Counts nodes regardless of whether their addresses are + * preferred. */ MOCK_IMPL(STATIC int, count_acceptable_nodes, (const smartlist_t *nodes, int direct)) { int num=0; + int flags = CRN_NEED_DESC; + + if (direct) + flags |= CRN_DIRECT_CONN; SMARTLIST_FOREACH_BEGIN(nodes, const node_t *, node) { // log_debug(LD_CIRC, -// "Contemplating whether router %d (%s) is a new option.", -// i, r->nickname); - if (! node->is_running) -// log_debug(LD_CIRC,"Nope, the directory says %d is not running.",i); - continue; - if (! node->is_valid) -// log_debug(LD_CIRC,"Nope, the directory says %d is not valid.",i); - continue; - if (! node_has_preferred_descriptor(node, direct)) - continue; - /* The node has a descriptor, so we can just check the ntor key directly */ - if (!node_has_curve25519_onion_key(node)) + // "Contemplating whether router %d (%s) is a new option.", + // i, r->nickname); + if (!router_can_choose_node(node, flags)) continue; ++num; } SMARTLIST_FOREACH_END(node); @@ -2278,10 +2317,8 @@ choose_good_middle_server(uint8_t purpose, excluded = build_middle_exclude_list(purpose, state, head, cur_len); - if (state->need_uptime) - flags |= CRN_NEED_UPTIME; - if (state->need_capacity) - flags |= CRN_NEED_CAPACITY; + flags |= cpath_build_state_to_crn_flags(state); + flags |= cpath_build_state_to_crn_ipv6_extend_flag(state, cur_len); /** If a hidden service circuit wants a specific middle node, pin it. */ if (middle_node_must_be_vanguard(options, purpose, cur_len)) { @@ -2357,10 +2394,7 @@ choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state, } if (state) { - if (state->need_uptime) - flags |= CRN_NEED_UPTIME; - if (state->need_capacity) - flags |= CRN_NEED_CAPACITY; + flags |= cpath_build_state_to_crn_flags(state); } choice = router_choose_random_node(excluded, options->ExcludeNodes, flags); diff --git a/src/core/or/circuitbuild.h b/src/core/or/circuitbuild.h index e62bb41de9..565be09975 100644 --- a/src/core/or/circuitbuild.h +++ b/src/core/or/circuitbuild.h @@ -97,6 +97,10 @@ STATIC int onion_extend_cpath(origin_circuit_t *circ); STATIC int onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit_ei, int is_hs_v3_rp_circuit); +STATIC int cpath_build_state_to_crn_flags(const cpath_build_state_t *state); +STATIC int cpath_build_state_to_crn_ipv6_extend_flag( + const cpath_build_state_t *state, + int cur_len); #endif /* defined(CIRCUITBUILD_PRIVATE) */ diff --git a/src/core/or/circuitlist.c b/src/core/or/circuitlist.c index 90cce47490..a69b7cbbe5 100644 --- a/src/core/or/circuitlist.c +++ b/src/core/or/circuitlist.c @@ -1944,7 +1944,7 @@ circuit_find_to_cannibalize(uint8_t purpose_to_produce, extend_info_t *info, /* Ignore any circuits for which we can't use the Guard. It is possible * that the Guard was removed from the sampled set after the circuit - * was created so avoid using it. */ + * was created, so avoid using it. */ if (!entry_guard_could_succeed(circ->guard_state)) { goto next; } diff --git a/src/core/or/circuituse.c b/src/core/or/circuituse.c index e2c4df25d0..7358817531 100644 --- a/src/core/or/circuituse.c +++ b/src/core/or/circuituse.c @@ -1642,7 +1642,7 @@ static void circuit_testing_opened(origin_circuit_t *circ) { if (have_performed_bandwidth_test || - !check_whether_orport_reachable(get_options())) { + !router_should_skip_orport_reachability_check(get_options())) { /* either we've already done everything we want with testing circuits, * or this testing circuit became open due to a fluke, e.g. we picked * a last hop where we already had the connection open due to an @@ -1660,7 +1660,8 @@ static void circuit_testing_failed(origin_circuit_t *circ, int at_last_hop) { const or_options_t *options = get_options(); - if (server_mode(options) && check_whether_orport_reachable(options)) + if (server_mode(options) && + router_should_skip_orport_reachability_check(options)) return; log_info(LD_GENERAL, @@ -2092,11 +2093,18 @@ circuit_should_cannibalize_to_build(uint8_t purpose_to_build, } /** Launch a new circuit with purpose <b>purpose</b> and exit node - * <b>extend_info</b> (or NULL to select a random exit node). If flags - * contains CIRCLAUNCH_NEED_UPTIME, choose among routers with high uptime. If - * CIRCLAUNCH_NEED_CAPACITY is set, choose among routers with high bandwidth. - * If CIRCLAUNCH_IS_INTERNAL is true, the last hop need not be an exit node. - * If CIRCLAUNCH_ONEHOP_TUNNEL is set, the circuit will have only one hop. + * <b>extend_info</b> (or NULL to select a random exit node). + * + * If flags contains: + * - CIRCLAUNCH_ONEHOP_TUNNEL: the circuit will have only one hop; + * - CIRCLAUNCH_NEED_UPTIME: choose routers with high uptime; + * - CIRCLAUNCH_NEED_CAPACITY: choose routers with high bandwidth; + * - CIRCLAUNCH_IS_IPV6_SELFTEST: the second-last hop must support IPv6 + * extends; + * - CIRCLAUNCH_IS_INTERNAL: the last hop need not be an exit node; + * - CIRCLAUNCH_IS_V3_RP: the last hop must support v3 onion service + * rendezvous. + * * Return the newly allocated circuit on success, or NULL on failure. */ origin_circuit_t * circuit_launch_by_extend_info(uint8_t purpose, diff --git a/src/core/or/circuituse.h b/src/core/or/circuituse.h index 95d36d6474..028fe4aa48 100644 --- a/src/core/or/circuituse.h +++ b/src/core/or/circuituse.h @@ -36,17 +36,23 @@ void circuit_try_attaching_streams(origin_circuit_t *circ); void circuit_build_failed(origin_circuit_t *circ); /** Flag to set when a circuit should have only a single hop. */ -#define CIRCLAUNCH_ONEHOP_TUNNEL (1<<0) +#define CIRCLAUNCH_ONEHOP_TUNNEL (1<<0) /** Flag to set when a circuit needs to be built of high-uptime nodes */ -#define CIRCLAUNCH_NEED_UPTIME (1<<1) +#define CIRCLAUNCH_NEED_UPTIME (1<<1) /** Flag to set when a circuit needs to be built of high-capacity nodes */ -#define CIRCLAUNCH_NEED_CAPACITY (1<<2) +#define CIRCLAUNCH_NEED_CAPACITY (1<<2) /** Flag to set when the last hop of a circuit doesn't need to be an * exit node. */ -#define CIRCLAUNCH_IS_INTERNAL (1<<3) +#define CIRCLAUNCH_IS_INTERNAL (1<<3) /** Flag to set when we are trying to launch a v3 rendezvous circuit. We need * to apply some additional filters on the node picked. */ -#define CIRCLAUNCH_IS_V3_RP (1<<4) +#define CIRCLAUNCH_IS_V3_RP (1<<4) +/** Flag to set when we are trying to launch a self-testing circuit to our + * IPv6 ORPort. We need to apply some additional filters on the second-last + * node in the circuit. (We are both the client and the last node in the + * circuit.) */ +#define CIRCLAUNCH_IS_IPV6_SELFTEST (1<<5) + origin_circuit_t *circuit_launch_by_extend_info(uint8_t purpose, extend_info_t *info, int flags); diff --git a/src/core/or/cpath_build_state_st.h b/src/core/or/cpath_build_state_st.h index ee9a0d972c..eb8e97edc5 100644 --- a/src/core/or/cpath_build_state_st.h +++ b/src/core/or/cpath_build_state_st.h @@ -24,6 +24,8 @@ struct cpath_build_state_t { unsigned int need_capacity : 1; /** Whether the last hop was picked with exiting in mind. */ unsigned int is_internal : 1; + /** Is this an IPv6 ORPort self-testing circuit? */ + unsigned int is_ipv6_selftest : 1; /** Did we pick this as a one-hop tunnel (not safe for other streams)? * These are for encrypted dir conns that exit to this router, not * for arbitrary exits from the circuit. */ diff --git a/src/core/or/or.h b/src/core/or/or.h index 5b35cbe7f1..7e02da6648 100644 --- a/src/core/or/or.h +++ b/src/core/or/or.h @@ -815,6 +815,18 @@ typedef struct protover_summary_flags_t { * accept EXTEND2 cells. This requires Relay=2. */ unsigned int supports_extend2_cells:1; + /** True iff this router has a version or protocol list that allows it to + * accept IPv6 connections. This requires Relay=2 or Relay=3. */ + unsigned int supports_accepting_ipv6_extends:1; + + /** True iff this router has a version or protocol list that allows it to + * initiate IPv6 connections. This requires Relay=3. */ + unsigned int supports_initiating_ipv6_extends:1; + + /** True iff this router has a version or protocol list that allows it to + * consider IPv6 connections canonical. This requires Relay=3. */ + unsigned int supports_canonical_ipv6_conns:1; + /** True iff this router has a protocol list that allows it to negotiate * ed25519 identity keys on a link handshake with us. This * requires LinkAuth=3. */ @@ -830,6 +842,10 @@ typedef struct protover_summary_flags_t { * the v3 protocol detailed in proposal 224. This requires HSIntro=4. */ unsigned int supports_ed25519_hs_intro : 1; + /** True iff this router has a protocol list that allows it to support the + * ESTABLISH_INTRO DoS cell extension. Requires HSIntro=5. */ + unsigned int supports_establish_intro_dos_extension : 1; + /** True iff this router has a protocol list that allows it to be an hidden * service directory supporting version 3 as seen in proposal 224. This * requires HSDir=2. */ @@ -841,12 +857,9 @@ typedef struct protover_summary_flags_t { unsigned int supports_v3_rendezvous_point: 1; /** True iff this router has a protocol list that allows clients to - * negotiate hs circuit setup padding. Requires Padding>=2. */ + * negotiate hs circuit setup padding. Requires Padding=2. */ unsigned int supports_hs_setup_padding : 1; - /** True iff this router has a protocol list that allows it to support the - * ESTABLISH_INTRO DoS cell extension. Requires HSIntro>=5. */ - unsigned int supports_establish_intro_dos_extension : 1; } protover_summary_flags_t; typedef struct routerinfo_t routerinfo_t; diff --git a/src/core/or/protover.c b/src/core/or/protover.c index c3f443631b..c6b0243693 100644 --- a/src/core/or/protover.c +++ b/src/core/or/protover.c @@ -326,6 +326,9 @@ protover_is_supported_here(protocol_type_t pr, uint32_t ver) /** * Return true iff "list" encodes a protocol list that includes support for * the indicated protocol and version. + * + * If the protocol list is unparseable, treat it as if it defines no + * protocols, and return 0. */ int protocol_list_supports_protocol(const char *list, protocol_type_t tp, @@ -348,6 +351,9 @@ protocol_list_supports_protocol(const char *list, protocol_type_t tp, /** * Return true iff "list" encodes a protocol list that includes support for * the indicated protocol and version, or some later version. + * + * If the protocol list is unparseable, treat it as if it defines no + * protocols, and return 0. */ int protocol_list_supports_protocol_or_later(const char *list, @@ -403,7 +409,7 @@ protover_get_supported_protocols(void) #endif "Microdesc=1-2 " "Padding=2 " - "Relay=1-2"; + "Relay=1-3"; } /** The protocols from protover_get_supported_protocols(), as parsed into a @@ -740,6 +746,9 @@ protover_compute_vote(const smartlist_t *list_of_proto_strings, * one that we support, and false otherwise. If <b>missing_out</b> is * provided, set it to the list of protocols we do not support. * + * If the protocol version string is unparseable, treat it as if it defines no + * protocols, and return 1. + * * NOTE: This is quadratic, but we don't do it much: only a few times per * consensus. Checking signatures should be way more expensive than this * ever would be. diff --git a/src/core/or/protover.h b/src/core/or/protover.h index 9509f3e8a3..2950147d1b 100644 --- a/src/core/or/protover.h +++ b/src/core/or/protover.h @@ -22,12 +22,32 @@ struct smartlist_t; /// `FIRST_TOR_VERSION_TO_ADVERTISE_PROTOCOLS` #define FIRST_TOR_VERSION_TO_ADVERTISE_PROTOCOLS "0.2.9.3-alpha" -/** The protover version number that signifies HSDir support for HSv3 */ -#define PROTOVER_HSDIR_V3 2 +/** The protover version number that signifies ed25519 link handshake support + */ +#define PROTOVER_LINKAUTH_ED25519_HANDSHAKE 3 + +/** The protover version number that signifies extend2 cell support */ +#define PROTOVER_RELAY_EXTEND2 2 +/** The protover version number where relays can accept IPv6 connections */ +#define PROTOVER_RELAY_ACCEPT_IPV6 2 +/** The protover version number where relays can initiate IPv6 extends */ +#define PROTOVER_RELAY_EXTEND_IPV6 3 +/** The protover version number where relays can consider IPv6 connections + * canonical */ +#define PROTOVER_RELAY_CANONICAL_IPV6 3 + /** The protover version number that signifies HSv3 intro point support */ #define PROTOVER_HS_INTRO_V3 4 +/** The protover version number where intro points support denial of service + * resistance */ +#define PROTOVER_HS_INTRO_DOS 5 + /** The protover version number that signifies HSv3 rendezvous point support */ #define PROTOVER_HS_RENDEZVOUS_POINT_V3 2 + +/** The protover version number that signifies HSDir support for HSv3 */ +#define PROTOVER_HSDIR_V3 2 + /** The protover that signals support for HS circuit setup padding machines */ #define PROTOVER_HS_SETUP_PADDING 2 diff --git a/src/core/or/versions.c b/src/core/or/versions.c index 31f1f5b997..2f8cbac0e9 100644 --- a/src/core/or/versions.c +++ b/src/core/or/versions.c @@ -408,6 +408,10 @@ static strmap_t *protover_summary_map = NULL; /** * Helper. Given a non-NULL protover string <b>protocols</b>, set <b>out</b> * to its summary, and memoize the result in <b>protover_summary_map</b>. + * + * If the protover string does not contain any recognised protocols, sets + * protocols_known, but does not set any other flags. (Empty strings are also + * treated this way.) */ static void memoize_protover_summary(protover_summary_flags_t *out, @@ -434,25 +438,49 @@ memoize_protover_summary(protover_summary_flags_t *out, memset(out, 0, sizeof(*out)); out->protocols_known = 1; - out->supports_extend2_cells = - protocol_list_supports_protocol(protocols, PRT_RELAY, 2); + out->supports_ed25519_link_handshake_compat = - protocol_list_supports_protocol(protocols, PRT_LINKAUTH, 3); + protocol_list_supports_protocol(protocols, PRT_LINKAUTH, + PROTOVER_LINKAUTH_ED25519_HANDSHAKE); out->supports_ed25519_link_handshake_any = - protocol_list_supports_protocol_or_later(protocols, PRT_LINKAUTH, 3); + protocol_list_supports_protocol_or_later( + protocols, + PRT_LINKAUTH, + PROTOVER_LINKAUTH_ED25519_HANDSHAKE); + + out->supports_extend2_cells = + protocol_list_supports_protocol(protocols, PRT_RELAY, + PROTOVER_RELAY_EXTEND2); + out->supports_accepting_ipv6_extends = ( + protocol_list_supports_protocol(protocols, PRT_RELAY, + PROTOVER_RELAY_ACCEPT_IPV6) || + protocol_list_supports_protocol(protocols, PRT_RELAY, + PROTOVER_RELAY_EXTEND_IPV6)); + out->supports_initiating_ipv6_extends = + protocol_list_supports_protocol(protocols, PRT_RELAY, + PROTOVER_RELAY_EXTEND_IPV6); + out->supports_canonical_ipv6_conns = + protocol_list_supports_protocol(protocols, PRT_RELAY, + PROTOVER_RELAY_CANONICAL_IPV6); + out->supports_ed25519_hs_intro = - protocol_list_supports_protocol(protocols, PRT_HSINTRO, 4); - out->supports_v3_hsdir = - protocol_list_supports_protocol(protocols, PRT_HSDIR, - PROTOVER_HSDIR_V3); + protocol_list_supports_protocol(protocols, PRT_HSINTRO, + PROTOVER_HS_INTRO_V3); + out->supports_establish_intro_dos_extension = + protocol_list_supports_protocol(protocols, PRT_HSINTRO, + PROTOVER_HS_INTRO_DOS); + out->supports_v3_rendezvous_point = protocol_list_supports_protocol(protocols, PRT_HSREND, PROTOVER_HS_RENDEZVOUS_POINT_V3); + + out->supports_v3_hsdir = + protocol_list_supports_protocol(protocols, PRT_HSDIR, + PROTOVER_HSDIR_V3); + out->supports_hs_setup_padding = protocol_list_supports_protocol(protocols, PRT_PADDING, PROTOVER_HS_SETUP_PADDING); - out->supports_establish_intro_dos_extension = - protocol_list_supports_protocol(protocols, PRT_HSINTRO, 5); protover_summary_flags_t *new_cached = tor_memdup(out, sizeof(*out)); cached = strmap_set(protover_summary_map, protocols, new_cached); @@ -461,6 +489,13 @@ memoize_protover_summary(protover_summary_flags_t *out, /** Summarize the protocols listed in <b>protocols</b> into <b>out</b>, * falling back or correcting them based on <b>version</b> as appropriate. + * + * If protocols and version are both NULL, returns a summary with no flags + * set. + * + * If the protover string does not contain any recognised protocols, and the + * version is not recognised, sets protocols_known, but does not set any other + * flags. (Empty strings are also treated this way.) */ void summarize_protover_flags(protover_summary_flags_t *out, |