From 440e48ddf27094e48c401c68c9014eca43b6867e Mon Sep 17 00:00:00 2001 From: Robert Ransom Date: Wed, 20 Apr 2011 02:27:58 -0700 Subject: Forget all rendezvous client state on SIGNAL NEWNYM --- src/or/main.c | 2 ++ src/or/or.h | 2 ++ src/or/rendclient.c | 37 +++++++++++++++++++++++++++++++++++++ src/or/rendcommon.c | 10 ++++++++++ 4 files changed, 51 insertions(+) (limited to 'src/or') diff --git a/src/or/main.c b/src/or/main.c index 96b7b456ea..e44fd49462 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -785,6 +785,8 @@ signewnym_impl(time_t now) { circuit_expire_all_dirty_circs(); addressmap_clear_transient(); + rend_cache_purge(); + rend_client_cancel_descriptor_fetches(); time_of_last_signewnym = now; signewnym_is_pending = 0; } diff --git a/src/or/or.h b/src/or/or.h index 57e091e9eb..897ad32a43 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -4039,6 +4039,7 @@ int rend_client_introduction_acked(origin_circuit_t *circ, size_t request_len); void rend_client_refetch_renddesc(const char *query); void rend_client_refetch_v2_renddesc(const rend_data_t *rend_query); +void rend_client_cancel_descriptor_fetches(void); int rend_client_remove_intro_point(extend_info_t *failed_intro, const rend_data_t *rend_query); int rend_client_rendezvous_acked(origin_circuit_t *circ, @@ -4137,6 +4138,7 @@ typedef struct rend_cache_entry_t { void rend_cache_init(void); void rend_cache_clean(void); void rend_cache_clean_v2_descs_as_dir(void); +void rend_cache_purge(void); void rend_cache_free_all(void); int rend_valid_service_id(const char *query); int rend_cache_lookup_desc(const char *query, int version, const char **desc, diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 51306b3dc1..37cca14208 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -557,8 +557,45 @@ rend_client_refetch_v2_renddesc(const rend_data_t *rend_query) return; } +/** Cancel all rendezvous descriptor fetches currently in progress. + */ +void +rend_client_cancel_descriptor_fetches(void) +{ + smartlist_t *connection_array = get_connection_array(); + + SMARTLIST_FOREACH_BEGIN(connection_array, connection_t *, conn) { + if (conn->type == CONN_TYPE_DIR && + (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC || + conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2)) { + /* It's a rendezvous descriptor fetch in progress -- cancel it + * by marking the connection for close. + * + * Even if this connection has already reached EOF, this is + * enough to make sure that if the descriptor hasn't been + * processed yet, it won't be. See the end of + * connection_handle_read; connection_reached_eof (indirectly) + * processes whatever response the connection received. */ + + const rend_data_t *rd = (TO_DIR_CONN(conn))->rend_data; + if (!rd) { + log_warn(LD_BUG | LD_REND, + "Marking for close dir conn fetching rendezvous " + "descriptor for unknown service!"); + } else { + log_debug(LD_REND, "Marking for close dir conn fetching v%d " + "rendezvous descriptor for service %s", + (int)(rd->rend_desc_version), + safe_str(rd->onion_address)); + } + connection_mark_for_close(conn); + } + } SMARTLIST_FOREACH_END(conn); +} + /** Remove failed_intro from ent. If ent now has no intro points, or * service is unrecognized, then launch a new renddesc fetch. + * * Return -1 if error, 0 if no intro points remain or service * unrecognized, 1 if recognized and some intro points remain. diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c index d6f5443815..ba28ccabd4 100644 --- a/src/or/rendcommon.c +++ b/src/or/rendcommon.c @@ -871,6 +871,16 @@ rend_cache_clean(void) } } +/** Remove ALL entries from the rendezvous service descriptor cache. + */ +void +rend_cache_purge(void) +{ + if (rend_cache) + strmap_free(rend_cache, _rend_cache_entry_free); + rend_cache = strmap_new(); +} + /** Remove all old v2 descriptors and those for which this hidden service * directory is not responsible for any more. */ void -- cgit v1.2.3-54-g00ecf From 2ad18ae7366ce4979b44fa53d0105940005489c0 Mon Sep 17 00:00:00 2001 From: Robert Ransom Date: Mon, 25 Apr 2011 08:36:02 -0700 Subject: Allow rend_client_send_introduction to fail transiently i.e. without closing the AP connection. --- changes/forget-rend-descs-on-newnym | 4 ++++ src/or/circuituse.c | 18 ++++++++++++------ src/or/rendclient.c | 20 ++++++++++---------- 3 files changed, 26 insertions(+), 16 deletions(-) (limited to 'src/or') diff --git a/changes/forget-rend-descs-on-newnym b/changes/forget-rend-descs-on-newnym index c086973d22..ab2fd61f34 100644 --- a/changes/forget-rend-descs-on-newnym +++ b/changes/forget-rend-descs-on-newnym @@ -2,4 +2,8 @@ - Forget all hidden service descriptors cached as a client when processing a SIGNAL NEWNYM command. Fixes bug 3000. Bugfix on 0.0.6. + o Code simplifications and refactoring: + - Allow rend_client_send_introduction to fail without closing the + AP connection permanently. + diff --git a/src/or/circuituse.c b/src/or/circuituse.c index 996c99cef1..247aca7e07 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -1560,14 +1560,20 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn) "introduction. (stream %d sec old)", introcirc->_base.n_circ_id, rendcirc->_base.n_circ_id, conn_age); - if (rend_client_send_introduction(introcirc, rendcirc) < 0) { + switch (rend_client_send_introduction(introcirc, rendcirc)) { + case 0: /* success */ + rendcirc->_base.timestamp_dirty = time(NULL); + introcirc->_base.timestamp_dirty = time(NULL); + assert_circuit_ok(TO_CIRCUIT(rendcirc)); + assert_circuit_ok(TO_CIRCUIT(introcirc)); + return 0; + case -1: /* transient error */ + return 0; + case -2: /* permanent error */ return -1; + default: /* oops */ + tor_fragile_assert(); } - rendcirc->_base.timestamp_dirty = time(NULL); - introcirc->_base.timestamp_dirty = time(NULL); - assert_circuit_ok(TO_CIRCUIT(rendcirc)); - assert_circuit_ok(TO_CIRCUIT(introcirc)); - return 0; } } diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 37cca14208..ca846d9b4b 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -77,7 +77,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc, log_warn(LD_REND, "query %s didn't have valid rend desc in cache. Failing.", escaped_safe_str(introcirc->rend_data->onion_address)); - goto err; + goto perm_err; } /* first 20 bytes of payload are the hash of Bob's pk */ @@ -115,13 +115,13 @@ rend_client_send_introduction(origin_circuit_t *introcirc, log_info(LD_REND, "Internal error: could not find intro key; we " "only have a v2 rend desc with %d intro points.", num_intro_points); - goto err; + goto perm_err; } } } if (crypto_pk_get_digest(intro_key, payload)<0) { log_warn(LD_BUG, "Internal error: couldn't hash public key."); - goto err; + goto perm_err; } /* Initialize the pending_final_cpath and start the DH handshake. */ @@ -132,11 +132,11 @@ rend_client_send_introduction(origin_circuit_t *introcirc, cpath->magic = CRYPT_PATH_MAGIC; if (!(cpath->dh_handshake_state = crypto_dh_new(DH_TYPE_REND))) { log_warn(LD_BUG, "Internal error: couldn't allocate DH."); - goto err; + goto perm_err; } if (crypto_dh_generate_public(cpath->dh_handshake_state)<0) { log_warn(LD_BUG, "Internal error: couldn't generate g^x."); - goto err; + goto perm_err; } } @@ -186,7 +186,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc, if (crypto_dh_get_public(cpath->dh_handshake_state, tmp+dh_offset, DH_KEY_LEN)<0) { log_warn(LD_BUG, "Internal error: couldn't extract g^x."); - goto err; + goto perm_err; } note_crypto_pk_op(REND_CLIENT); @@ -199,7 +199,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc, PK_PKCS1_OAEP_PADDING, 0); if (r<0) { log_warn(LD_BUG,"Internal error: hybrid pk encrypt failed."); - goto err; + goto perm_err; } payload_len = DIGEST_LEN + r; @@ -212,17 +212,17 @@ rend_client_send_introduction(origin_circuit_t *introcirc, introcirc->cpath->prev)<0) { /* introcirc is already marked for close. leave rendcirc alone. */ log_warn(LD_BUG, "Couldn't send INTRODUCE1 cell"); - return -1; + return -2; } /* Now, we wait for an ACK or NAK on this circuit. */ introcirc->_base.purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT; return 0; -err: +perm_err: circuit_mark_for_close(TO_CIRCUIT(introcirc), END_CIRC_REASON_INTERNAL); circuit_mark_for_close(TO_CIRCUIT(rendcirc), END_CIRC_REASON_INTERNAL); - return -1; + return -2; } /** Called when a rendezvous circuit is open; sends a establish -- cgit v1.2.3-54-g00ecf From f1cf9bd74d225e90ca123eb664c1c5538eedaa03 Mon Sep 17 00:00:00 2001 From: Robert Ransom Date: Mon, 25 Apr 2011 06:38:35 -0700 Subject: Fix a bug introduced by purging rend_cache on NEWNYM If the user sent a SIGNAL NEWNYM command after we fetched a rendezvous descriptor, while we were building the introduction-point circuit, we would give up entirely on trying to connect to the hidden service. Original patch by rransom slightly edited to go into 0.2.1 --- src/or/rendclient.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) (limited to 'src/or') diff --git a/src/or/rendclient.c b/src/or/rendclient.c index ca846d9b4b..fb95efbdcb 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -74,10 +74,27 @@ rend_client_send_introduction(origin_circuit_t *introcirc, if (rend_cache_lookup_entry(introcirc->rend_data->onion_address, -1, &entry) < 1) { - log_warn(LD_REND, - "query %s didn't have valid rend desc in cache. Failing.", - escaped_safe_str(introcirc->rend_data->onion_address)); - goto perm_err; + log_info(LD_REND, + "query %s didn't have valid rend desc in cache. " + "Refetching descriptor.", + safe_str(introcirc->rend_data->onion_address)); + /* Fetch both v0 and v2 rend descriptors in parallel. Use whichever + * arrives first. Exception: When using client authorization, only + * fetch v2 descriptors.*/ + rend_client_refetch_v2_renddesc(introcirc->rend_data); + if (introcirc->rend_data->auth_type == REND_NO_AUTH) + rend_client_refetch_renddesc(introcirc->rend_data->onion_address); + { + connection_t *conn; + + while ((conn = connection_get_by_type_state_rendquery(CONN_TYPE_AP, + AP_CONN_STATE_CIRCUIT_WAIT, + introcirc->rend_data->onion_address, -1))) { + conn->state = AP_CONN_STATE_RENDDESC_WAIT; + } + } + + return -1; } /* first 20 bytes of payload are the hash of Bob's pk */ -- cgit v1.2.3-54-g00ecf From 8a36f2125137dc31a0771a8eeac0f2bb8c1343d0 Mon Sep 17 00:00:00 2001 From: Sebastian Hahn Date: Thu, 28 Apr 2011 01:48:25 +0200 Subject: Fix a failure case of connection_ap_handshake_attach_circuit() tor_fragile_assert() might be a no-op, so we have to return something here to indicate failure to the caller. --- src/or/circuituse.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/or') diff --git a/src/or/circuituse.c b/src/or/circuituse.c index 247aca7e07..6a9c3975c2 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -1573,6 +1573,7 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn) return -1; default: /* oops */ tor_fragile_assert(); + return -1; } } } -- cgit v1.2.3-54-g00ecf