aboutsummaryrefslogtreecommitdiff
path: root/src/or/rendclient.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2011-04-28 15:57:27 -0400
committerNick Mathewson <nickm@torproject.org>2011-04-28 15:57:27 -0400
commit32918e954fa3c2d55eb6b7695bd833197c31e09e (patch)
tree414b6ed3d4e1b98db8f05b4907006e4737024b0d /src/or/rendclient.c
parent26456d33546b674d5fa4d2c0112eeec561da7279 (diff)
parent2c0258b69a232a7b11ecc999bee74dac1c1b1495 (diff)
downloadtor-32918e954fa3c2d55eb6b7695bd833197c31e09e.tar
tor-32918e954fa3c2d55eb6b7695bd833197c31e09e.tar.gz
Merge remote-tracking branch 'origin/maint-0.2.2'
Conflicts: src/or/rendcommon.h
Diffstat (limited to 'src/or/rendclient.c')
-rw-r--r--src/or/rendclient.c76
1 files changed, 62 insertions, 14 deletions
diff --git a/src/or/rendclient.c b/src/or/rendclient.c
index da6cfa376..4fbf47421 100644
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@ -92,13 +92,25 @@ 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_client(introcirc->rend_data->onion_address));
- goto err;
+ log_info(LD_REND,
+ "query %s didn't have valid rend desc in cache. "
+ "Refetching descriptor.",
+ safe_str_client(introcirc->rend_data->onion_address));
+ rend_client_refetch_v2_renddesc(introcirc->rend_data);
+ {
+ connection_t *conn;
+
+ while ((conn = connection_get_by_type_state_rendquery(CONN_TYPE_AP,
+ AP_CONN_STATE_CIRCUIT_WAIT,
+ introcirc->rend_data->onion_address))) {
+ conn->state = AP_CONN_STATE_RENDDESC_WAIT;
+ }
+ }
+
+ return -1;
}
- /* first 20 bytes of payload are the hash of the intro key */
+ /* first 20 bytes of payload are the hash of Bob's pk */
intro_key = NULL;
SMARTLIST_FOREACH(entry->parsed->intro_nodes, rend_intro_point_t *,
intro, {
@@ -113,11 +125,11 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
"mid-connect! Could not find intro key; we only have a "
"v2 rend desc with %d intro points. Giving up.",
smartlist_len(entry->parsed->intro_nodes));
- 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. */
@@ -128,11 +140,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;
}
}
@@ -182,7 +194,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);
@@ -195,7 +207,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;
@@ -208,17 +220,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
@@ -529,8 +541,44 @@ 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 "
+ "rendezvous descriptor for service %s",
+ 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.