mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
fix a race condition in 008pre2: don't try to extend onto a connection
that's still handshaking. for servers in clique mode, require the conn to be open before you'll choose it for your path. svn:r2198
This commit is contained in:
+17
-12
@@ -443,8 +443,6 @@ int circuit_extend(cell_t *cell, circuit_t *circ) {
|
||||
relay_header_unpack(&rh, cell->payload);
|
||||
|
||||
if (rh.length == 4+2+ONIONSKIN_CHALLENGE_LEN) {
|
||||
/* Once this format is no longer supported, nobody will use
|
||||
* connection_*_get_by_addr_port. */
|
||||
old_format = 1;
|
||||
} else if (rh.length == 4+2+ONIONSKIN_CHALLENGE_LEN+DIGEST_LEN) {
|
||||
old_format = 0;
|
||||
@@ -457,7 +455,7 @@ int circuit_extend(cell_t *cell, circuit_t *circ) {
|
||||
circ->n_port = ntohs(get_uint16(cell->payload+RELAY_HEADER_SIZE+4));
|
||||
|
||||
if (old_format) {
|
||||
n_conn = connection_twin_get_by_addr_port(circ->n_addr,circ->n_port);
|
||||
n_conn = connection_exact_get_by_addr_port(circ->n_addr,circ->n_port);
|
||||
onionskin = cell->payload+RELAY_HEADER_SIZE+4+2;
|
||||
} else {
|
||||
onionskin = cell->payload+RELAY_HEADER_SIZE+4+2;
|
||||
@@ -465,7 +463,7 @@ int circuit_extend(cell_t *cell, circuit_t *circ) {
|
||||
n_conn = connection_get_by_identity_digest(id_digest, CONN_TYPE_OR);
|
||||
}
|
||||
|
||||
if(!n_conn) { /* we should try to open a connection */
|
||||
if(!n_conn || n_conn->state != OR_CONN_STATE_OPEN) {
|
||||
/* Note that this will close circuits where the onion has the same
|
||||
* router twice in a row in the path. I think that's ok.
|
||||
*/
|
||||
@@ -478,7 +476,7 @@ int circuit_extend(cell_t *cell, circuit_t *circ) {
|
||||
if (old_format) {
|
||||
router = router_get_by_addr_port(circ->n_addr, circ->n_port);
|
||||
if(!router) {
|
||||
log_fn(LOG_INFO,"Next hop is an unknown router. Closing.");
|
||||
log_fn(LOG_WARN,"Next hop is an unknown router. Closing.");
|
||||
return -1;
|
||||
}
|
||||
id_digest = router->identity_digest;
|
||||
@@ -499,19 +497,26 @@ int circuit_extend(cell_t *cell, circuit_t *circ) {
|
||||
/* imprint the circuit with its future n_conn->id */
|
||||
memcpy(circ->n_conn_id_digest, id_digest, DIGEST_LEN);
|
||||
|
||||
n_conn = connection_or_connect(circ->n_addr, circ->n_port, id_digest);
|
||||
if(!n_conn) {
|
||||
log_fn(LOG_INFO,"Launching n_conn failed. Closing.");
|
||||
return -1;
|
||||
if(n_conn) {
|
||||
circ->n_addr = n_conn->addr;
|
||||
circ->n_port = n_conn->port;
|
||||
} else {
|
||||
/* we should try to open a connection */
|
||||
n_conn = connection_or_connect(circ->n_addr, circ->n_port, id_digest);
|
||||
if(!n_conn) {
|
||||
log_fn(LOG_INFO,"Launching n_conn failed. Closing.");
|
||||
return -1;
|
||||
}
|
||||
log_fn(LOG_DEBUG,"connecting in progress (or finished). Good.");
|
||||
}
|
||||
log_fn(LOG_DEBUG,"connecting in progress (or finished). Good.");
|
||||
/* return success. The onion/circuit/etc will be taken care of automatically
|
||||
* (may already have been) whenever n_conn reaches OR_CONN_STATE_OPEN.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
circ->n_addr = n_conn->addr; /* these are different if we found a twin instead */
|
||||
/* these may be different if the router connected to us from elsewhere */
|
||||
circ->n_addr = n_conn->addr;
|
||||
circ->n_port = n_conn->port;
|
||||
|
||||
circ->n_conn = n_conn;
|
||||
@@ -1022,7 +1027,7 @@ static int count_acceptable_routers(smartlist_t *routers) {
|
||||
if(clique_mode()) {
|
||||
conn = connection_get_by_identity_digest(r->identity_digest,
|
||||
CONN_TYPE_OR);
|
||||
if(!conn || conn->type != CONN_TYPE_OR || conn->state != OR_CONN_STATE_OPEN) {
|
||||
if(!conn || conn->state != OR_CONN_STATE_OPEN) {
|
||||
log_fn(LOG_DEBUG,"Nope, %d is not connected.",i);
|
||||
goto next_i_loop;
|
||||
}
|
||||
|
||||
@@ -978,45 +978,6 @@ connection_t *connection_exact_get_by_addr_port(uint32_t addr, uint16_t port) {
|
||||
return best;
|
||||
}
|
||||
|
||||
/** Find a connection to the router described by addr and port,
|
||||
* or alternately any router with the same identity key.
|
||||
* This connection <em>must</em> be in an "open" state.
|
||||
* If not, return NULL.
|
||||
*/
|
||||
/* XXX this twin thing is busted, now that we're rotating onion
|
||||
* keys. abandon/patch? */
|
||||
connection_t *connection_twin_get_by_addr_port(uint32_t addr, uint16_t port) {
|
||||
int i, n;
|
||||
connection_t *conn;
|
||||
routerinfo_t *router;
|
||||
connection_t **carray;
|
||||
|
||||
/* first check if it's there exactly */
|
||||
conn = connection_exact_get_by_addr_port(addr,port);
|
||||
if(conn && connection_state_is_open(conn)) {
|
||||
log(LOG_DEBUG,"connection_twin_get_by_addr_port(): Found exact match.");
|
||||
return conn;
|
||||
}
|
||||
|
||||
/* now check if any of the other open connections are a twin for this one */
|
||||
|
||||
router = router_get_by_addr_port(addr,port);
|
||||
if(!router)
|
||||
return NULL;
|
||||
|
||||
get_connection_array(&carray,&n);
|
||||
for(i=0;i<n;i++) {
|
||||
conn = carray[i];
|
||||
tor_assert(conn);
|
||||
if(connection_state_is_open(conn) &&
|
||||
!crypto_pk_cmp_keys(conn->identity_pkey, router->identity_pkey)) {
|
||||
log(LOG_DEBUG,"connection_twin_get_by_addr_port(): Found twin (%s).",conn->address);
|
||||
return conn;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
connection_t *connection_get_by_identity_digest(const char *digest, int type)
|
||||
{
|
||||
int i, n;
|
||||
|
||||
@@ -168,8 +168,11 @@ connection_t *connection_or_connect(uint32_t addr, uint16_t port,
|
||||
/* this function should never be called if we're already connected to
|
||||
* id_digest, but check first to be sure */
|
||||
conn = connection_get_by_identity_digest(id_digest, CONN_TYPE_OR);
|
||||
if(conn)
|
||||
if(conn) {
|
||||
tor_assert(conn->nickname);
|
||||
log_fn(LOG_WARN,"Asked me to connect to %s, but there's already a connection.", conn->nickname);
|
||||
return conn;
|
||||
}
|
||||
|
||||
conn = connection_new(CONN_TYPE_OR);
|
||||
|
||||
|
||||
@@ -1061,7 +1061,6 @@ int connection_outbuf_too_full(connection_t *conn);
|
||||
int connection_handle_write(connection_t *conn);
|
||||
void connection_write_to_buf(const char *string, int len, connection_t *conn);
|
||||
|
||||
connection_t *connection_twin_get_by_addr_port(uint32_t addr, uint16_t port);
|
||||
connection_t *connection_exact_get_by_addr_port(uint32_t addr, uint16_t port);
|
||||
connection_t *connection_get_by_identity_digest(const char *digest, int type);
|
||||
|
||||
|
||||
@@ -192,11 +192,17 @@ void router_add_running_routers_to_smartlist(smartlist_t *sl) {
|
||||
for(i=0;i<smartlist_len(routerlist->routers);i++) {
|
||||
router = smartlist_get(routerlist->routers, i);
|
||||
/* XXX008 for now, only choose verified routers */
|
||||
if(router->is_running && router->is_verified &&
|
||||
(!clique_mode() ||
|
||||
connection_get_by_identity_digest(router->identity_digest,
|
||||
CONN_TYPE_OR)))
|
||||
smartlist_add(sl, router);
|
||||
if(router->is_running && router->is_verified) {
|
||||
if(!clique_mode()) {
|
||||
smartlist_add(sl, router);
|
||||
} else {
|
||||
connection_t *conn =
|
||||
connection_get_by_identity_digest(router->identity_digest,
|
||||
CONN_TYPE_OR);
|
||||
if(conn && conn->state == OR_CONN_STATE_OPEN)
|
||||
smartlist_add(sl, router);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1308,7 +1308,7 @@ static int router_get_hash_impl(const char *s, char *digest,
|
||||
return -1;
|
||||
}
|
||||
if (start != s && *(start-1) != '\n') {
|
||||
log_fn(LOG_WARN, "first occurance of \"%s\" is not at the start of a line",
|
||||
log_fn(LOG_WARN, "first occurrence of \"%s\" is not at the start of a line",
|
||||
start_str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user