diff options
-rw-r--r-- | src/or/circuitlist.c | 44 | ||||
-rw-r--r-- | src/or/circuitlist.h | 2 | ||||
-rw-r--r-- | src/or/rendmid.c | 43 |
3 files changed, 53 insertions, 36 deletions
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index 947489636..68c9cd53c 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -1230,21 +1230,23 @@ circuit_get_next_by_pk_and_purpose(origin_circuit_t *start, return NULL; } -/** Return the first OR circuit in the global list whose purpose is - * <b>purpose</b>, and whose rend_token is the <b>len</b>-byte - * <b>token</b>. */ -static or_circuit_t * -circuit_get_by_rend_token_and_purpose(uint8_t purpose, const char *token, - size_t len) +/** Return the circuits waiting for intro cells of the given digest. + * + */ +smartlist_t * +circuits_get_intro_point(const char *digest) { + smartlist_t *circuits = smartlist_new(); + circuit_t *circ; TOR_LIST_FOREACH(circ, &global_circuitlist, head) { if (! circ->marked_for_close && - circ->purpose == purpose && - tor_memeq(TO_OR_CIRCUIT(circ)->rend_token, token, len)) - return TO_OR_CIRCUIT(circ); + circ->purpose == CIRCUIT_PURPOSE_INTRO_POINT && + tor_memeq(TO_OR_CIRCUIT(circ)->rend_token, digest, DIGEST_LEN)) + smartlist_add(circuits, TO_OR_CIRCUIT(circ)); } - return NULL; + + return circuits; } /** Return the circuit waiting for a rendezvous with the provided cookie. @@ -1253,20 +1255,14 @@ circuit_get_by_rend_token_and_purpose(uint8_t purpose, const char *token, or_circuit_t * circuit_get_rendezvous(const char *cookie) { - return circuit_get_by_rend_token_and_purpose( - CIRCUIT_PURPOSE_REND_POINT_WAITING, - cookie, REND_COOKIE_LEN); -} - -/** Return the circuit waiting for intro cells of the given digest. - * Return NULL if no such circuit is found. - */ -or_circuit_t * -circuit_get_intro_point(const char *digest) -{ - return circuit_get_by_rend_token_and_purpose( - CIRCUIT_PURPOSE_INTRO_POINT, digest, - DIGEST_LEN); + circuit_t *circ; + TOR_LIST_FOREACH(circ, &global_circuitlist, head) { + if (! circ->marked_for_close && + circ->purpose == CIRCUIT_PURPOSE_REND_POINT_WAITING && + tor_memeq(TO_OR_CIRCUIT(circ)->rend_token, cookie, REND_COOKIE_LEN)) + return TO_OR_CIRCUIT(circ); + } + return NULL; } /** Return a circuit that is open, is CIRCUIT_PURPOSE_C_GENERAL, diff --git a/src/or/circuitlist.h b/src/or/circuitlist.h index 1c8cf7de2..bc7dc1e84 100644 --- a/src/or/circuitlist.h +++ b/src/or/circuitlist.h @@ -48,7 +48,7 @@ origin_circuit_t *circuit_get_ready_rend_circ_by_rend_data( origin_circuit_t *circuit_get_next_by_pk_and_purpose(origin_circuit_t *start, const char *digest, uint8_t purpose); or_circuit_t *circuit_get_rendezvous(const char *cookie); -or_circuit_t *circuit_get_intro_point(const char *digest); +smartlist_t *circuits_get_intro_point(const char *digest); origin_circuit_t *circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info, int flags); void circuit_mark_all_unused_circs(void); diff --git a/src/or/rendmid.c b/src/or/rendmid.c index 8741397fc..e7a7849db 100644 --- a/src/or/rendmid.c +++ b/src/or/rendmid.c @@ -27,7 +27,6 @@ rend_mid_establish_intro(or_circuit_t *circ, const uint8_t *request, char expected_digest[DIGEST_LEN]; char pk_digest[DIGEST_LEN]; size_t asn1len; - or_circuit_t *c; char serviceid[REND_SERVICE_ID_LEN_BASE32+1]; int reason = END_CIRC_REASON_INTERNAL; @@ -93,14 +92,22 @@ rend_mid_establish_intro(or_circuit_t *circ, const uint8_t *request, pk_digest, REND_SERVICE_ID_LEN); if (!get_options()->IntroPointAcceptMutipleConnections) { - /* Close any other intro circuits with the same pk. */ - c = NULL; - while ((c = circuit_get_intro_point(pk_digest))) { - log_info(LD_REND, "Replacing old circuit for service %s", - safe_str(serviceid)); - circuit_mark_for_close(TO_CIRCUIT(c), END_CIRC_REASON_FINISHED); - /* Now it's marked, and it won't be returned next time. */ - } + log_info(LD_REND, "Checking for existing circuits to remove %s as " + "IntroPointAcceptMutipleConnections is not set", + safe_str(serviceid)); + + smartlist_t *circuits = circuits_get_intro_point(pk_digest); + + /* Close any other intro circuits with the same pk. */ + SMARTLIST_FOREACH_BEGIN(circuits, or_circuit_t *, circ) { + log_info(LD_REND, "Replacing old circuit for service %s", + safe_str(serviceid)); + circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_FINISHED); + } SMARTLIST_FOREACH_END(circ); + } else { + log_info(LD_REND, "Not removing existing circuits for %s as " + "IntroPointAcceptMutipleConnections is set", + safe_str(serviceid)); } /* Acknowledge the request. */ @@ -167,8 +174,13 @@ rend_mid_introduce(or_circuit_t *circ, const uint8_t *request, (char*)request, REND_SERVICE_ID_LEN); /* The first 20 bytes are all we look at: they have a hash of Bob's PK. */ - intro_circ = circuit_get_intro_point((char*)request); - if (!intro_circ) { + smartlist_t *intro_circuits = circuits_get_intro_point((char*)request); + + log_info(LD_REND, + "found %i possible introduction circuits for service %s", + smartlist_len(intro_circuits), safe_str(serviceid)); + + if (smartlist_len(intro_circuits) == 0) { log_info(LD_REND, "No intro circ found for INTRODUCE1 cell (%s) from circuit %u; " "responding with nack.", @@ -176,6 +188,15 @@ rend_mid_introduce(or_circuit_t *circ, const uint8_t *request, goto err; } + // Need to select which circuit to use + int circ_selection = crypto_rand_int(smartlist_len(intro_circuits)); + + log_info(LD_REND, + "selected circuit %i for service %s", + circ_selection, safe_str(serviceid)); + + intro_circ = smartlist_get(intro_circuits, circ_selection); + log_info(LD_REND, "Sending introduction request for service %s " "from circ %u to circ %u", |