Loading changes/reject-tap 0 → 100644 +15 −0 Original line number Diff line number Diff line o Major bug fixes (circuit building): - Tor authorities, relays, and clients only use ntor, except for rare cases in the hidden service protocol. - Authorities, relays and clients specifically check that each descriptor has an ntor key. - Clients avoid downloading a descriptor if the relay version is too old to support ntor. - Client code never chooses nodes without ntor keys: they will not be selected during circuit-building, or as guards, or as directory mirrors, or as introduction or rendezvous points. - Circuit-building code assumes that all hops can use ntor, except for rare hidden service protocol cases. - Hidden service client to intro point and service to rendezvous point connections use the TAP key supplied by the protocol. Fixes bug 19163; bugfix on 0.2.4.18-rc. doc/tor.1.txt +0 −10 Original line number Diff line number Diff line Loading @@ -1452,16 +1452,6 @@ The following options are useful only for clients (that is, if "auto" (recommended) then it is on for all clients that do not set FetchUselessDescriptors. (Default: auto) [[UseNTorHandshake]] **UseNTorHandshake** **0**|**1**|**auto**:: The "ntor" circuit-creation handshake is faster and (we think) more secure than the original ("TAP") circuit handshake, but starting to use it too early might make your client stand out. If this option is 0, your Tor client won't use the ntor handshake. If it's 1, your Tor client will use the ntor handshake to extend circuits through servers that support it. If this option is "auto", then your client will use the ntor handshake once enough directory authorities recommend it. (Default: 1) [[PathBiasCircThreshold]] **PathBiasCircThreshold** __NUM__ + [[PathBiasNoticeRate]] **PathBiasNoticeRate** __NUM__ + Loading src/or/circuitbuild.c +166 −64 Original line number Diff line number Diff line Loading @@ -58,7 +58,6 @@ 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); static int circuits_can_use_ntor(void); /** This function tries to get a channel to the specified endpoint, * and then calls command_setup_channel() to give it the right Loading Loading @@ -365,7 +364,7 @@ circuit_rep_hist_note_result(origin_circuit_t *circ) } while (hop!=circ->cpath); } /** Return 1 iff at least one node in circ's cpath supports ntor. */ /** Return 1 iff every node in circ's cpath definitely supports ntor. */ static int circuit_cpath_supports_ntor(const origin_circuit_t *circ) { Loading @@ -373,16 +372,19 @@ circuit_cpath_supports_ntor(const origin_circuit_t *circ) cpath = head = circ->cpath; do { if (cpath->extend_info && !tor_mem_is_zero( (const char*)cpath->extend_info->curve25519_onion_key.public_key, CURVE25519_PUBKEY_LEN)) return 1; /* if the extend_info is missing, we can't tell if it supports ntor */ if (!cpath->extend_info) { return 0; } /* if the key is blank, it definitely doesn't support ntor */ if (!extend_info_supports_ntor(cpath->extend_info)) { return 0; } cpath = cpath->next; } while (cpath != head); return 0; return 1; } /** Pick all the entries in our cpath. Stop and return 0 when we're Loading @@ -390,43 +392,63 @@ circuit_cpath_supports_ntor(const origin_circuit_t *circ) static int onion_populate_cpath(origin_circuit_t *circ) { int n_tries = 0; const int using_ntor = circuits_can_use_ntor(); int r = 0; #define MAX_POPULATE_ATTEMPTS 32 /* onion_extend_cpath assumes these are non-NULL */ tor_assert(circ); tor_assert(circ->build_state); while (1) { int r = onion_extend_cpath(circ); while (r == 0) { 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; /* The path is complete */ tor_assert(r == 1); /* No node in the circuit supports ntor. Have we already tried too many * times? */ if (++n_tries >= MAX_POPULATE_ATTEMPTS) break; /* Does every node in this path support ntor? */ int path_supports_ntor = circuit_cpath_supports_ntor(circ); /* Clear the path and retry */ circuit_clear_cpath(circ); /* We would like every path to support ntor, but we have to allow for some * edge cases. */ tor_assert(circuit_get_cpath_len(circ)); if (circuit_can_use_tap(circ)) { /* Circuits from clients to intro points, and hidden services to * rend points do not support ntor, because the hidden service protocol * does not include ntor onion keys. This is also true for Tor2web clients * and Single Onion Services. */ return 0; } if (circuit_get_cpath_len(circ) == 1) { /* Allow for bootstrapping: when we're fetching directly from a fallback, * authority, or bridge, we have no way of knowing its ntor onion key * before we connect to it. So instead, we try connecting, and end up using * CREATE_FAST. */ tor_assert(circ->cpath); tor_assert(circ->cpath->extend_info); const node_t *node = node_get_by_id( circ->cpath->extend_info->identity_digest); /* If we don't know the node and its descriptor, we must be bootstrapping. */ if (!node || !node_has_descriptor(node)) { return 0; } } 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); if (BUG(!path_supports_ntor)) { /* If we're building a multi-hop path, and it's not one of the HS or * bootstrapping exceptions, and it doesn't support ntor, something has * gone wrong. */ return -1; } return 0; } /** Create and return a new origin circuit. Initialize its purpose and * build-state based on our arguments. The <b>flags</b> argument is a * bitfield of CIRCLAUNCH_* flags. */ Loading Loading @@ -757,10 +779,13 @@ should_use_create_fast_for_circuit(origin_circuit_t *circ) tor_assert(circ->cpath); tor_assert(circ->cpath->extend_info); if (!circ->cpath->extend_info->onion_key) return 1; /* our hand is forced: only a create_fast will work. */ if (!circuit_has_usable_onion_key(circ)) { /* We don't have ntor, and we don't have or can't use TAP, * so our hand is forced: only a create_fast will work. */ return 1; } if (public_server_mode(options)) { /* We're a server, and we know an onion key. We can choose. /* We're a server, and we have a usable onion key. We can choose. * Prefer to blend our circuit into the other circuits we are * creating on behalf of others. */ return 0; Loading @@ -785,30 +810,20 @@ circuit_timeout_want_to_count_circ(origin_circuit_t *circ) && circ->build_state->desired_path_len == DEFAULT_ROUTE_LEN; } /** 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); } /** 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. */ * accordingly. * Note that TAP handshakes are only used for direct connections: * - from Tor2web to intro points not in the client's consensus, and * - from Single Onions to rend points not in the service's consensus. * This is checked in onion_populate_cpath. */ static void circuit_pick_create_handshake(uint8_t *cell_type_out, uint16_t *handshake_type_out, const extend_info_t *ei) { /* XXXX029 Remove support for deciding to use TAP. */ if (!tor_mem_is_zero((const char*)ei->curve25519_onion_key.public_key, CURVE25519_PUBKEY_LEN) && circuits_can_use_ntor()) { /* XXXX030 Remove support for deciding to use TAP. */ if (extend_info_supports_ntor(ei)) { *cell_type_out = CELL_CREATE2; *handshake_type_out = ONION_HANDSHAKE_TYPE_NTOR; return; Loading @@ -822,7 +837,11 @@ circuit_pick_create_handshake(uint8_t *cell_type_out, * 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. */ * *<b>create_cell_type_out</b> accordingly. * Note that TAP handshakes are only used for extend handshakes: * - from clients to intro points, and * - from hidden services to rend points. * This is checked in onion_populate_cpath. */ static void circuit_pick_extend_handshake(uint8_t *cell_type_out, uint8_t *create_cell_type_out, Loading @@ -833,11 +852,21 @@ circuit_pick_extend_handshake(uint8_t *cell_type_out, uint8_t t; circuit_pick_create_handshake(&t, handshake_type_out, ei); /* XXXX029 Remove support for deciding to use TAP. */ /* XXXX030 Remove support for deciding to use TAP. */ /* It is an error to extend if there is no previous node. */ tor_assert_nonfatal(node_prev); /* It is an error for a node with a known version to be so old it does not * support ntor. */ tor_assert_nonfatal(routerstatus_version_supports_ntor(node_prev->rs, 1)); /* Assume relays without tor versions or routerstatuses support ntor. * The authorities enforce ntor support, and assuming and failing is better * than allowing a malicious node to perform a protocol downgrade to TAP. */ 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))) { (routerstatus_version_supports_ntor(node_prev->rs, 1)))) { *cell_type_out = RELAY_COMMAND_EXTEND2; *create_cell_type_out = CELL_CREATE2; } else { Loading Loading @@ -2058,15 +2087,18 @@ count_acceptable_nodes(smartlist_t *nodes) if (! node->is_running) // log_debug(LD_CIRC,"Nope, the directory says %d is not running.",i); continue; /* XXX This clause makes us count incorrectly: if AllowInvalidRouters * allows this node in some places, then we're getting an inaccurate * count. For now, be conservative and don't count it. But later we * should try to be smarter. */ if (! node->is_valid) // log_debug(LD_CIRC,"Nope, the directory says %d is not valid.",i); continue; if (! node_has_descriptor(node)) continue; /* XXX This clause makes us count incorrectly: if AllowInvalidRouters * allows this node in some places, then we're getting an inaccurate * count. For now, be conservative and don't count it. But later we * should try to be smarter. */ /* The node has a descriptor, so we can just check the ntor key directly */ if (!node_has_curve25519_onion_key(node)) continue; ++num; } SMARTLIST_FOREACH_END(node); Loading Loading @@ -2356,6 +2388,14 @@ extend_info_from_node(const node_t *node, int for_direct_connect) log_warn(LD_CIRC, "Could not choose valid address for %s", node->ri ? node->ri->nickname : node->rs->nickname); /* Every node we connect or extend to must support ntor */ if (!node_has_curve25519_onion_key(node)) { log_fn(LOG_PROTOCOL_WARN, LD_CIRC, "Attempted to create extend_info for a node that does not support " "ntor: %s", node_describe(node)); return NULL; } if (valid_addr && node->ri) return extend_info_new(node->ri->nickname, node->identity, Loading Loading @@ -2441,3 +2481,65 @@ extend_info_addr_is_allowed(const tor_addr_t *addr) return 0; } /* Does ei have a valid TAP key? */ int extend_info_supports_tap(const extend_info_t* ei) { tor_assert(ei); /* Valid TAP keys are not NULL */ return ei->onion_key != NULL; } /* Does ei have a valid ntor key? */ int extend_info_supports_ntor(const extend_info_t* ei) { tor_assert(ei); /* Valid ntor keys have at least one non-zero byte */ return !tor_mem_is_zero( (const char*)ei->curve25519_onion_key.public_key, CURVE25519_PUBKEY_LEN); } /* Is circuit purpose allowed to use the deprecated TAP encryption protocol? * The hidden service protocol still uses TAP for some connections, because * ntor onion keys aren't included in HS descriptors or INTRODUCE cells. */ static int circuit_purpose_can_use_tap_impl(uint8_t purpose) { return (purpose == CIRCUIT_PURPOSE_S_CONNECT_REND || purpose == CIRCUIT_PURPOSE_C_INTRODUCING); } /* Is circ allowed to use the deprecated TAP encryption protocol? * The hidden service protocol still uses TAP for some connections, because * ntor onion keys aren't included in HS descriptors or INTRODUCE cells. */ int circuit_can_use_tap(const origin_circuit_t *circ) { tor_assert(circ); tor_assert(circ->cpath); tor_assert(circ->cpath->extend_info); return (circuit_purpose_can_use_tap_impl(circ->base_.purpose) && extend_info_supports_tap(circ->cpath->extend_info)); } /* Does circ have an onion key which it's allowed to use? */ int circuit_has_usable_onion_key(const origin_circuit_t *circ) { tor_assert(circ); tor_assert(circ->cpath); tor_assert(circ->cpath->extend_info); return (extend_info_supports_ntor(circ->cpath->extend_info) || circuit_can_use_tap(circ)); } /* Does ei have an onion key which it would prefer to use? * Currently, we prefer ntor keys*/ int extend_info_has_preferred_onion_key(const extend_info_t* ei) { tor_assert(ei); return extend_info_supports_ntor(ei); } src/or/circuitbuild.h +5 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,11 @@ 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); int extend_info_addr_is_allowed(const tor_addr_t *addr); int extend_info_supports_tap(const extend_info_t* ei); int extend_info_supports_ntor(const extend_info_t* ei); int circuit_can_use_tap(const origin_circuit_t *circ); int circuit_has_usable_onion_key(const origin_circuit_t *circ); int extend_info_has_preferred_onion_key(const extend_info_t* ei); const node_t *build_state_get_exit_node(cpath_build_state_t *state); const char *build_state_get_exit_nickname(cpath_build_state_t *state); Loading src/or/circuitlist.c +4 −2 Original line number Diff line number Diff line Loading @@ -1613,7 +1613,8 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info, return best; } /** Return the number of hops in circuit's path. */ /** Return the number of hops in circuit's path. If circ has no entries, * or is NULL, returns 0. */ int circuit_get_cpath_len(origin_circuit_t *circ) { Loading @@ -1629,7 +1630,8 @@ circuit_get_cpath_len(origin_circuit_t *circ) } /** Return the <b>hopnum</b>th hop in <b>circ</b>->cpath, or NULL if there * aren't that many hops in the list. */ * aren't that many hops in the list. <b>hopnum</b> starts at 1. * Returns NULL if <b>hopnum</b> is 0 or negative. */ crypt_path_t * circuit_get_cpath_hop(origin_circuit_t *circ, int hopnum) { Loading Loading
changes/reject-tap 0 → 100644 +15 −0 Original line number Diff line number Diff line o Major bug fixes (circuit building): - Tor authorities, relays, and clients only use ntor, except for rare cases in the hidden service protocol. - Authorities, relays and clients specifically check that each descriptor has an ntor key. - Clients avoid downloading a descriptor if the relay version is too old to support ntor. - Client code never chooses nodes without ntor keys: they will not be selected during circuit-building, or as guards, or as directory mirrors, or as introduction or rendezvous points. - Circuit-building code assumes that all hops can use ntor, except for rare hidden service protocol cases. - Hidden service client to intro point and service to rendezvous point connections use the TAP key supplied by the protocol. Fixes bug 19163; bugfix on 0.2.4.18-rc.
doc/tor.1.txt +0 −10 Original line number Diff line number Diff line Loading @@ -1452,16 +1452,6 @@ The following options are useful only for clients (that is, if "auto" (recommended) then it is on for all clients that do not set FetchUselessDescriptors. (Default: auto) [[UseNTorHandshake]] **UseNTorHandshake** **0**|**1**|**auto**:: The "ntor" circuit-creation handshake is faster and (we think) more secure than the original ("TAP") circuit handshake, but starting to use it too early might make your client stand out. If this option is 0, your Tor client won't use the ntor handshake. If it's 1, your Tor client will use the ntor handshake to extend circuits through servers that support it. If this option is "auto", then your client will use the ntor handshake once enough directory authorities recommend it. (Default: 1) [[PathBiasCircThreshold]] **PathBiasCircThreshold** __NUM__ + [[PathBiasNoticeRate]] **PathBiasNoticeRate** __NUM__ + Loading
src/or/circuitbuild.c +166 −64 Original line number Diff line number Diff line Loading @@ -58,7 +58,6 @@ 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); static int circuits_can_use_ntor(void); /** This function tries to get a channel to the specified endpoint, * and then calls command_setup_channel() to give it the right Loading Loading @@ -365,7 +364,7 @@ circuit_rep_hist_note_result(origin_circuit_t *circ) } while (hop!=circ->cpath); } /** Return 1 iff at least one node in circ's cpath supports ntor. */ /** Return 1 iff every node in circ's cpath definitely supports ntor. */ static int circuit_cpath_supports_ntor(const origin_circuit_t *circ) { Loading @@ -373,16 +372,19 @@ circuit_cpath_supports_ntor(const origin_circuit_t *circ) cpath = head = circ->cpath; do { if (cpath->extend_info && !tor_mem_is_zero( (const char*)cpath->extend_info->curve25519_onion_key.public_key, CURVE25519_PUBKEY_LEN)) return 1; /* if the extend_info is missing, we can't tell if it supports ntor */ if (!cpath->extend_info) { return 0; } /* if the key is blank, it definitely doesn't support ntor */ if (!extend_info_supports_ntor(cpath->extend_info)) { return 0; } cpath = cpath->next; } while (cpath != head); return 0; return 1; } /** Pick all the entries in our cpath. Stop and return 0 when we're Loading @@ -390,43 +392,63 @@ circuit_cpath_supports_ntor(const origin_circuit_t *circ) static int onion_populate_cpath(origin_circuit_t *circ) { int n_tries = 0; const int using_ntor = circuits_can_use_ntor(); int r = 0; #define MAX_POPULATE_ATTEMPTS 32 /* onion_extend_cpath assumes these are non-NULL */ tor_assert(circ); tor_assert(circ->build_state); while (1) { int r = onion_extend_cpath(circ); while (r == 0) { 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; /* The path is complete */ tor_assert(r == 1); /* No node in the circuit supports ntor. Have we already tried too many * times? */ if (++n_tries >= MAX_POPULATE_ATTEMPTS) break; /* Does every node in this path support ntor? */ int path_supports_ntor = circuit_cpath_supports_ntor(circ); /* Clear the path and retry */ circuit_clear_cpath(circ); /* We would like every path to support ntor, but we have to allow for some * edge cases. */ tor_assert(circuit_get_cpath_len(circ)); if (circuit_can_use_tap(circ)) { /* Circuits from clients to intro points, and hidden services to * rend points do not support ntor, because the hidden service protocol * does not include ntor onion keys. This is also true for Tor2web clients * and Single Onion Services. */ return 0; } if (circuit_get_cpath_len(circ) == 1) { /* Allow for bootstrapping: when we're fetching directly from a fallback, * authority, or bridge, we have no way of knowing its ntor onion key * before we connect to it. So instead, we try connecting, and end up using * CREATE_FAST. */ tor_assert(circ->cpath); tor_assert(circ->cpath->extend_info); const node_t *node = node_get_by_id( circ->cpath->extend_info->identity_digest); /* If we don't know the node and its descriptor, we must be bootstrapping. */ if (!node || !node_has_descriptor(node)) { return 0; } } 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); if (BUG(!path_supports_ntor)) { /* If we're building a multi-hop path, and it's not one of the HS or * bootstrapping exceptions, and it doesn't support ntor, something has * gone wrong. */ return -1; } return 0; } /** Create and return a new origin circuit. Initialize its purpose and * build-state based on our arguments. The <b>flags</b> argument is a * bitfield of CIRCLAUNCH_* flags. */ Loading Loading @@ -757,10 +779,13 @@ should_use_create_fast_for_circuit(origin_circuit_t *circ) tor_assert(circ->cpath); tor_assert(circ->cpath->extend_info); if (!circ->cpath->extend_info->onion_key) return 1; /* our hand is forced: only a create_fast will work. */ if (!circuit_has_usable_onion_key(circ)) { /* We don't have ntor, and we don't have or can't use TAP, * so our hand is forced: only a create_fast will work. */ return 1; } if (public_server_mode(options)) { /* We're a server, and we know an onion key. We can choose. /* We're a server, and we have a usable onion key. We can choose. * Prefer to blend our circuit into the other circuits we are * creating on behalf of others. */ return 0; Loading @@ -785,30 +810,20 @@ circuit_timeout_want_to_count_circ(origin_circuit_t *circ) && circ->build_state->desired_path_len == DEFAULT_ROUTE_LEN; } /** 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); } /** 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. */ * accordingly. * Note that TAP handshakes are only used for direct connections: * - from Tor2web to intro points not in the client's consensus, and * - from Single Onions to rend points not in the service's consensus. * This is checked in onion_populate_cpath. */ static void circuit_pick_create_handshake(uint8_t *cell_type_out, uint16_t *handshake_type_out, const extend_info_t *ei) { /* XXXX029 Remove support for deciding to use TAP. */ if (!tor_mem_is_zero((const char*)ei->curve25519_onion_key.public_key, CURVE25519_PUBKEY_LEN) && circuits_can_use_ntor()) { /* XXXX030 Remove support for deciding to use TAP. */ if (extend_info_supports_ntor(ei)) { *cell_type_out = CELL_CREATE2; *handshake_type_out = ONION_HANDSHAKE_TYPE_NTOR; return; Loading @@ -822,7 +837,11 @@ circuit_pick_create_handshake(uint8_t *cell_type_out, * 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. */ * *<b>create_cell_type_out</b> accordingly. * Note that TAP handshakes are only used for extend handshakes: * - from clients to intro points, and * - from hidden services to rend points. * This is checked in onion_populate_cpath. */ static void circuit_pick_extend_handshake(uint8_t *cell_type_out, uint8_t *create_cell_type_out, Loading @@ -833,11 +852,21 @@ circuit_pick_extend_handshake(uint8_t *cell_type_out, uint8_t t; circuit_pick_create_handshake(&t, handshake_type_out, ei); /* XXXX029 Remove support for deciding to use TAP. */ /* XXXX030 Remove support for deciding to use TAP. */ /* It is an error to extend if there is no previous node. */ tor_assert_nonfatal(node_prev); /* It is an error for a node with a known version to be so old it does not * support ntor. */ tor_assert_nonfatal(routerstatus_version_supports_ntor(node_prev->rs, 1)); /* Assume relays without tor versions or routerstatuses support ntor. * The authorities enforce ntor support, and assuming and failing is better * than allowing a malicious node to perform a protocol downgrade to TAP. */ 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))) { (routerstatus_version_supports_ntor(node_prev->rs, 1)))) { *cell_type_out = RELAY_COMMAND_EXTEND2; *create_cell_type_out = CELL_CREATE2; } else { Loading Loading @@ -2058,15 +2087,18 @@ count_acceptable_nodes(smartlist_t *nodes) if (! node->is_running) // log_debug(LD_CIRC,"Nope, the directory says %d is not running.",i); continue; /* XXX This clause makes us count incorrectly: if AllowInvalidRouters * allows this node in some places, then we're getting an inaccurate * count. For now, be conservative and don't count it. But later we * should try to be smarter. */ if (! node->is_valid) // log_debug(LD_CIRC,"Nope, the directory says %d is not valid.",i); continue; if (! node_has_descriptor(node)) continue; /* XXX This clause makes us count incorrectly: if AllowInvalidRouters * allows this node in some places, then we're getting an inaccurate * count. For now, be conservative and don't count it. But later we * should try to be smarter. */ /* The node has a descriptor, so we can just check the ntor key directly */ if (!node_has_curve25519_onion_key(node)) continue; ++num; } SMARTLIST_FOREACH_END(node); Loading Loading @@ -2356,6 +2388,14 @@ extend_info_from_node(const node_t *node, int for_direct_connect) log_warn(LD_CIRC, "Could not choose valid address for %s", node->ri ? node->ri->nickname : node->rs->nickname); /* Every node we connect or extend to must support ntor */ if (!node_has_curve25519_onion_key(node)) { log_fn(LOG_PROTOCOL_WARN, LD_CIRC, "Attempted to create extend_info for a node that does not support " "ntor: %s", node_describe(node)); return NULL; } if (valid_addr && node->ri) return extend_info_new(node->ri->nickname, node->identity, Loading Loading @@ -2441,3 +2481,65 @@ extend_info_addr_is_allowed(const tor_addr_t *addr) return 0; } /* Does ei have a valid TAP key? */ int extend_info_supports_tap(const extend_info_t* ei) { tor_assert(ei); /* Valid TAP keys are not NULL */ return ei->onion_key != NULL; } /* Does ei have a valid ntor key? */ int extend_info_supports_ntor(const extend_info_t* ei) { tor_assert(ei); /* Valid ntor keys have at least one non-zero byte */ return !tor_mem_is_zero( (const char*)ei->curve25519_onion_key.public_key, CURVE25519_PUBKEY_LEN); } /* Is circuit purpose allowed to use the deprecated TAP encryption protocol? * The hidden service protocol still uses TAP for some connections, because * ntor onion keys aren't included in HS descriptors or INTRODUCE cells. */ static int circuit_purpose_can_use_tap_impl(uint8_t purpose) { return (purpose == CIRCUIT_PURPOSE_S_CONNECT_REND || purpose == CIRCUIT_PURPOSE_C_INTRODUCING); } /* Is circ allowed to use the deprecated TAP encryption protocol? * The hidden service protocol still uses TAP for some connections, because * ntor onion keys aren't included in HS descriptors or INTRODUCE cells. */ int circuit_can_use_tap(const origin_circuit_t *circ) { tor_assert(circ); tor_assert(circ->cpath); tor_assert(circ->cpath->extend_info); return (circuit_purpose_can_use_tap_impl(circ->base_.purpose) && extend_info_supports_tap(circ->cpath->extend_info)); } /* Does circ have an onion key which it's allowed to use? */ int circuit_has_usable_onion_key(const origin_circuit_t *circ) { tor_assert(circ); tor_assert(circ->cpath); tor_assert(circ->cpath->extend_info); return (extend_info_supports_ntor(circ->cpath->extend_info) || circuit_can_use_tap(circ)); } /* Does ei have an onion key which it would prefer to use? * Currently, we prefer ntor keys*/ int extend_info_has_preferred_onion_key(const extend_info_t* ei) { tor_assert(ei); return extend_info_supports_ntor(ei); }
src/or/circuitbuild.h +5 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,11 @@ 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); int extend_info_addr_is_allowed(const tor_addr_t *addr); int extend_info_supports_tap(const extend_info_t* ei); int extend_info_supports_ntor(const extend_info_t* ei); int circuit_can_use_tap(const origin_circuit_t *circ); int circuit_has_usable_onion_key(const origin_circuit_t *circ); int extend_info_has_preferred_onion_key(const extend_info_t* ei); const node_t *build_state_get_exit_node(cpath_build_state_t *state); const char *build_state_get_exit_nickname(cpath_build_state_t *state); Loading
src/or/circuitlist.c +4 −2 Original line number Diff line number Diff line Loading @@ -1613,7 +1613,8 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info, return best; } /** Return the number of hops in circuit's path. */ /** Return the number of hops in circuit's path. If circ has no entries, * or is NULL, returns 0. */ int circuit_get_cpath_len(origin_circuit_t *circ) { Loading @@ -1629,7 +1630,8 @@ circuit_get_cpath_len(origin_circuit_t *circ) } /** Return the <b>hopnum</b>th hop in <b>circ</b>->cpath, or NULL if there * aren't that many hops in the list. */ * aren't that many hops in the list. <b>hopnum</b> starts at 1. * Returns NULL if <b>hopnum</b> is 0 or negative. */ crypt_path_t * circuit_get_cpath_hop(origin_circuit_t *circ, int hopnum) { Loading