diff options
author | Nick Mathewson <nickm@torproject.org> | 2007-11-01 03:43:02 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2007-11-01 03:43:02 +0000 |
commit | d1df046e3b230d9b445d146577eab428c3f4aa0a (patch) | |
tree | 82034dfe1dd7411b20a2429ef395dedde14fa740 /src/or | |
parent | 5da5d2bd7926707dcd9d2a40e50f5b2f9f26745a (diff) | |
download | tor-d1df046e3b230d9b445d146577eab428c3f4aa0a.tar tor-d1df046e3b230d9b445d146577eab428c3f4aa0a.tar.gz |
r16314@catbus: nickm | 2007-10-31 23:40:08 -0400
Clients download and cache new hidden descriptor format.
svn:r12302
Diffstat (limited to 'src/or')
-rw-r--r-- | src/or/connection_edge.c | 8 | ||||
-rw-r--r-- | src/or/or.h | 1 | ||||
-rw-r--r-- | src/or/rendclient.c | 62 | ||||
-rw-r--r-- | src/or/rendcommon.c | 16 |
4 files changed, 76 insertions, 11 deletions
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index ba0d2a85a..df7daa76c 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -1443,7 +1443,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, log_info(LD_REND,"Got a hidden service request for ID '%s'", safe_str(conn->rend_query)); /* see if we already have it cached */ - r = rend_cache_lookup_entry(conn->rend_query, 0, &entry); + r = rend_cache_lookup_entry(conn->rend_query, -1, &entry); if (r<0) { log_warn(LD_BUG,"Invalid service name '%s'", safe_str(conn->rend_query)); @@ -1454,6 +1454,9 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, conn->_base.state = AP_CONN_STATE_RENDDESC_WAIT; log_info(LD_REND, "Unknown descriptor %s. Fetching.", safe_str(conn->rend_query)); + /* Fetch both, v0 and v2 rend descriptors in parallel. Use whichever + * arrives first. */ + rend_client_refetch_v2_renddesc(conn->rend_query); rend_client_refetch_renddesc(conn->rend_query); } else { /* r > 0 */ /** How long after we receive a hidden service descriptor do we consider @@ -1470,6 +1473,9 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, conn->_base.state = AP_CONN_STATE_RENDDESC_WAIT; log_info(LD_REND, "Stale descriptor %s. Refetching.", safe_str(conn->rend_query)); + /* Fetch both, v0 and v2 rend descriptors in parallel. Use whichever + * arrives first. */ + rend_client_refetch_v2_renddesc(conn->rend_query); rend_client_refetch_renddesc(conn->rend_query); } } diff --git a/src/or/or.h b/src/or/or.h index 512f90c32..ac832d8fb 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -3418,6 +3418,7 @@ void rend_client_rendcirc_has_opened(origin_circuit_t *circ); int rend_client_introduction_acked(origin_circuit_t *circ, const char *request, size_t request_len); void rend_client_refetch_renddesc(const char *query); +void rend_client_refetch_v2_renddesc(const char *query); int rend_client_remove_intro_point(extend_info_t *failed_intro, const char *query); int rend_client_rendezvous_acked(origin_circuit_t *circ, const char *request, diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 8f910ccd8..da86808f0 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -63,13 +63,14 @@ 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; /* 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); tor_assert(!rend_cmp_service_ids(introcirc->rend_query, rendcirc->rend_query)); - if (rend_cache_lookup_entry(introcirc->rend_query, 0, &entry) < 1) { + if (rend_cache_lookup_entry(introcirc->rend_query, -1, &entry) < 1) { log_warn(LD_REND, "query %s didn't have valid rend desc in cache. Failing.", escaped_safe_str(introcirc->rend_query)); @@ -77,7 +78,17 @@ rend_client_send_introduction(origin_circuit_t *introcirc, } /* first 20 bytes of payload are the hash of bob's pk */ - if (crypto_pk_get_digest(entry->parsed->pk, payload)<0) { + if (entry->parsed->version == 0) { /* unversioned descriptor */ + intro_key = entry->parsed->pk; + } else { /* versioned descriptor */ + char hex_digest[HEX_DIGEST_LEN+2]; + hex_digest[0] = '$'; + base16_encode(hex_digest+1, HEX_DIGEST_LEN+1, + introcirc->build_state->chosen_exit->identity_digest, + DIGEST_LEN); + intro_key = strmap_get(entry->parsed->intro_keys, hex_digest); + } + if (crypto_pk_get_digest(intro_key, payload)<0) { log_warn(LD_BUG, "Internal error: couldn't hash public key."); goto err; } @@ -132,7 +143,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc, note_crypto_pk_op(REND_CLIENT); /*XXX maybe give crypto_pk_public_hybrid_encrypt a max_len arg, * to avoid buffer overflows? */ - r = crypto_pk_public_hybrid_encrypt(entry->parsed->pk, payload+DIGEST_LEN, + r = crypto_pk_public_hybrid_encrypt(intro_key, payload+DIGEST_LEN, tmp, (int)(dh_offset+DH_KEY_LEN), PK_PKCS1_OAEP_PADDING, 0); @@ -268,6 +279,39 @@ rend_client_refetch_renddesc(const char *query) } } +/** If we are not currently fetching a rendezvous service descriptor for the + * base32-encoded service ID <b>query</b>, start a connection to a hidden + * service directory to fetch a new one. + */ +void +rend_client_refetch_v2_renddesc(const char *query) +{ + char descriptor_id[DIGEST_LEN]; + int replica; + smartlist_t *hs_dirs; + tor_assert(query); + tor_assert(strlen(query) == REND_SERVICE_ID_LEN); + /* Are we configured to fetch descriptors? */ + if (!get_options()->FetchHidServDescriptors) { + log_warn(LD_REND, "We received an onion address for a v2 rendezvous " + "service descriptor, but are not fetching service descriptors."); + return; + } + log_debug(LD_REND, "Fetching v2 rendezvous descriptor for service %s", + query); + replica = crypto_rand_int(REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS); + if (rend_compute_v2_desc_id(descriptor_id, query, NULL, time(NULL), + replica) < 0) { + log_warn(LD_REND, "Internal error: Computing v2 rendezvous " + "descriptor ID did not succeed."); + return; + } + hs_dirs = hid_serv_create_routing_table(); + directory_get_from_hs_dir(descriptor_id, query, hs_dirs); + smartlist_free(hs_dirs); + return; +} + /** Remove failed_intro from ent. If ent now has no intro points, or * service is unrecognized, then launch a new renddesc fetch. * @@ -281,7 +325,7 @@ rend_client_remove_intro_point(extend_info_t *failed_intro, const char *query) rend_cache_entry_t *ent; connection_t *conn; - r = rend_cache_lookup_entry(query, 0, &ent); + r = rend_cache_lookup_entry(query, -1, &ent); if (r<0) { log_warn(LD_BUG, "Malformed service ID %s.", escaped_safe_str(query)); return -1; @@ -289,6 +333,9 @@ rend_client_remove_intro_point(extend_info_t *failed_intro, const char *query) if (r==0) { log_info(LD_REND, "Unknown service %s. Re-fetching descriptor.", escaped_safe_str(query)); + /* Fetch both, v0 and v2 rend descriptors in parallel. Use whichever + * arrives first. */ + rend_client_refetch_v2_renddesc(query); rend_client_refetch_renddesc(query); return 0; } @@ -325,6 +372,9 @@ rend_client_remove_intro_point(extend_info_t *failed_intro, const char *query) log_info(LD_REND, "No more intro points remain for %s. Re-fetching descriptor.", escaped_safe_str(query)); + /* Fetch both, v0 and v2 rend descriptors in parallel. Use whichever + * arrives first. */ + rend_client_refetch_v2_renddesc(query); rend_client_refetch_renddesc(query); /* move all pending streams back to renddesc_wait */ @@ -450,7 +500,7 @@ rend_client_desc_here(const char *query) if (rend_cmp_service_ids(query, conn->rend_query)) continue; assert_connection_ok(TO_CONN(conn), now); - if (rend_cache_lookup_entry(conn->rend_query, 0, &entry) == 1 && + if (rend_cache_lookup_entry(conn->rend_query, -1, &entry) == 1 && entry->parsed->n_intro_points > 0) { /* either this fetch worked, or it failed but there was a * valid entry from before which we should reuse */ @@ -486,7 +536,7 @@ rend_client_get_random_intro(const char *query) int i; rend_cache_entry_t *entry; - if (rend_cache_lookup_entry(query, 0, &entry) < 1) { + if (rend_cache_lookup_entry(query, -1, &entry) < 1) { log_warn(LD_REND, "Query '%s' didn't have valid rend desc in cache. Failing.", safe_str(query)); diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c index 6c7555570..535a21236 100644 --- a/src/or/rendcommon.c +++ b/src/or/rendcommon.c @@ -778,18 +778,26 @@ rend_valid_service_id(const char *query) /** If we have a cached rend_cache_entry_t for the service ID <b>query</b> * with <b>version</b>, set *<b>e</b> to that entry and return 1. - * Else return 0. + * Else return 0. If <b>version</b> is nonnegative, only return an entry + * in that descriptor format version. Otherwise (if <b>version</b> is + * negative), return the most recent format we have. */ int rend_cache_lookup_entry(const char *query, int version, rend_cache_entry_t **e) { char key[REND_SERVICE_ID_LEN+2]; /* <version><query>\0 */ tor_assert(rend_cache); - tor_assert(!version); if (!rend_valid_service_id(query)) return -1; - tor_snprintf(key, sizeof(key), "%d%s", version, query); - *e = strmap_get_lc(rend_cache, key); + *e = NULL; + if (version != 0) { + tor_snprintf(key, sizeof(key), "2%s", query); + *e = strmap_get_lc(rend_cache, key); + } + if (!*e && version != 2) { + tor_snprintf(key, sizeof(key), "0%s", query); + *e = strmap_get_lc(rend_cache, key); + } if (!*e) return 0; return 1; |