summaryrefslogtreecommitdiff
path: root/src/or/rendclient.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2009-05-27 18:12:18 -0400
committerNick Mathewson <nickm@torproject.org>2009-05-27 18:12:18 -0400
commitcb18fc2190ce909a9256849f9b141148177d4dd4 (patch)
tree42e2aca11768f5772128b9e504eacc10c779bc89 /src/or/rendclient.c
parente86ad6b7fb49a497fa75b79bc15d004b02ebd371 (diff)
parentd49711e52c22e77e95c30660f78b19d4f6025d04 (diff)
downloadtor-cb18fc2190ce909a9256849f9b141148177d4dd4.tar.gz
tor-cb18fc2190ce909a9256849f9b141148177d4dd4.zip
Merge commit 'origin/maint-0.2.1'
Diffstat (limited to 'src/or/rendclient.c')
-rw-r--r--src/or/rendclient.c95
1 files changed, 71 insertions, 24 deletions
diff --git a/src/or/rendclient.c b/src/or/rendclient.c
index 3be67c9f83..fb50e8dc00 100644
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@ -63,7 +63,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
rend_cache_entry_t *entry;
crypt_path_t *cpath;
off_t dh_offset;
- crypto_pk_env_t *intro_key = NULL;
+ crypto_pk_env_t *intro_key; /* either Bob's public key or an intro key. */
tor_assert(introcirc->_base.purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
tor_assert(rendcirc->_base.purpose == CIRCUIT_PURPOSE_C_REND_READY);
@@ -80,19 +80,23 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
goto err;
}
- /* first 20 bytes of payload are the hash of the intro key */
- intro_key = NULL;
- SMARTLIST_FOREACH(entry->parsed->intro_nodes, rend_intro_point_t *,
- intro, {
- if (!memcmp(introcirc->build_state->chosen_exit->identity_digest,
- intro->extend_info->identity_digest, DIGEST_LEN)) {
- intro_key = intro->intro_key;
- break;
+ /* first 20 bytes of payload are the hash of bob's pk */
+ if (entry->parsed->version == 0) { /* unversioned descriptor */
+ intro_key = entry->parsed->pk;
+ } else { /* versioned descriptor */
+ intro_key = NULL;
+ SMARTLIST_FOREACH(entry->parsed->intro_nodes, rend_intro_point_t *,
+ intro, {
+ if (!memcmp(introcirc->build_state->chosen_exit->identity_digest,
+ intro->extend_info->identity_digest, DIGEST_LEN)) {
+ intro_key = intro->intro_key;
+ break;
+ }
+ });
+ if (!intro_key) {
+ log_warn(LD_BUG, "Internal error: could not find intro key.");
+ goto err;
}
- });
- if (!intro_key) {
- log_warn(LD_BUG, "Internal error: could not find intro key.");
- goto err;
}
if (crypto_pk_get_digest(intro_key, payload)<0) {
log_warn(LD_BUG, "Internal error: couldn't hash public key.");
@@ -447,6 +451,28 @@ directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query)
return 1;
}
+/** If we are not currently fetching a rendezvous service descriptor
+ * for the service ID <b>query</b>, start a directory connection to fetch a
+ * new one.
+ */
+void
+rend_client_refetch_renddesc(const char *query)
+{
+ if (!get_options()->FetchHidServDescriptors)
+ return;
+ log_info(LD_REND, "Fetching rendezvous descriptor for service %s",
+ escaped_safe_str(query));
+ if (connection_get_by_type_state_rendquery(CONN_TYPE_DIR, 0, query, 0)) {
+ log_info(LD_REND,"Would fetch a new renddesc here (for %s), but one is "
+ "already in progress.", escaped_safe_str(query));
+ } else {
+ /* not one already; initiate a dir rend desc lookup */
+ directory_get_from_dirserver(DIR_PURPOSE_FETCH_RENDDESC,
+ ROUTER_PURPOSE_GENERAL, query,
+ PDS_RETRY_IF_NO_SERVERS);
+ }
+}
+
/** Start a connection to a hidden service directory to fetch a v2
* rendezvous service descriptor for the base32-encoded service ID
* <b>query</b>.
@@ -498,8 +524,8 @@ rend_client_refetch_v2_renddesc(const rend_data_t *rend_query)
log_info(LD_REND, "Could not pick one of the responsible hidden "
"service directories to fetch descriptors, because "
"we already tried them all unsuccessfully.");
- /* Close pending connections. */
- rend_client_desc_trynow(rend_query->onion_address);
+ /* Close pending connections (unless a v0 request is still going on). */
+ rend_client_desc_trynow(rend_query->onion_address, 2);
return;
}
@@ -526,7 +552,12 @@ rend_client_remove_intro_point(extend_info_t *failed_intro,
if (r==0) {
log_info(LD_REND, "Unknown service %s. Re-fetching descriptor.",
escaped_safe_str(rend_query->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(rend_query);
+ if (rend_query->auth_type == REND_NO_AUTH)
+ rend_client_refetch_renddesc(rend_query->onion_address);
return 0;
}
@@ -544,12 +575,17 @@ rend_client_remove_intro_point(extend_info_t *failed_intro,
log_info(LD_REND,
"No more intro points remain for %s. Re-fetching descriptor.",
escaped_safe_str(rend_query->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(rend_query);
+ if (rend_query->auth_type == REND_NO_AUTH)
+ rend_client_refetch_renddesc(rend_query->onion_address);
/* move all pending streams back to renddesc_wait */
while ((conn = connection_get_by_type_state_rendquery(CONN_TYPE_AP,
AP_CONN_STATE_CIRCUIT_WAIT,
- rend_query->onion_address))) {
+ rend_query->onion_address, -1))) {
conn->state = AP_CONN_STATE_RENDDESC_WAIT;
}
@@ -658,17 +694,22 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const char *request,
return -1;
}
-/** Find all the apconns in state AP_CONN_STATE_RENDDESC_WAIT that are
- * waiting on <b>query</b>. If there's a working cache entry here with at
- * least one intro point, move them to the next state. */
+/** Find all the apconns in state AP_CONN_STATE_RENDDESC_WAIT that
+ * are waiting on query. If there's a working cache entry here
+ * with at least one intro point, move them to the next state. If
+ * <b>rend_version</b> is non-negative, fail connections that have
+ * requested <b>query</b> unless there are still descriptor fetch
+ * requests in progress for other descriptor versions than
+ * <b>rend_version</b>.
+ */
void
-rend_client_desc_trynow(const char *query)
+rend_client_desc_trynow(const char *query, int rend_version)
{
edge_connection_t *conn;
rend_cache_entry_t *entry;
time_t now = time(NULL);
- smartlist_t *conns = get_connection_array();
+ smartlist_t *conns = get_connection_array();
SMARTLIST_FOREACH(conns, connection_t *, _conn,
{
if (_conn->type != CONN_TYPE_AP ||
@@ -702,9 +743,15 @@ rend_client_desc_trynow(const char *query)
connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
}
} else { /* 404, or fetch didn't get that far */
- log_notice(LD_REND,"Closing stream for '%s.onion': hidden service is "
- "unavailable (try again later).", safe_str(query));
- connection_mark_unattached_ap(conn, END_STREAM_REASON_RESOLVEFAILED);
+ /* Unless there are requests for another descriptor version pending,
+ * close the connection. */
+ if (rend_version >= 0 &&
+ !connection_get_by_type_state_rendquery(CONN_TYPE_DIR, 0, query,
+ rend_version == 0 ? 2 : 0)) {
+ log_notice(LD_REND,"Closing stream for '%s.onion': hidden service is "
+ "unavailable (try again later).", safe_str(query));
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_RESOLVEFAILED);
+ }
}
});
}