diff options
Diffstat (limited to 'src/or/rendclient.c')
-rw-r--r-- | src/or/rendclient.c | 60 |
1 files changed, 50 insertions, 10 deletions
diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 88241a4b2c..61e3b917e3 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -1,5 +1,5 @@ /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -66,6 +66,14 @@ rend_client_send_establish_rendezvous(origin_circuit_t *circ) circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL); return -1; } + + /* Set timestamp_dirty, because circuit_expire_building expects it, + * and the rend cookie also means we've used the circ. */ + circ->base_.timestamp_dirty = time(NULL); + + /* We've attempted to use this circuit. Probe it if we fail */ + pathbias_count_use_attempt(circ); + if (relay_send_command_from_edge(0, TO_CIRCUIT(circ), RELAY_COMMAND_ESTABLISH_RENDEZVOUS, circ->rend_data->rend_cookie, @@ -100,6 +108,7 @@ rend_client_reextend_intro_circuit(origin_circuit_t *circ) circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL); return -1; } + // XXX: should we not re-extend if hs_circ_has_timed_out? if (circ->remaining_relay_early_cells) { log_info(LD_REND, "Re-extending circ %d, this time to %s.", @@ -206,12 +215,12 @@ rend_client_send_introduction(origin_circuit_t *introcirc, cpath = rendcirc->build_state->pending_final_cpath = tor_malloc_zero(sizeof(crypt_path_t)); cpath->magic = CRYPT_PATH_MAGIC; - if (!(cpath->dh_handshake_state = crypto_dh_new(DH_TYPE_REND))) { + if (!(cpath->rend_dh_handshake_state = crypto_dh_new(DH_TYPE_REND))) { log_warn(LD_BUG, "Internal error: couldn't allocate DH."); status = -2; goto perm_err; } - if (crypto_dh_generate_public(cpath->dh_handshake_state)<0) { + if (crypto_dh_generate_public(cpath->rend_dh_handshake_state)<0) { log_warn(LD_BUG, "Internal error: couldn't generate g^x."); status = -2; goto perm_err; @@ -261,7 +270,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc, dh_offset = MAX_NICKNAME_LEN+1+REND_COOKIE_LEN; } - if (crypto_dh_get_public(cpath->dh_handshake_state, tmp+dh_offset, + if (crypto_dh_get_public(cpath->rend_dh_handshake_state, tmp+dh_offset, DH_KEY_LEN)<0) { log_warn(LD_BUG, "Internal error: couldn't extract g^x."); status = -2; @@ -310,6 +319,8 @@ rend_client_send_introduction(origin_circuit_t *introcirc, * state. */ introcirc->base_.timestamp_dirty = time(NULL); + pathbias_count_use_attempt(introcirc); + goto cleanup; perm_err: @@ -338,6 +349,32 @@ rend_client_rendcirc_has_opened(origin_circuit_t *circ) } } +/** + * Called to close other intro circuits we launched in parallel + * due to timeout. + */ +static void +rend_client_close_other_intros(const char *onion_address) +{ + circuit_t *c; + /* abort parallel intro circs, if any */ + for (c = circuit_get_global_list_(); c; c = c->next) { + if ((c->purpose == CIRCUIT_PURPOSE_C_INTRODUCING || + c->purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) && + !c->marked_for_close && CIRCUIT_IS_ORIGIN(c)) { + origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(c); + if (oc->rend_data && + !rend_cmp_service_ids(onion_address, + oc->rend_data->onion_address)) { + log_info(LD_REND|LD_CIRC, "Closing introduction circuit %d that we " + "built in parallel (Purpose %d).", oc->global_identifier, + c->purpose); + circuit_mark_for_close(c, END_CIRC_REASON_TIMEOUT); + } + } + } +} + /** Called when get an ACK or a NAK for a REND_INTRODUCE1 cell. */ int @@ -363,7 +400,7 @@ rend_client_introduction_acked(origin_circuit_t *circ, /* For path bias: This circuit was used successfully. Valid * nacks and acks count. */ - circ->path_state = PATH_STATE_USE_SUCCEEDED; + pathbias_mark_use_success(circ); if (request_len == 0) { /* It's an ACK; the introduction point relayed our introduction request. */ @@ -389,6 +426,9 @@ rend_client_introduction_acked(origin_circuit_t *circ, circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_C_INTRODUCE_ACKED); circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_FINISHED); + + /* close any other intros launched in parallel */ + rend_client_close_other_intros(circ->rend_data->onion_address); } else { /* It's a NAK; the introduction point didn't relay our request. */ circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_C_INTRODUCING); @@ -867,7 +907,7 @@ rend_client_rendezvous_acked(origin_circuit_t *circ, const uint8_t *request, * Waiting any longer opens us up to attacks from Bob. He could induce * Alice to attempt to connect to his hidden service and never reply * to her rend requests */ - circ->path_state = PATH_STATE_USE_SUCCEEDED; + pathbias_mark_use_success(circ); /* XXXX This is a pretty brute-force approach. It'd be better to * attach only the connections that are waiting on this circuit, rather @@ -907,9 +947,9 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const uint8_t *request, tor_assert(circ->build_state); tor_assert(circ->build_state->pending_final_cpath); hop = circ->build_state->pending_final_cpath; - tor_assert(hop->dh_handshake_state); + tor_assert(hop->rend_dh_handshake_state); if (crypto_dh_compute_secret(LOG_PROTOCOL_WARN, - hop->dh_handshake_state, (char*)request, + hop->rend_dh_handshake_state, (char*)request, DH_KEY_LEN, keys, DIGEST_LEN+CPATH_KEY_MATERIAL_LEN)<0) { log_warn(LD_GENERAL, "Couldn't complete DH handshake."); @@ -925,8 +965,8 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const uint8_t *request, goto err; } - crypto_dh_free(hop->dh_handshake_state); - hop->dh_handshake_state = NULL; + crypto_dh_free(hop->rend_dh_handshake_state); + hop->rend_dh_handshake_state = NULL; /* All is well. Extend the circuit. */ circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_C_REND_JOINED); |