diff options
author | Mike Perry <mikeperry-git@torproject.org> | 2023-02-03 02:11:10 +0000 |
---|---|---|
committer | Mike Perry <mikeperry-git@torproject.org> | 2023-04-06 15:57:11 +0000 |
commit | 46e473f43ee6aa920a779d37f7d2a28da64df383 (patch) | |
tree | 54521dbc2f71056b3990d0ab9f5632d5c4b2f980 /src/core | |
parent | 336a24754d117b46793ce6824e35ff6b7962bf9d (diff) | |
download | tor-46e473f43ee6aa920a779d37f7d2a28da64df383.tar.gz tor-46e473f43ee6aa920a779d37f7d2a28da64df383.zip |
Prop#329 Pool: Avoid sharing Guards and Middles between circuits.
Conflux must not use the same Guard for each leg; nor the same middle for each
leg.
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/or/circuitbuild.c | 24 | ||||
-rw-r--r-- | src/core/or/circuitbuild.h | 3 | ||||
-rw-r--r-- | src/core/or/conflux_pool.c | 123 | ||||
-rw-r--r-- | src/core/or/conflux_pool.h | 5 |
4 files changed, 146 insertions, 9 deletions
diff --git a/src/core/or/circuitbuild.c b/src/core/or/circuitbuild.c index 743d67acde..d6e022e7fa 100644 --- a/src/core/or/circuitbuild.c +++ b/src/core/or/circuitbuild.c @@ -45,6 +45,7 @@ #include "core/or/command.h" #include "core/or/connection_edge.h" #include "core/or/connection_or.h" +#include "core/or/conflux_pool.h" #include "core/or/extendinfo.h" #include "core/or/onion.h" #include "core/or/ocirc_event.h" @@ -89,7 +90,8 @@ static int circuit_send_first_onion_skin(origin_circuit_t *circ); static int circuit_build_no_more_hops(origin_circuit_t *circ); static int circuit_send_intermediate_onion_skin(origin_circuit_t *circ, crypt_path_t *hop); -static const node_t *choose_good_middle_server(uint8_t purpose, +static const node_t *choose_good_middle_server(const origin_circuit_t *, + uint8_t purpose, cpath_build_state_t *state, crypt_path_t *head, int cur_len); @@ -2313,7 +2315,8 @@ build_vanguard_middle_exclude_list(uint8_t purpose, * hop, based on already chosen nodes. */ static smartlist_t * -build_middle_exclude_list(uint8_t purpose, +build_middle_exclude_list(const origin_circuit_t *circ, + uint8_t purpose, cpath_build_state_t *state, crypt_path_t *head, int cur_len) @@ -2330,6 +2333,9 @@ build_middle_exclude_list(uint8_t purpose, excluded = smartlist_new(); + // Exclude other middles on pending and built conflux circs + conflux_add_middles_to_exclude_list(circ, excluded); + /* For non-vanguard circuits, add the exit and its family to the exclude list * (note that the exit/last hop is always chosen first in * circuit_establish_circuit()). */ @@ -2423,7 +2429,8 @@ pick_vanguard_middle_node(const or_options_t *options, * family, and make sure we don't duplicate any previous nodes or their * families. */ static const node_t * -choose_good_middle_server(uint8_t purpose, +choose_good_middle_server(const origin_circuit_t * circ, + uint8_t purpose, cpath_build_state_t *state, crypt_path_t *head, int cur_len) @@ -2438,7 +2445,7 @@ choose_good_middle_server(uint8_t purpose, log_debug(LD_CIRC, "Contemplating intermediate hop #%d: random choice.", cur_len+1); - excluded = build_middle_exclude_list(purpose, state, head, cur_len); + excluded = build_middle_exclude_list(circ, purpose, state, head, cur_len); flags |= cpath_build_state_to_crn_flags(state); flags |= cpath_build_state_to_crn_ipv6_extend_flag(state, cur_len); @@ -2483,7 +2490,8 @@ choose_good_middle_server(uint8_t purpose, * guard worked or not. */ const node_t * -choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state, +choose_good_entry_server(const origin_circuit_t *circ, + uint8_t purpose, cpath_build_state_t *state, circuit_guard_state_t **guard_state_out) { const node_t *choice; @@ -2505,7 +2513,7 @@ choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state, /* This request is for an entry server to use for a regular circuit, * and we use entry guard nodes. Just return one of the guard nodes. */ tor_assert(guard_state_out); - return guards_choose_guard(state, purpose, guard_state_out); + return guards_choose_guard(circ, state, purpose, guard_state_out); } excluded = smartlist_new(); @@ -2551,7 +2559,7 @@ onion_extend_cpath(origin_circuit_t *circ) if (cur_len == state->desired_path_len - 1) { /* Picking last node */ info = extend_info_dup(state->chosen_exit); } else if (cur_len == 0) { /* picking first node */ - const node_t *r = choose_good_entry_server(purpose, state, + const node_t *r = choose_good_entry_server(circ, purpose, state, &circ->guard_state); if (r) { /* If we're a client, use the preferred address rather than the @@ -2564,7 +2572,7 @@ onion_extend_cpath(origin_circuit_t *circ) } } else { const node_t *r = - choose_good_middle_server(purpose, state, circ->cpath, cur_len); + choose_good_middle_server(circ, purpose, state, circ->cpath, cur_len); if (r) { info = extend_info_from_node(r, 0, false); } diff --git a/src/core/or/circuitbuild.h b/src/core/or/circuitbuild.h index 4235ee96b2..c76259fc29 100644 --- a/src/core/or/circuitbuild.h +++ b/src/core/or/circuitbuild.h @@ -57,7 +57,8 @@ const char *build_state_get_exit_nickname(cpath_build_state_t *state); struct circuit_guard_state_t; -const node_t *choose_good_entry_server(uint8_t purpose, +const node_t *choose_good_entry_server(const origin_circuit_t *circ, + uint8_t purpose, cpath_build_state_t *state, struct circuit_guard_state_t **guard_state_out); void circuit_upgrade_circuits_from_guard_wait(void); diff --git a/src/core/or/conflux_pool.c b/src/core/or/conflux_pool.c index 66a405d4c1..c1b522fa67 100644 --- a/src/core/or/conflux_pool.c +++ b/src/core/or/conflux_pool.c @@ -31,6 +31,8 @@ #include "core/or/crypt_path_st.h" #include "core/or/or_circuit_st.h" #include "core/or/origin_circuit_st.h" +#include "core/or/extend_info_st.h" +#include "core/or/conflux_st.h" #include "feature/nodelist/nodelist.h" @@ -1092,6 +1094,127 @@ conflux_launch_leg(const uint8_t *nonce) return false; } +/** + * Add the identity digest of the guard nodes of all legs of the conflux + * circuit. + * + * This function checks both pending and linked conflux circuits. + */ +void +conflux_add_guards_to_exclude_list(const origin_circuit_t *orig_circ, + smartlist_t *excluded) +{ + tor_assert(orig_circ); + tor_assert(excluded); + + /* Ease our lives. */ + const circuit_t *circ = TO_CIRCUIT(orig_circ); + + /* Ignore if this is not conflux related. */ + if (!CIRCUIT_IS_CONFLUX(circ)) { + return; + } + + /* When building a circuit, we should not have a conflux object + * ourselves (though one may exist elsewhere). */ + tor_assert(!circ->conflux); + + /* Getting here without a nonce is a code flow issue. */ + if (BUG(!circ->conflux_pending_nonce)) { + return; + } + + /* A linked set exists, use it. */ + const conflux_t *cfx = linked_pool_get(circ->conflux_pending_nonce, true); + if (cfx) { + CONFLUX_FOR_EACH_LEG_BEGIN(cfx, leg) { + const origin_circuit_t *ocirc = CONST_TO_ORIGIN_CIRCUIT(leg->circ); + smartlist_add(excluded, + tor_memdup(ocirc->cpath->extend_info->identity_digest, + DIGEST_LEN)); + } CONFLUX_FOR_EACH_LEG_END(leg); + } + + /* An unlinked set might exist for this nonce, if so, add the second hop of + * the existing legs to the exclusion list. */ + unlinked_circuits_t *unlinked = + unlinked_pool_get(circ->conflux_pending_nonce, true); + if (unlinked) { + tor_assert(unlinked->is_client); + SMARTLIST_FOREACH_BEGIN(unlinked->legs, leg_t *, leg) { + /* Convert to origin circ and get cpath */ + const origin_circuit_t *ocirc = CONST_TO_ORIGIN_CIRCUIT(leg->circ); + smartlist_add(excluded, + tor_memdup(ocirc->cpath->extend_info->identity_digest, + DIGEST_LEN)); + } SMARTLIST_FOREACH_END(leg); + } +} + +/** + * Add the identity digest of the middle nodes of all legs of the conflux + * circuit. + * + * This function checks both pending and linked conflux circuits. + * + * XXX: The add guard and middle could be merged since it is the exact same + * code except for the cpath position and the identity digest vs node_t in + * the list. We could use an extra param indicating guard or middle. */ +void +conflux_add_middles_to_exclude_list(const origin_circuit_t *orig_circ, + smartlist_t *excluded) +{ + tor_assert(orig_circ); + tor_assert(excluded); + + /* Ease our lives. */ + const circuit_t *circ = TO_CIRCUIT(orig_circ); + + /* Ignore if this is not conflux related. */ + if (!CIRCUIT_IS_CONFLUX(circ)) { + return; + } + + /* When building a circuit, we should not have a conflux object + * ourselves (though one may exist elsewhere). */ + tor_assert(!circ->conflux); + + /* Getting here without a nonce is a code flow issue. */ + if (BUG(!circ->conflux_pending_nonce)) { + return; + } + + /* A linked set exists, use it. */ + const conflux_t *cfx = linked_pool_get(circ->conflux_pending_nonce, true); + if (cfx) { + CONFLUX_FOR_EACH_LEG_BEGIN(cfx, leg) { + const origin_circuit_t *ocirc = CONST_TO_ORIGIN_CIRCUIT(leg->circ); + node_t *node = node_get_mutable_by_id( + ocirc->cpath->next->extend_info->identity_digest); + if (node) { + smartlist_add(excluded, node); + } + } CONFLUX_FOR_EACH_LEG_END(leg); + } + + /* An unlinked set might exist for this nonce, if so, add the second hop of + * the existing legs to the exclusion list. */ + unlinked_circuits_t *unlinked = + unlinked_pool_get(circ->conflux_pending_nonce, true); + if (unlinked) { + tor_assert(unlinked->is_client); + SMARTLIST_FOREACH_BEGIN(unlinked->legs, leg_t *, leg) { + /* Convert to origin circ and get cpath */ + const origin_circuit_t *ocirc = CONST_TO_ORIGIN_CIRCUIT(leg->circ); + node_t *node = node_get_mutable_by_id( + ocirc->cpath->next->extend_info->identity_digest); + if (node) { + smartlist_add(excluded, node); + } + } SMARTLIST_FOREACH_END(leg); + } +} + /** The given circuit is conflux pending and has closed. This deletes the leg * from the set, attempt to finalize it and relaunch a new leg. If the set is * empty after removing this leg, it is deleted. */ diff --git a/src/core/or/conflux_pool.h b/src/core/or/conflux_pool.h index 4276049485..547b4d3974 100644 --- a/src/core/or/conflux_pool.h +++ b/src/core/or/conflux_pool.h @@ -21,6 +21,11 @@ void conflux_predict_new(time_t now); bool conflux_launch_leg(const uint8_t *nonce); +void conflux_add_guards_to_exclude_list(const origin_circuit_t *circ, + smartlist_t *excluded); +void conflux_add_middles_to_exclude_list(const origin_circuit_t *circ, + smartlist_t *excluded); + void conflux_circuit_has_closed(circuit_t *circ); void conflux_circuit_has_opened(origin_circuit_t *orig_circ); void conflux_circuit_about_to_free(circuit_t *circ); |