aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2014-02-07 10:47:34 -0500
committerNick Mathewson <nickm@torproject.org>2014-02-07 10:47:34 -0500
commitbabbd3ff08496bfd3d99f05257279ff6135fb027 (patch)
tree5226404947be461b8339b9052811185dde166356
parent372adfa09a143490dfc058a6e2db78ca27ef9399 (diff)
parent1068e50aecefac8469991884afc08b6ecb24e740 (diff)
downloadtor-babbd3ff08496bfd3d99f05257279ff6135fb027.tar
tor-babbd3ff08496bfd3d99f05257279ff6135fb027.tar.gz
Merge remote-tracking branch 'public/feature9777_024_squashed'
Conflicts: src/or/circuitbuild.c
-rw-r--r--changes/feature97773
-rw-r--r--src/or/circuitbuild.c77
-rw-r--r--src/or/circuitlist.c10
-rw-r--r--src/or/circuitlist.h1
4 files changed, 81 insertions, 10 deletions
diff --git a/changes/feature9777 b/changes/feature9777
new file mode 100644
index 000000000..312b5e034
--- /dev/null
+++ b/changes/feature9777
@@ -0,0 +1,3 @@
+ o Minor features:
+ - Avoid using circuit paths if no node in the path supports the ntor
+ circuit extension handshake. Implements ticket 9777.
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 8e6bb59ef..ffcca4666 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -57,6 +57,9 @@ static crypt_path_t *onion_next_hop_in_cpath(crypt_path_t *cpath);
static int onion_extend_cpath(origin_circuit_t *circ);
static int count_acceptable_nodes(smartlist_t *routers);
static int onion_append_hop(crypt_path_t **head_ptr, extend_info_t *choice);
+#ifdef CURVE25519_ENABLED
+static int circuits_can_use_ntor(void);
+#endif
/** This function tries to get a channel to the specified endpoint,
* and then calls command_setup_channel() to give it the right
@@ -269,21 +272,74 @@ circuit_rep_hist_note_result(origin_circuit_t *circ)
} while (hop!=circ->cpath);
}
+#ifdef CURVE25519_ENABLED
+/** Return 1 iff at least one node in circ's cpath supports ntor. */
+static int
+circuit_cpath_supports_ntor(const origin_circuit_t *circ)
+{
+ crypt_path_t *head = circ->cpath, *cpath = circ->cpath;
+
+ cpath = head;
+ do {
+ if (cpath->extend_info &&
+ !tor_mem_is_zero(
+ (const char*)cpath->extend_info->curve25519_onion_key.public_key,
+ CURVE25519_PUBKEY_LEN))
+ return 1;
+
+ cpath = cpath->next;
+ } while (cpath != head);
+
+ return 0;
+}
+#else
+#define circuit_cpath_supports_ntor(circ) 0
+#endif
+
/** Pick all the entries in our cpath. Stop and return 0 when we're
* happy, or return -1 if an error occurs. */
static int
onion_populate_cpath(origin_circuit_t *circ)
{
- int r;
- again:
- r = onion_extend_cpath(circ);
- if (r < 0) {
- log_info(LD_CIRC,"Generating cpath hop failed.");
- return -1;
+ int n_tries = 0;
+#ifdef CURVE25519_ENABLED
+ const int using_ntor = circuits_can_use_ntor();
+#else
+ const int using_ntor = 0;
+#endif
+
+#define MAX_POPULATE_ATTEMPTS 32
+
+ while (1) {
+ int r = onion_extend_cpath(circ);
+ if (r < 0) {
+ log_info(LD_CIRC,"Generating cpath hop failed.");
+ return -1;
+ }
+ if (r == 1) {
+ /* This circuit doesn't need/shouldn't be forced to have an ntor hop */
+ if (circ->build_state->desired_path_len <= 1 || ! using_ntor)
+ return 0;
+
+ /* This circuit has an ntor hop. great! */
+ if (circuit_cpath_supports_ntor(circ))
+ return 0;
+
+ /* No node in the circuit supports ntor. Have we already tried too many
+ * times? */
+ if (++n_tries >= MAX_POPULATE_ATTEMPTS)
+ break;
+
+ /* Clear the path and retry */
+ circuit_clear_cpath(circ);
+ }
}
- if (r == 0)
- goto again;
- return 0; /* if r == 1 */
+ log_warn(LD_CIRC, "I tried for %d times, but I couldn't build a %d-hop "
+ "circuit with at least one node that supports ntor.",
+ MAX_POPULATE_ATTEMPTS,
+ circ->build_state->desired_path_len);
+
+ return -1;
}
/** Create and return a new origin circuit. Initialize its purpose and
@@ -1946,6 +2002,9 @@ onion_next_hop_in_cpath(crypt_path_t *cpath)
/** Choose a suitable next hop in the cpath <b>head_ptr</b>,
* based on <b>state</b>. Append the hop info to head_ptr.
+ *
+ * Return 1 if the path is complete, 0 if we successfully added a hop,
+ * and -1 on error.
*/
static int
onion_extend_cpath(origin_circuit_t *circ)
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index c31bc49d0..22224db54 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -796,7 +796,7 @@ circuit_free_cpath(crypt_path_t *cpath)
if (!cpath)
return;
- /* it's a doubly linked list, so we have to notice when we've
+ /* it's a circular list, so we have to notice when we've
* gone through it once. */
while (cpath->next && cpath->next != head) {
victim = cpath;
@@ -807,6 +807,14 @@ circuit_free_cpath(crypt_path_t *cpath)
circuit_free_cpath_node(cpath);
}
+/** Remove all the items in the cpath on <b>circ</b>.*/
+void
+circuit_clear_cpath(origin_circuit_t *circ)
+{
+ circuit_free_cpath(circ->cpath);
+ circ->cpath = NULL;
+}
+
/** Release all storage held by circuits. */
void
circuit_free_all(void)
diff --git a/src/or/circuitlist.h b/src/or/circuitlist.h
index bf3d1b467..1c8cf7de2 100644
--- a/src/or/circuitlist.h
+++ b/src/or/circuitlist.h
@@ -56,6 +56,7 @@ void circuit_mark_all_dirty_circs_as_unusable(void);
void circuit_mark_for_close_(circuit_t *circ, int reason,
int line, const char *file);
int circuit_get_cpath_len(origin_circuit_t *circ);
+void circuit_clear_cpath(origin_circuit_t *circ);
crypt_path_t *circuit_get_cpath_hop(origin_circuit_t *circ, int hopnum);
void circuit_get_all_pending_on_channel(smartlist_t *out,
channel_t *chan);