summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorMike Perry <mikeperry-git@torproject.org>2023-02-03 02:11:10 +0000
committerMike Perry <mikeperry-git@torproject.org>2023-04-06 15:57:11 +0000
commit46e473f43ee6aa920a779d37f7d2a28da64df383 (patch)
tree54521dbc2f71056b3990d0ab9f5632d5c4b2f980 /src/core
parent336a24754d117b46793ce6824e35ff6b7962bf9d (diff)
downloadtor-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.c24
-rw-r--r--src/core/or/circuitbuild.h3
-rw-r--r--src/core/or/conflux_pool.c123
-rw-r--r--src/core/or/conflux_pool.h5
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);