From 7d8de8cd1041ed84f1073c55aa588de88bcd23c3 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 2 Jul 2004 23:40:03 +0000 Subject: More digest/nickname fixes svn:r2000 --- src/common/crypto.c | 3 ++- src/or/circuitbuild.c | 52 +++++++++++++++++++++++++++------------------ src/or/circuitlist.c | 6 +++--- src/or/circuituse.c | 41 ++++++++++++++++++++++++------------ src/or/connection.c | 7 ++++--- src/or/connection_or.c | 2 ++ src/or/directory.c | 2 +- src/or/or.h | 12 +++++++---- src/or/rendclient.c | 16 +++++++------- src/or/rendservice.c | 22 +++++++++---------- src/or/router.c | 1 + src/or/routerlist.c | 57 ++++++++++++++++++++++++++++++++++++++++---------- src/or/routerparse.c | 4 ++-- src/or/test.c | 11 ++++++++++ 14 files changed, 160 insertions(+), 76 deletions(-) (limited to 'src') diff --git a/src/common/crypto.c b/src/common/crypto.c index 93a4738cf..b8882cf21 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -1448,7 +1448,7 @@ int base16_encode(char *dest, int destlen, const char *src, int srclen) ++src; cp += 2; } - *dest = '\0'; + *cp = '\0'; return 0; } @@ -1484,6 +1484,7 @@ int base16_decode(char *dest, int destlen, const char *src, int srclen) return -1; *(uint8_t*)dest = (v1<<4)|v2; ++dest; + src+=2; } *dest = '\0'; return 0; diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index bb31deb79..c063a6f61 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -21,7 +21,7 @@ extern circuit_t *global_circuitlist; static int circuit_deliver_create_cell(circuit_t *circ, char *payload); static cpath_build_state_t * -onion_new_cpath_build_state(uint8_t purpose, const char *exit_nickname); +onion_new_cpath_build_state(uint8_t purpose, const char *exit_digest); static int onion_extend_cpath(crypt_path_t **head_ptr, cpath_build_state_t *state, routerinfo_t **router_out); @@ -75,7 +75,7 @@ void circuit_log_path(int severity, circuit_t *circ) { tor_assert(CIRCUIT_IS_ORIGIN(circ) && circ->cpath); snprintf(s, sizeof(buf)-1, "circ (length %d, exit %s): ", - circ->build_state->desired_path_len, circ->build_state->chosen_exit); + circ->build_state->desired_path_len, circ->build_state->chosen_exit_name); hop=circ->cpath; do { s = buf + strlen(buf); @@ -148,7 +148,7 @@ circuit_dump_details(int severity, circuit_t *circ, int poll_index, if(CIRCUIT_IS_ORIGIN(circ)) { /* circ starts at this node */ if(circ->state == CIRCUIT_STATE_BUILDING) log(severity,"Building: desired len %d, planned exit node %s.", - circ->build_state->desired_path_len, circ->build_state->chosen_exit); + circ->build_state->desired_path_len, circ->build_state->chosen_exit_name); for(hop=circ->cpath;hop->next != circ->cpath; hop=hop->next) log(severity,"hop: state %d, addr 0x%.8x, port %d", hop->state, (unsigned int)hop->addr, @@ -185,7 +185,7 @@ void circuit_dump_by_conn(connection_t *conn, int severity) { } } -/** Build a new circuit for purpose. If exit_nickname +/** Build a new circuit for purpose. If exit_digest * is defined, then use that as your exit router, else choose a suitable * exit node. * @@ -193,14 +193,14 @@ void circuit_dump_by_conn(connection_t *conn, int severity) { * it's not open already. */ circuit_t *circuit_establish_circuit(uint8_t purpose, - const char *exit_nickname) { + const char *exit_digest) { routerinfo_t *firsthop; connection_t *n_conn; circuit_t *circ; circ = circuit_new(0, NULL); /* sets circ->p_circ_id and circ->p_conn */ circ->state = CIRCUIT_STATE_OR_WAIT; - circ->build_state = onion_new_cpath_build_state(purpose, exit_nickname); + circ->build_state = onion_new_cpath_build_state(purpose, exit_digest); circ->purpose = purpose; if (! circ->build_state) { @@ -302,6 +302,10 @@ circuit_deliver_create_cell(circuit_t *circ, char *payload) { tor_assert(circ && circ->n_conn && circ->n_conn->type == CONN_TYPE_OR); tor_assert(payload); + /* XXXX008 How can we keep a good upgrade path here? We should + * compare keys, not nicknames...but older servers will compare nicknames. + * Should we check server version from the most recent directory? Hm. + */ circ_id_type = decide_circ_id_type(options.Nickname, circ->n_conn->nickname); circ->n_circ_id = get_unique_circ_id_by_conn(circ->n_conn, circ_id_type); @@ -345,7 +349,7 @@ int circuit_send_next_onion_skin(circuit_t *circ) { if(circ->cpath->state == CPATH_STATE_CLOSED) { log_fn(LOG_DEBUG,"First skin; sending create cell."); - router = router_get_by_nickname(circ->n_conn->nickname); + router = router_get_by_digest(circ->n_conn->identity_digest); if (!router) { log_fn(LOG_WARN,"Couldn't find routerinfo for %s", circ->n_conn->nickname); @@ -945,22 +949,29 @@ static routerinfo_t *choose_good_exit_server(uint8_t purpose, routerlist_t *dir) * return it. */ static cpath_build_state_t * -onion_new_cpath_build_state(uint8_t purpose, const char *exit_nickname) +onion_new_cpath_build_state(uint8_t purpose, const char *exit_digest) { routerlist_t *rl; int r; cpath_build_state_t *info; routerinfo_t *exit; - router_get_routerlist(&rl); r = new_route_len(options.PathlenCoinWeight, purpose, rl->routers); if (r < 0) return NULL; info = tor_malloc_zero(sizeof(cpath_build_state_t)); info->desired_path_len = r; - if(exit_nickname) { /* the circuit-builder pre-requested one */ - log_fn(LOG_INFO,"Using requested exit node '%s'", exit_nickname); - info->chosen_exit = tor_strdup(exit_nickname); + if(exit_digest) { /* the circuit-builder pre-requested one */ + memcpy(info->chosen_exit_digest, exit_digest, DIGEST_LEN); + exit = router_get_by_digest(exit_digest); + if (exit) { + info->chosen_exit_name = tor_strdup(exit->nickname); + } else { + info->chosen_exit_name = tor_malloc(HEX_DIGEST_LEN+1); + base16_encode(info->chosen_exit_name, HEX_DIGEST_LEN+1, + exit_digest, DIGEST_LEN); + } + log_fn(LOG_INFO,"Using requested exit node '%s'", info->chosen_exit_name); } else { /* we have to decide one */ exit = choose_good_exit_server(purpose, rl); if(!exit) { @@ -968,7 +979,8 @@ onion_new_cpath_build_state(uint8_t purpose, const char *exit_nickname) tor_free(info); return NULL; } - info->chosen_exit = tor_strdup(exit->nickname); + memcpy(info->chosen_exit_digest, exit->identity_digest, DIGEST_LEN); + info->chosen_exit_name = tor_strdup(exit->nickname); } return info; } @@ -1091,12 +1103,12 @@ onion_extend_cpath(crypt_path_t **head_ptr, cpath_build_state_t if(cur_len == state->desired_path_len - 1) { /* Picking last node */ log_fn(LOG_DEBUG, "Contemplating last hop: choice already made: %s", - state->chosen_exit); - choice = router_get_by_nickname(state->chosen_exit); + state->chosen_exit_name); + choice = router_get_by_digest(state->chosen_exit_digest); smartlist_free(excludednodes); if(!choice) { log_fn(LOG_WARN,"Our chosen exit %s is no longer in the directory? Discarding this circuit.", - state->chosen_exit); + state->chosen_exit_name); return -1; } } else if(cur_len == 0) { /* picking first node */ @@ -1104,7 +1116,7 @@ onion_extend_cpath(crypt_path_t **head_ptr, cpath_build_state_t sl = smartlist_create(); add_nickname_list_to_smartlist(sl,options.EntryNodes); /* XXX one day, consider picking chosen_exit knowing what's in EntryNodes */ - remove_twins_from_smartlist(sl,router_get_by_nickname(state->chosen_exit)); + remove_twins_from_smartlist(sl,router_get_by_digest(state->chosen_exit_digest)); remove_twins_from_smartlist(sl,router_get_my_routerinfo()); smartlist_subtract(sl,excludednodes); choice = smartlist_choose(sl); @@ -1112,7 +1124,7 @@ onion_extend_cpath(crypt_path_t **head_ptr, cpath_build_state_t if(!choice) { sl = smartlist_create(); router_add_running_routers_to_smartlist(sl); - remove_twins_from_smartlist(sl,router_get_by_nickname(state->chosen_exit)); + remove_twins_from_smartlist(sl,router_get_by_digest(state->chosen_exit_digest)); remove_twins_from_smartlist(sl,router_get_my_routerinfo()); smartlist_subtract(sl,excludednodes); choice = smartlist_choose(sl); @@ -1127,7 +1139,7 @@ onion_extend_cpath(crypt_path_t **head_ptr, cpath_build_state_t log_fn(LOG_DEBUG, "Contemplating intermediate hop: random choice."); sl = smartlist_create(); router_add_running_routers_to_smartlist(sl); - remove_twins_from_smartlist(sl,router_get_by_nickname(state->chosen_exit)); + remove_twins_from_smartlist(sl,router_get_by_digest(state->chosen_exit_digest)); remove_twins_from_smartlist(sl,router_get_my_routerinfo()); for (i = 0, cpath = *head_ptr; i < cur_len; ++i, cpath=cpath->next) { r = router_get_by_digest(cpath->identity_digest); @@ -1145,7 +1157,7 @@ onion_extend_cpath(crypt_path_t **head_ptr, cpath_build_state_t } log_fn(LOG_DEBUG,"Chose router %s for hop %d (exit is %s)", - choice->nickname, cur_len, state->chosen_exit); + choice->nickname, cur_len, state->chosen_exit_name); hop = tor_malloc_zero(sizeof(crypt_path_t)); diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index f1280c4d7..3090e78b3 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -113,7 +113,7 @@ static void circuit_free(circuit_t *circ) { if (circ->p_digest) crypto_free_digest_env(circ->p_digest); if(circ->build_state) { - tor_free(circ->build_state->chosen_exit); + tor_free(circ->build_state->chosen_exit_name); if (circ->build_state->pending_final_cpath) circuit_free_cpath_node(circ->build_state->pending_final_cpath); } @@ -361,8 +361,8 @@ int _circuit_mark_for_close(circuit_t *circ) { tor_assert(circ->state == CIRCUIT_STATE_OPEN); /* treat this like getting a nack from it */ log_fn(LOG_INFO,"Failed intro circ %s to %s (awaiting ack). Removing from descriptor.", - circ->rend_query, circ->build_state->chosen_exit); - rend_client_remove_intro_point(circ->build_state->chosen_exit, circ->rend_query); + circ->rend_query, circ->build_state->chosen_exit_name); + rend_client_remove_intro_point(circ->build_state->chosen_exit_name, circ->rend_query); } if(circ->n_conn) diff --git a/src/or/circuituse.c b/src/or/circuituse.c index 3b9e2e964..9b971f599 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -66,7 +66,7 @@ static int circuit_is_acceptable(circuit_t *circ, * circuit, it's the magical extra bob hop. so just check the nickname * of the one we meant to finish at. */ - exitrouter = router_get_by_nickname(circ->build_state->chosen_exit); + exitrouter = router_get_by_digest(circ->build_state->chosen_exit_digest); if(!exitrouter) { log_fn(LOG_INFO,"Skipping broken circ (exit router vanished)"); @@ -201,12 +201,12 @@ void circuit_expire_building(time_t now) { if(!victim->timestamp_dirty) log_fn(LOG_DEBUG,"Considering %sopen purp %d to %s (circid %d). (clean).", victim->state == CIRCUIT_STATE_OPEN ? "" : "non", - victim->purpose, victim->build_state->chosen_exit, + victim->purpose, victim->build_state->chosen_exit_name, victim->n_circ_id); else log_fn(LOG_DEBUG,"Considering %sopen purp %d to %s (circid %d). %d secs since dirty.", victim->state == CIRCUIT_STATE_OPEN ? "" : "non", - victim->purpose, victim->build_state->chosen_exit, + victim->purpose, victim->build_state->chosen_exit_name, victim->n_circ_id, (int)(now - victim->timestamp_dirty)); } @@ -266,7 +266,7 @@ int circuit_stream_is_being_handled(connection_t *conn) { !circ->marked_for_close && circ->purpose == CIRCUIT_PURPOSE_C_GENERAL && (!circ->timestamp_dirty || circ->timestamp_dirty + options.NewCircuitPeriod < now)) { - exitrouter = router_get_by_nickname(circ->build_state->chosen_exit); + exitrouter = router_get_by_digest(circ->build_state->chosen_exit_digest); if(exitrouter && connection_ap_can_use_exit(conn, exitrouter) != ADDR_POLICY_REJECTED) if(++num >= MIN_CIRCUITS_HANDLING_STREAM) return 1; @@ -305,7 +305,7 @@ void circuit_build_needed_circs(time_t now) { if(options.RunTesting && circ && circ->timestamp_created + TESTING_CIRCUIT_INTERVAL < now) { log_fn(LOG_INFO,"Creating a new testing circuit."); - circuit_launch_new(CIRCUIT_PURPOSE_C_GENERAL, NULL); + circuit_launch_by_identity(CIRCUIT_PURPOSE_C_GENERAL, NULL); } } @@ -318,7 +318,7 @@ void circuit_build_needed_circs(time_t now) { * go ahead and try another. */ if(!circ && circuit_count_building(CIRCUIT_PURPOSE_C_GENERAL) < CIRCUIT_MIN_BUILDING_GENERAL) { - circuit_launch_new(CIRCUIT_PURPOSE_C_GENERAL, NULL); + circuit_launch_by_identity(CIRCUIT_PURPOSE_C_GENERAL, NULL); } /* XXX count idle rendezvous circs and build more */ @@ -565,10 +565,10 @@ void circuit_build_failed(circuit_t *circ) { /* Don't increment failure count, since Alice may have picked * the rendezvous point maliciously */ if (failed_at_last_hop) { - log_fn(LOG_INFO,"Couldn't connect to Alice's chosen rend point %s. Sucks to be Alice.", circ->build_state->chosen_exit); + log_fn(LOG_INFO,"Couldn't connect to Alice's chosen rend point %s. Sucks to be Alice.", circ->build_state->chosen_exit_name); } else { log_fn(LOG_INFO,"Couldn't connect to Alice's chosen rend point %s, because an earlier node failed.", - circ->build_state->chosen_exit); + circ->build_state->chosen_exit_name); rend_service_relaunch_rendezvous(circ); } break; @@ -588,9 +588,8 @@ static int n_circuit_failures = 0; * success. */ #define MAX_CIRCUIT_FAILURES 5 -/** Launch a new circuit and return a pointer to it. Return NULL if you failed. */ -circuit_t *circuit_launch_new(uint8_t purpose, const char *exit_nickname) { - +circuit_t *circuit_launch_by_identity(uint8_t purpose, const char *exit_digest) +{ if (n_circuit_failures > MAX_CIRCUIT_FAILURES) { /* too many failed circs in a row. don't try. */ // log_fn(LOG_INFO,"%d failures so far, not trying.",n_circuit_failures); @@ -598,7 +597,23 @@ circuit_t *circuit_launch_new(uint8_t purpose, const char *exit_nickname) { } /* try a circ. if it fails, circuit_mark_for_close will increment n_circuit_failures */ - return circuit_establish_circuit(purpose, exit_nickname); + return circuit_establish_circuit(purpose, exit_digest); +} + +/** Launch a new circuit and return a pointer to it. Return NULL if you failed. */ +circuit_t *circuit_launch_by_nickname(uint8_t purpose, const char *exit_nickname) +{ + const char *digest = NULL; + + if (exit_nickname) { + routerinfo_t *r = router_get_by_nickname(exit_nickname); + if (!r) { + log_fn(LOG_WARN, "No such OR as '%s'", exit_nickname); + return NULL; + } + digest = r->identity_digest; + } + return circuit_launch_by_identity(purpose, digest); } /** Record another failure at opening a general circuit. When we have @@ -682,7 +697,7 @@ circuit_get_open_circ_or_launch(connection_t *conn, else new_circ_purpose = desired_circuit_purpose; - circ = circuit_launch_new(new_circ_purpose, exitname); + circ = circuit_launch_by_nickname(new_circ_purpose, exitname); tor_free(exitname); if(circ && diff --git a/src/or/connection.c b/src/or/connection.c index 9b7b28495..00ef5ab95 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -712,7 +712,7 @@ int connection_handle_read(connection_t *conn) { conn->state == DIR_CONN_STATE_CONNECTING) { /* it's a directory server and connecting failed: forget about this router */ /* XXX I suspect pollerr may make Windows not get to this point. :( */ - router_mark_as_down(conn->nickname); + router_mark_as_down(conn->identity_digest); } /* There's a read error; kill the connection.*/ connection_close_immediate(conn); /* Don't flush; connection is dead. */ @@ -828,8 +828,9 @@ int connection_handle_write(connection_t *conn) { log_fn(LOG_DEBUG,"in-progress connect failed. Removing."); connection_close_immediate(conn); connection_mark_for_close(conn); - if (conn->nickname) - router_mark_as_down(conn->nickname); + /* Previously we tested conn->nickname; is this right? */ + if (conn->type == CONN_TYPE_OR) + router_mark_as_down(conn->identity_digest); return -1; } else { return 0; /* no change, see if next time is better */ diff --git a/src/or/connection_or.c b/src/or/connection_or.c index bc5cd70c4..667a82d92 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -304,6 +304,8 @@ connection_tls_finish_handshake(connection_t *conn) { } log_fn(LOG_DEBUG,"The router's cert is valid."); + /* XXXX008 This isn't right; fix this one we launch by identity digest + * XXXX008 rather than by nickname */ if (conn->nickname) { /* I initiated this connection. */ if (strcasecmp(conn->nickname, nickname)) { diff --git a/src/or/directory.c b/src/or/directory.c index 0d3ffa072..432c704f7 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -149,7 +149,7 @@ directory_initiate_command(routerinfo_t *router, uint8_t purpose, /* then we want to connect directly */ switch(connection_connect(conn, conn->address, conn->addr, conn->port)) { case -1: - router_mark_as_down(conn->nickname); /* don't try him again */ + router_mark_as_down(conn->identity_digest); /* don't try him again */ connection_free(conn); return; case 1: diff --git a/src/or/or.h b/src/or/or.h index 6011b1bd7..b13a0af2c 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -674,7 +674,9 @@ typedef struct { /** Intended length of the final circuit. */ int desired_path_len; /** Nickname of planned exit node. */ - char *chosen_exit; + char *chosen_exit_name; + /** Identity of planned exit node. */ + char chosen_exit_digest[DIGEST_LEN]; /** The crypt_path_t to append after rendezvous: used for rendezvous. */ struct crypt_path_t *pending_final_cpath; /** How many times has building a circuit for this task failed? */ @@ -919,7 +921,7 @@ void circuit_log_path(int severity, circuit_t *circ); void circuit_rep_hist_note_result(circuit_t *circ); void circuit_dump_by_conn(connection_t *conn, int severity); circuit_t *circuit_establish_circuit(uint8_t purpose, - const char *exit_nickname); + const char *exit_digest); void circuit_n_conn_done(connection_t *or_conn, int success); int circuit_send_next_onion_skin(circuit_t *circ); int circuit_extend(cell_t *cell, circuit_t *circ); @@ -968,7 +970,8 @@ void circuit_detach_stream(circuit_t *circ, connection_t *conn); void circuit_about_to_close_connection(connection_t *conn); void circuit_has_opened(circuit_t *circ); void circuit_build_failed(circuit_t *circ); -circuit_t *circuit_launch_new(uint8_t purpose, const char *exit_nickname); +circuit_t *circuit_launch_by_nickname(uint8_t purpose, const char *exit_nickname); +circuit_t *circuit_launch_by_identity(uint8_t purpose, const char *exit_digest); void circuit_reset_failure_count(void); int connection_ap_handshake_attach_circuit(connection_t *conn); @@ -1346,6 +1349,7 @@ routerinfo_t *router_pick_directory_server(void); struct smartlist_t; void add_nickname_list_to_smartlist(struct smartlist_t *sl, const char *list); void router_add_running_routers_to_smartlist(struct smartlist_t *sl); +int router_nickname_matches(routerinfo_t *router, const char *nickname); routerinfo_t *router_choose_random_node(char *preferred, char *excluded, struct smartlist_t *excludedsmartlist); routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port); @@ -1357,7 +1361,7 @@ void routerlist_free(routerlist_t *routerlist); void routerlist_clear_trusted_directories(void); void routerinfo_free(routerinfo_t *router); routerinfo_t *routerinfo_copy(const routerinfo_t *router); -void router_mark_as_down(char *nickname); +void router_mark_as_down(const char *digest); void routerlist_remove_old_routers(void); int router_load_routerlist_from_file(char *routerfile, int trusted); int router_load_routerlist_from_string(const char *s, int trusted); diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 081384995..aaaf86503 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -90,7 +90,7 @@ rend_client_send_introduction(circuit_t *introcirc, circuit_t *rendcirc) { } /* write the remaining items into tmp */ - strncpy(tmp, rendcirc->build_state->chosen_exit, (MAX_NICKNAME_LEN+1)); /* nul pads */ + strncpy(tmp, rendcirc->build_state->chosen_exit_name, (MAX_NICKNAME_LEN+1)); /* nul pads */ memcpy(tmp+MAX_NICKNAME_LEN+1, rendcirc->rend_cookie, REND_COOKIE_LEN); if (crypto_dh_get_public(cpath->handshake_state, tmp+MAX_NICKNAME_LEN+1+REND_COOKIE_LEN, @@ -164,7 +164,7 @@ rend_client_introduction_acked(circuit_t *circ, return -1; } - tor_assert(circ->build_state->chosen_exit); + tor_assert(circ->build_state->chosen_exit_name); if (request_len == 0) { /* It's an ACK; the introduction point relayed our introduction request. */ @@ -187,14 +187,15 @@ rend_client_introduction_acked(circuit_t *circ, * points. If any remain, extend to a new one and try again. * If none remain, refetch the service descriptor. */ - if(rend_client_remove_intro_point(circ->build_state->chosen_exit, + if(rend_client_remove_intro_point(circ->build_state->chosen_exit_name, circ->rend_query) > 0) { /* There are introduction points left. re-extend the circuit to * another intro point and try again. */ + routerinfo_t *r; nickname = rend_client_get_random_intro(circ->rend_query); tor_assert(nickname); - log_fn(LOG_INFO,"Got nack for %s from %s, extending to %s.", circ->rend_query, circ->build_state->chosen_exit, nickname); - if (!router_get_by_nickname(nickname)) { + log_fn(LOG_INFO,"Got nack for %s from %s, extending to %s.", circ->rend_query, circ->build_state->chosen_exit_name, nickname); + if (!(r = router_get_by_nickname(nickname))) { log_fn(LOG_WARN, "Advertised intro point '%s' for %s is not known. Closing.", nickname, circ->rend_query); circuit_mark_for_close(circ); @@ -203,8 +204,9 @@ rend_client_introduction_acked(circuit_t *circ, log_fn(LOG_INFO, "Chose new intro point %s for %s (circ %d)", nickname, circ->rend_query, circ->n_circ_id); circ->state = CIRCUIT_STATE_BUILDING; - tor_free(circ->build_state->chosen_exit); - circ->build_state->chosen_exit = tor_strdup(nickname); + tor_free(circ->build_state->chosen_exit_name); + circ->build_state->chosen_exit_name = tor_strdup(nickname); + memcpy(circ->build_state->chosen_exit_digest, r->identity_digest, DIGEST_LEN); ++circ->build_state->desired_path_len; if (circuit_send_next_onion_skin(circ)<0) { log_fn(LOG_WARN, "Couldn't extend circuit to new intro point."); diff --git a/src/or/rendservice.c b/src/or/rendservice.c index d10d47c82..4e3323e90 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -437,7 +437,7 @@ rend_service_introduce(circuit_t *circuit, const char *request, int request_len) /* Launch a circuit to alice's chosen rendezvous point. */ - launched = circuit_launch_new(CIRCUIT_PURPOSE_S_CONNECT_REND, rp_nickname); + launched = circuit_launch_by_nickname(CIRCUIT_PURPOSE_S_CONNECT_REND, rp_nickname); log_fn(LOG_INFO, "Accepted intro; launching circuit to '%s' (cookie %s) for service %s", rp_nickname, hexcookie, serviceid); @@ -487,18 +487,18 @@ rend_service_relaunch_rendezvous(circuit_t *oldcirc) if (!oldcirc->build_state || oldcirc->build_state->failure_count > MAX_REND_FAILURES) { log_fn(LOG_INFO,"Attempt to build circuit to %s for rendezvous has failed too many times; giving up.", - oldcirc->build_state->chosen_exit); + oldcirc->build_state->chosen_exit_name); return; } log_fn(LOG_INFO,"Reattempting rendezvous circuit to %s", - oldcirc->build_state->chosen_exit); + oldcirc->build_state->chosen_exit_name); - newcirc = circuit_launch_new(CIRCUIT_PURPOSE_S_CONNECT_REND, - oldcirc->build_state->chosen_exit); + newcirc = circuit_launch_by_nickname(CIRCUIT_PURPOSE_S_CONNECT_REND, + oldcirc->build_state->chosen_exit_name); if (!newcirc) { log_fn(LOG_WARN,"Couldn't relaunch rendezvous circuit to %s", - oldcirc->build_state->chosen_exit); + oldcirc->build_state->chosen_exit_name); return; } oldstate = oldcirc->build_state; @@ -525,7 +525,7 @@ rend_service_launch_establish_intro(rend_service_t *service, const char *nicknam nickname, service->service_id); ++service->n_intro_circuits_launched; - launched = circuit_launch_new(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO, nickname); + launched = circuit_launch_by_nickname(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO, nickname); if (!launched) { log_fn(LOG_WARN, "Can't launch circuit to establish introduction at '%s'", nickname); @@ -715,8 +715,8 @@ find_intro_circuit(routerinfo_t *router, const char *pk_digest) while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest, CIRCUIT_PURPOSE_S_INTRO))) { tor_assert(circ->cpath); - if (circ->build_state->chosen_exit && - !strcasecmp(circ->build_state->chosen_exit, router->nickname)) { + if (circ->build_state->chosen_exit_name && + !strcasecmp(circ->build_state->chosen_exit_name, router->nickname)) { return circ; } } @@ -725,8 +725,8 @@ find_intro_circuit(routerinfo_t *router, const char *pk_digest) while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest, CIRCUIT_PURPOSE_S_ESTABLISH_INTRO))) { tor_assert(circ->cpath); - if (circ->build_state->chosen_exit && - !strcasecmp(circ->build_state->chosen_exit, router->nickname)) { + if (circ->build_state->chosen_exit_name && + !strcasecmp(circ->build_state->chosen_exit_name, router->nickname)) { return circ; } } diff --git a/src/or/router.c b/src/or/router.c index 3a9ee99de..178687309 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -394,6 +394,7 @@ int router_compare_to_my_exit_policy(connection_t *conn) int router_is_me(routerinfo_t *router) { tor_assert(router); + /* XXXX008 should compare identity instead? */ return options.Nickname && !strcasecmp(router->nickname, options.Nickname); } diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 9416aafd2..1c9d83756 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -207,19 +207,46 @@ routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port) { return NULL; } +/* DOCDOC */ +static INLINE int router_hex_digest_matches(routerinfo_t *router, + const char *hexdigest) +{ + char digest[DIGEST_LEN]; + tor_assert(hexdigest); + if (hexdigest[0] == '$') + ++hexdigest; + + if (base16_decode(digest, DIGEST_LEN, hexdigest, HEX_DIGEST_LEN)<0) + return 0; + else + return (!memcmp(digest, router->identity_digest, DIGEST_LEN)); +} + +/* DOCDOC */ +int router_nickname_matches(routerinfo_t *router, const char *nickname) +{ + if (nickname[0]!='$' && !strcasecmp(router->nickname, nickname)) + return 1; + else + return router_hex_digest_matches(router, nickname); +} + /** Return the router in our routerlist whose (case-insensitive) * nickname or (case-sensitive) hexadecimal key digest is * nickname. Return NULL if no such router is known. */ routerinfo_t *router_get_by_nickname(const char *nickname) { - int i, maybedigest; + int i, maybedigest, mustbedigest; routerinfo_t *router; char digest[DIGEST_LEN]; tor_assert(nickname); if (!routerlist) return NULL; + if (nickname[0] == '$') + return router_get_by_hexdigest(nickname); + maybedigest = (strlen(nickname) == HEX_DIGEST_LEN) && (base16_decode(digest,DIGEST_LEN,nickname,HEX_DIGEST_LEN) == 0); @@ -242,6 +269,8 @@ routerinfo_t *router_get_by_hexdigest(const char *hexdigest) { tor_assert(hexdigest); if (!routerlist) return NULL; + if (hexdigest[0]=='$') + ++hexdigest; if (strlen(hexdigest) != HEX_DIGEST_LEN || base16_decode(digest,DIGEST_LEN,hexdigest,HEX_DIGEST_LEN) < 0) return NULL; @@ -326,10 +355,10 @@ void routerlist_free(routerlist_t *rl) } /** Mark the router named nickname as non-running in our routerlist. */ -void router_mark_as_down(char *nickname) { +void router_mark_as_down(const char *digest) { routerinfo_t *router; - tor_assert(nickname); - router = router_get_by_nickname(nickname); + tor_assert(digest); + router = router_get_by_digest(digest); if(!router) /* we don't seem to know about him in the first place */ return; log_fn(LOG_DEBUG,"Marking %s as down.",router->nickname); @@ -350,6 +379,7 @@ int router_add_to_routerlist(routerinfo_t *router) { */ for (i = 0; i < smartlist_len(routerlist->routers); ++i) { r = smartlist_get(routerlist->routers, i); + /* XXXX008 should just compare digests instead. */ if (!strcasecmp(router->nickname, r->nickname)) { if (!crypto_pk_cmp_keys(router->identity_pkey, r->identity_pkey)) { if (router->published_on > r->published_on) { @@ -377,6 +407,8 @@ int router_add_to_routerlist(routerinfo_t *router) { return -1; } } else { + /* XXXX008 It's okay to have two keys for a nickname as soon as + * all the 007 clients are dead. */ log_fn(LOG_WARN, "Identity key mismatch for router '%s'", router->nickname); routerinfo_free(router); @@ -698,13 +730,16 @@ void routerlist_update_from_runningrouters(routerlist_t *list, router = smartlist_get(list->routers, i); for (j=0; jrunning_routers, j); - if (!strcasecmp(name, router->nickname)) { - router->is_running = 1; - break; - } - if (*name == '!' && strcasecmp(name+1, router->nickname)) { - router->is_running = 0; - break; + if (*name != '!') { + if (router_nickname_matches(router, name)) { + router->is_running = 1; + break; + } + } else { /* *name == '!' */ + if (router_nickname_matches(router, name)) { + router->is_running = 0; + break; + } } } } diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 90657e6fa..ccf77c9f7 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -539,7 +539,7 @@ static int check_directory_signature(const char *digest, int router_parse_list_from_string(const char **s, routerlist_t **dest, int n_good_nicknames, - const char **good_nickname_lst) + const char **good_nickname_list) { routerinfo_t *router; smartlist_t *routers; @@ -574,7 +574,7 @@ router_parse_list_from_string(const char **s, routerlist_t **dest, if (n_good_nicknames>=0) { router->is_running = 0; for (i = 0; i < n_good_nicknames; ++i) { - if (0==strcasecmp(good_nickname_lst[i], router->nickname)) { + if (router_nickname_matches(router, good_nickname_list[i])) { router->is_running = 1; break; } diff --git a/src/or/test.c b/src/or/test.c index 5ee586611..4dc914589 100644 --- a/src/or/test.c +++ b/src/or/test.c @@ -420,6 +420,17 @@ test_crypto() test_eq(i,0); test_streq(data2, "772w2rfobvomsywe"); + /* Base16 tests */ + strcpy(data1, "6chrs\xff"); + i = base16_encode(data2, 13, data1, 6); + test_eq(i,0); + test_streq(data2, "3663687273FF"); + + strcpy(data1, "f0d678affc000100"); + i = base16_decode(data2, 8, data1, 16); + test_eq(i,0); + test_memeq(data2, "\xf0\xd6\x78\xaf\xfc\x00\x01\x00",8); + free(data1); free(data2); free(data3); -- cgit v1.2.3