Enable the ntor handshake on the client side.

"works for me"
This commit is contained in:
Nick Mathewson 2012-12-06 01:53:29 -05:00
parent ecf88b16b8
commit b286373908
12 changed files with 128 additions and 16 deletions

View File

@ -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.

View File

@ -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

View File

@ -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);

View File

@ -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. */

View File

@ -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"),

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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. */

View File

@ -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. */

View File

@ -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.

View File

@ -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]);