summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2012-12-06 01:53:29 -0500
committerNick Mathewson <nickm@torproject.org>2013-01-03 11:29:47 -0500
commitb2863739083125d332cf1166ae6b095df7d0f155 (patch)
tree44e6a25866048d143b1e739a46528823306ff9e7
parentecf88b16b8672c8b734d13d84910e97357c470a8 (diff)
downloadtor-b2863739083125d332cf1166ae6b095df7d0f155.tar.gz
tor-b2863739083125d332cf1166ae6b095df7d0f155.zip
Enable the ntor handshake on the client side.
"works for me"
-rw-r--r--src/or/channeltls.c2
-rw-r--r--src/or/circuitbuild.c103
-rw-r--r--src/or/circuitbuild.h5
-rw-r--r--src/or/circuituse.c4
-rw-r--r--src/or/config.c1
-rw-r--r--src/or/entrynodes.c2
-rw-r--r--src/or/nodelist.c12
-rw-r--r--src/or/nodelist.h1
-rw-r--r--src/or/or.h5
-rw-r--r--src/or/relay.c4
-rw-r--r--src/or/router.c3
-rw-r--r--src/or/routerparse.c2
12 files changed, 128 insertions, 16 deletions
diff --git a/src/or/channeltls.c b/src/or/channeltls.c
index ede245894e..f6069e0037 100644
--- a/src/or/channeltls.c
+++ b/src/or/channeltls.c
@@ -914,6 +914,8 @@ channel_tls_handle_cell(cell_t *cell, or_connection_t *conn)
case CELL_RELAY:
case CELL_RELAY_EARLY:
case CELL_DESTROY:
+ case CELL_CREATE2:
+ case CELL_CREATED2:
/*
* These are all transport independent and we pass them up through the
* channel_t mechanism. They are ultimately handled in command.c.
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index b7ab47f559..9300b049cb 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -604,6 +604,73 @@ circuit_timeout_want_to_count_circ(origin_circuit_t *circ)
&& circ->build_state->desired_path_len == DEFAULT_ROUTE_LEN;
}
+#ifdef CURVE25519_ENABLED
+/** Return true if the ntor handshake is enabled in the configuration, or if
+ * it's been set to "auto" in the configuration and it's enabled in the
+ * consensus. */
+static int
+circuits_can_use_ntor(void)
+{
+ const or_options_t *options = get_options();
+ if (options->UseNTorHandshake != -1)
+ return options->UseNTorHandshake;
+ return networkstatus_get_param(NULL, "UseNTorHandshake", 0, 0, 1);
+}
+#endif
+
+/** Decide whether to use a TAP or ntor handshake for connecting to <b>ei</b>
+ * directly, and set *<b>cell_type_out</b> and *<b>handshake_type_out</b>
+ * accordingly. */
+static void
+circuit_pick_create_handshake(uint8_t *cell_type_out,
+ uint16_t *handshake_type_out,
+ const extend_info_t *ei)
+{
+#ifdef CURVE25519_ENABLED
+ if (!tor_mem_is_zero((const char*)ei->curve25519_onion_key.public_key,
+ CURVE25519_PUBKEY_LEN) &&
+ circuits_can_use_ntor()) {
+ *cell_type_out = CELL_CREATE2;
+ *handshake_type_out = ONION_HANDSHAKE_TYPE_NTOR;
+ return;
+ }
+#else
+ (void) ei;
+#endif
+
+ *cell_type_out = CELL_CREATE;
+ *handshake_type_out = ONION_HANDSHAKE_TYPE_TAP;
+}
+
+/** Decide whether to use a TAP or ntor handshake for connecting to <b>ei</b>
+ * directly, and set *<b>handshake_type_out</b> accordingly. Decide whether,
+ * in extending through <b>node</b> to do so, we should use an EXTEND2 or an
+ * EXTEND cell to do so, and set *<b>cell_type_out</b> and
+ * *<b>create_cell_type_out</b> accordingly. */
+static void
+circuit_pick_extend_handshake(uint8_t *cell_type_out,
+ uint8_t *create_cell_type_out,
+ uint16_t *handshake_type_out,
+ const node_t *node_prev,
+ const extend_info_t *ei)
+{
+ uint8_t t;
+ circuit_pick_create_handshake(&t, handshake_type_out, ei);
+ /* XXXX024 The check for whether the node has a curve25519 key is a bad
+ * proxy for whether it can do extend2 cells; once a version that
+ * handles extend2 cells is out, remove it. */
+ if (node_prev &&
+ *handshake_type_out != ONION_HANDSHAKE_TYPE_TAP &&
+ (node_has_curve25519_onion_key(node_prev) ||
+ (node_prev->rs && node_prev->rs->version_supports_extend2_cells))) {
+ *cell_type_out = RELAY_COMMAND_EXTEND2;
+ *create_cell_type_out = CELL_CREATE2;
+ } else {
+ *cell_type_out = RELAY_COMMAND_EXTEND;
+ *create_cell_type_out = CELL_CREATE;
+ }
+}
+
/** This is the backbone function for building circuits.
*
* If circ's first hop is closed, then we need to build a create
@@ -638,10 +705,10 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
fast = should_use_create_fast_for_circuit(circ);
if (!fast) {
/* We are an OR and we know the right onion key: we should
- * send an old slow create cell.
+ * send a create cell.
*/
- cc.cell_type = CELL_CREATE;
- cc.handshake_type = ONION_HANDSHAKE_TYPE_TAP;
+ circuit_pick_create_handshake(&cc.cell_type, &cc.handshake_type,
+ circ->cpath->extend_info);
note_request("cell: create", 1);
} else {
/* We are not an OR, and we're building the first hop of a circuit to a
@@ -747,15 +814,21 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
return - END_CIRC_REASON_INTERNAL;
}
- ec.cell_type = RELAY_COMMAND_EXTEND;
+ {
+ const node_t *prev_node;
+ prev_node = node_get_by_id(hop->prev->extend_info->identity_digest);
+ circuit_pick_extend_handshake(&ec.cell_type,
+ &ec.create_cell.cell_type,
+ &ec.create_cell.handshake_type,
+ prev_node,
+ 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);
memcpy(ec.node_id, hop->extend_info->identity_digest, DIGEST_LEN);
- ec.create_cell.handshake_type = ONION_HANDSHAKE_TYPE_TAP;
- ec.create_cell.cell_type = CELL_CREATE;
-
len = onion_skin_create(ec.create_cell.handshake_type,
hop->extend_info,
&hop->handshake_state,
@@ -903,6 +976,7 @@ circuit_extend(cell_t *cell, circuit_t *circ)
circ->n_hop = extend_info_new(NULL /*nickname*/,
(const char*)ec.node_id,
NULL /*onion_key*/,
+ NULL /*curve25519_key*/,
&ec.orport_ipv4.addr,
ec.orport_ipv4.port);
@@ -938,6 +1012,7 @@ circuit_extend(cell_t *cell, circuit_t *circ)
if (circuit_deliver_create_cell(circ, &ec.create_cell, 1) < 0)
return -1;
+
return 0;
}
@@ -2310,8 +2385,9 @@ onion_append_hop(crypt_path_t **head_ptr, extend_info_t *choice)
/** Allocate a new extend_info object based on the various arguments. */
extend_info_t *
extend_info_new(const char *nickname, const char *digest,
- crypto_pk_t *onion_key,
- const tor_addr_t *addr, uint16_t port)
+ crypto_pk_t *onion_key,
+ const curve25519_public_key_t *curve25519_key,
+ const tor_addr_t *addr, uint16_t port)
{
extend_info_t *info = tor_malloc_zero(sizeof(extend_info_t));
memcpy(info->identity_digest, digest, DIGEST_LEN);
@@ -2319,6 +2395,13 @@ extend_info_new(const char *nickname, const char *digest,
strlcpy(info->nickname, nickname, sizeof(info->nickname));
if (onion_key)
info->onion_key = crypto_pk_dup_key(onion_key);
+#ifdef CURVE25519_ENABLED
+ if (curve25519_key)
+ memcpy(&info->curve25519_onion_key, curve25519_key,
+ sizeof(curve25519_public_key_t));
+#else
+ (void)curve25519_key;
+#endif
tor_addr_copy(&info->addr, addr);
info->port = port;
return info;
@@ -2353,12 +2436,14 @@ extend_info_from_node(const node_t *node, int for_direct_connect)
return extend_info_new(node->ri->nickname,
node->identity,
node->ri->onion_pkey,
+ node->ri->onion_curve25519_pkey,
&ap.addr,
ap.port);
else if (node->rs && node->md)
return extend_info_new(node->rs->nickname,
node->identity,
node->md->onion_pkey,
+ node->md->onion_curve25519_pkey,
&ap.addr,
ap.port);
else
diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h
index 23213e8e83..d4f7926cab 100644
--- a/src/or/circuitbuild.h
+++ b/src/or/circuitbuild.h
@@ -46,8 +46,9 @@ int circuit_append_new_exit(origin_circuit_t *circ, extend_info_t *info);
int circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *info);
void onion_append_to_cpath(crypt_path_t **head_ptr, crypt_path_t *new_hop);
extend_info_t *extend_info_new(const char *nickname, const char *digest,
- crypto_pk_t *onion_key,
- const tor_addr_t *addr, uint16_t port);
+ crypto_pk_t *onion_key,
+ const curve25519_public_key_t *curve25519_key,
+ const tor_addr_t *addr, uint16_t port);
extend_info_t *extend_info_from_node(const node_t *r, int for_direct_connect);
extend_info_t *extend_info_dup(extend_info_t *info);
void extend_info_free(extend_info_t *info);
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index d3cde1d66c..6a733d6d1a 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -1577,8 +1577,8 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn,
return -1;
}
extend_info = extend_info_new(conn->chosen_exit_name+1,
- digest, NULL, &addr,
- conn->socks_request->port);
+ digest, NULL, NULL, &addr,
+ conn->socks_request->port);
} else {
/* We will need an onion key for the router, and we
* don't have one. Refuse or relax requirements. */
diff --git a/src/or/config.c b/src/or/config.c
index 75f6193352..979d09c7cd 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -383,6 +383,7 @@ static config_var_t option_vars_[] = {
V(UseBridges, BOOL, "0"),
V(UseEntryGuards, BOOL, "1"),
V(UseMicrodescriptors, AUTOBOOL, "auto"),
+ V(UseNTorHandshake, AUTOBOOL, "auto"),
V(User, STRING, NULL),
V(UserspaceIOCPBuffers, BOOL, "0"),
VAR("V1AuthoritativeDirectory",BOOL, V1AuthoritativeDir, "0"),
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index edb26dc088..a4e18d04fe 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -1502,7 +1502,7 @@ routerset_contains_bridge(const routerset_t *routerset,
return 0;
extinfo = extend_info_new(
- NULL, bridge->identity, NULL, &bridge->addr, bridge->port);
+ NULL, bridge->identity, NULL, NULL, &bridge->addr, bridge->port);
result = routerset_contains_extendinfo(routerset, extinfo);
extend_info_free(extinfo);
return result;
diff --git a/src/or/nodelist.c b/src/or/nodelist.c
index 95345fb262..fa3828fc26 100644
--- a/src/or/nodelist.c
+++ b/src/or/nodelist.c
@@ -916,6 +916,18 @@ node_get_pref_ipv6_orport(const node_t *node, tor_addr_port_t *ap_out)
}
}
+/** Return true iff <b>node</b> has a curve25519 onion key. */
+int
+node_has_curve25519_onion_key(const node_t *node)
+{
+ if (node->ri)
+ return node->ri->onion_curve25519_pkey != NULL;
+ else if (node->md)
+ return node->md->onion_curve25519_pkey != NULL;
+ else
+ return 0;
+}
+
/** Refresh the country code of <b>ri</b>. This function MUST be called on
* each router when the GeoIP database is reloaded, and on all new routers. */
void
diff --git a/src/or/nodelist.h b/src/or/nodelist.h
index 13a3847414..39f0948779 100644
--- a/src/or/nodelist.h
+++ b/src/or/nodelist.h
@@ -54,6 +54,7 @@ int node_ipv6_preferred(const node_t *node);
int node_get_prim_orport(const node_t *node, tor_addr_port_t *ap_out);
void node_get_pref_orport(const node_t *node, tor_addr_port_t *ap_out);
void node_get_pref_ipv6_orport(const node_t *node, tor_addr_port_t *ap_out);
+int node_has_curve25519_onion_key(const node_t *node);
smartlist_t *nodelist_get_list(void);
diff --git a/src/or/or.h b/src/or/or.h
index 66e9054491..b5718a83dc 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2025,6 +2025,9 @@ typedef struct routerstatus_t {
/** True iff this router is a version that allows DATA cells to arrive on
* a stream before it has sent a CONNECTED cell. */
unsigned int version_supports_optimistic_data:1;
+ /** True iff this router has a version that allows it to accept EXTEND2
+ * cells */
+ unsigned int version_supports_extend2_cells:1;
unsigned int has_bandwidth:1; /**< The vote/consensus had bw info */
unsigned int has_exitsummary:1; /**< The vote/consensus had exit summaries */
@@ -3799,6 +3802,8 @@ typedef struct {
int IPv6Exit; /**< Do we support exiting to IPv6 addresses? */
+ /** Autobool: should we use the ntor handshake if we can? */
+ int UseNTorHandshake;
} or_options_t;
/** Persistent state for an onion router, as saved to disk. */
diff --git a/src/or/relay.c b/src/or/relay.c
index 5d87b270f7..ddeec4e789 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -572,6 +572,7 @@ relay_send_command_from_edge(streamid_t stream_id, circuit_t *circ,
origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ);
if (origin_circ->remaining_relay_early_cells > 0 &&
(relay_command == RELAY_COMMAND_EXTEND ||
+ relay_command == RELAY_COMMAND_EXTEND2 ||
cpath_layer != origin_circ->cpath)) {
/* If we've got any relay_early cells left and (we're sending
* an extend cell or we're not talking to the first hop), use
@@ -585,7 +586,8 @@ relay_send_command_from_edge(streamid_t stream_id, circuit_t *circ,
* task 878. */
origin_circ->relay_early_commands[
origin_circ->relay_early_cells_sent++] = relay_command;
- } else if (relay_command == RELAY_COMMAND_EXTEND) {
+ } else if (relay_command == RELAY_COMMAND_EXTEND ||
+ relay_command == RELAY_COMMAND_EXTEND2) {
/* If no RELAY_EARLY cells can be sent over this circuit, log which
* commands have been sent as RELAY_EARLY cells before; helps debug
* task 878. */
diff --git a/src/or/router.c b/src/or/router.c
index 3733bec4d0..a97db858b0 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -1071,7 +1071,8 @@ extend_info_from_router(const routerinfo_t *r)
router_get_prim_orport(r, &ap);
return extend_info_new(r->nickname, r->cache_info.identity_digest,
- r->onion_pkey, &ap.addr, ap.port);
+ r->onion_pkey, r->onion_curve25519_pkey,
+ &ap.addr, ap.port);
}
/** Some time has passed, or we just got new directory information.
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index 17902d9d0a..1be2374062 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -2188,6 +2188,8 @@ routerstatus_parse_entry_from_string(memarea_t *area,
tor_version_supports_microdescriptors(tok->args[0]);
rs->version_supports_optimistic_data =
tor_version_as_new_as(tok->args[0], "0.2.3.1-alpha");
+ rs->version_supports_extend2_cells =
+ tor_version_as_new_as(tok->args[0], "0.2.4.7-alpha");
}
if (vote_rs) {
vote_rs->version = tor_strdup(tok->args[0]);