mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-28 06:13:31 +01:00
r16314@catbus: nickm | 2007-10-31 23:40:08 -0400
Clients download and cache new hidden descriptor format. svn:r12302
This commit is contained in:
parent
5da5d2bd79
commit
d1df046e3b
@ -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'",
|
log_info(LD_REND,"Got a hidden service request for ID '%s'",
|
||||||
safe_str(conn->rend_query));
|
safe_str(conn->rend_query));
|
||||||
/* see if we already have it cached */
|
/* 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) {
|
if (r<0) {
|
||||||
log_warn(LD_BUG,"Invalid service name '%s'",
|
log_warn(LD_BUG,"Invalid service name '%s'",
|
||||||
safe_str(conn->rend_query));
|
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;
|
conn->_base.state = AP_CONN_STATE_RENDDESC_WAIT;
|
||||||
log_info(LD_REND, "Unknown descriptor %s. Fetching.",
|
log_info(LD_REND, "Unknown descriptor %s. Fetching.",
|
||||||
safe_str(conn->rend_query));
|
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);
|
rend_client_refetch_renddesc(conn->rend_query);
|
||||||
} else { /* r > 0 */
|
} else { /* r > 0 */
|
||||||
/** How long after we receive a hidden service descriptor do we consider
|
/** 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;
|
conn->_base.state = AP_CONN_STATE_RENDDESC_WAIT;
|
||||||
log_info(LD_REND, "Stale descriptor %s. Refetching.",
|
log_info(LD_REND, "Stale descriptor %s. Refetching.",
|
||||||
safe_str(conn->rend_query));
|
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);
|
rend_client_refetch_renddesc(conn->rend_query);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
int rend_client_introduction_acked(origin_circuit_t *circ, const char *request,
|
||||||
size_t request_len);
|
size_t request_len);
|
||||||
void rend_client_refetch_renddesc(const char *query);
|
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,
|
int rend_client_remove_intro_point(extend_info_t *failed_intro,
|
||||||
const char *query);
|
const char *query);
|
||||||
int rend_client_rendezvous_acked(origin_circuit_t *circ, const char *request,
|
int rend_client_rendezvous_acked(origin_circuit_t *circ, const char *request,
|
||||||
|
@ -63,13 +63,14 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
|
|||||||
rend_cache_entry_t *entry;
|
rend_cache_entry_t *entry;
|
||||||
crypt_path_t *cpath;
|
crypt_path_t *cpath;
|
||||||
off_t dh_offset;
|
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(introcirc->_base.purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
|
||||||
tor_assert(rendcirc->_base.purpose == CIRCUIT_PURPOSE_C_REND_READY);
|
tor_assert(rendcirc->_base.purpose == CIRCUIT_PURPOSE_C_REND_READY);
|
||||||
tor_assert(!rend_cmp_service_ids(introcirc->rend_query,
|
tor_assert(!rend_cmp_service_ids(introcirc->rend_query,
|
||||||
rendcirc->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,
|
log_warn(LD_REND,
|
||||||
"query %s didn't have valid rend desc in cache. Failing.",
|
"query %s didn't have valid rend desc in cache. Failing.",
|
||||||
escaped_safe_str(introcirc->rend_query));
|
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 */
|
/* 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.");
|
log_warn(LD_BUG, "Internal error: couldn't hash public key.");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@ -132,7 +143,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
|
|||||||
note_crypto_pk_op(REND_CLIENT);
|
note_crypto_pk_op(REND_CLIENT);
|
||||||
/*XXX maybe give crypto_pk_public_hybrid_encrypt a max_len arg,
|
/*XXX maybe give crypto_pk_public_hybrid_encrypt a max_len arg,
|
||||||
* to avoid buffer overflows? */
|
* 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,
|
tmp,
|
||||||
(int)(dh_offset+DH_KEY_LEN),
|
(int)(dh_offset+DH_KEY_LEN),
|
||||||
PK_PKCS1_OAEP_PADDING, 0);
|
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
|
/** Remove failed_intro from ent. If ent now has no intro points, or
|
||||||
* service is unrecognized, then launch a new renddesc fetch.
|
* 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;
|
rend_cache_entry_t *ent;
|
||||||
connection_t *conn;
|
connection_t *conn;
|
||||||
|
|
||||||
r = rend_cache_lookup_entry(query, 0, &ent);
|
r = rend_cache_lookup_entry(query, -1, &ent);
|
||||||
if (r<0) {
|
if (r<0) {
|
||||||
log_warn(LD_BUG, "Malformed service ID %s.", escaped_safe_str(query));
|
log_warn(LD_BUG, "Malformed service ID %s.", escaped_safe_str(query));
|
||||||
return -1;
|
return -1;
|
||||||
@ -289,6 +333,9 @@ rend_client_remove_intro_point(extend_info_t *failed_intro, const char *query)
|
|||||||
if (r==0) {
|
if (r==0) {
|
||||||
log_info(LD_REND, "Unknown service %s. Re-fetching descriptor.",
|
log_info(LD_REND, "Unknown service %s. Re-fetching descriptor.",
|
||||||
escaped_safe_str(query));
|
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);
|
rend_client_refetch_renddesc(query);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -325,6 +372,9 @@ rend_client_remove_intro_point(extend_info_t *failed_intro, const char *query)
|
|||||||
log_info(LD_REND,
|
log_info(LD_REND,
|
||||||
"No more intro points remain for %s. Re-fetching descriptor.",
|
"No more intro points remain for %s. Re-fetching descriptor.",
|
||||||
escaped_safe_str(query));
|
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);
|
rend_client_refetch_renddesc(query);
|
||||||
|
|
||||||
/* move all pending streams back to renddesc_wait */
|
/* 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))
|
if (rend_cmp_service_ids(query, conn->rend_query))
|
||||||
continue;
|
continue;
|
||||||
assert_connection_ok(TO_CONN(conn), now);
|
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) {
|
entry->parsed->n_intro_points > 0) {
|
||||||
/* either this fetch worked, or it failed but there was a
|
/* either this fetch worked, or it failed but there was a
|
||||||
* valid entry from before which we should reuse */
|
* valid entry from before which we should reuse */
|
||||||
@ -486,7 +536,7 @@ rend_client_get_random_intro(const char *query)
|
|||||||
int i;
|
int i;
|
||||||
rend_cache_entry_t *entry;
|
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,
|
log_warn(LD_REND,
|
||||||
"Query '%s' didn't have valid rend desc in cache. Failing.",
|
"Query '%s' didn't have valid rend desc in cache. Failing.",
|
||||||
safe_str(query));
|
safe_str(query));
|
||||||
|
@ -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>
|
/** 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.
|
* 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
|
int
|
||||||
rend_cache_lookup_entry(const char *query, int version, rend_cache_entry_t **e)
|
rend_cache_lookup_entry(const char *query, int version, rend_cache_entry_t **e)
|
||||||
{
|
{
|
||||||
char key[REND_SERVICE_ID_LEN+2]; /* <version><query>\0 */
|
char key[REND_SERVICE_ID_LEN+2]; /* <version><query>\0 */
|
||||||
tor_assert(rend_cache);
|
tor_assert(rend_cache);
|
||||||
tor_assert(!version);
|
|
||||||
if (!rend_valid_service_id(query))
|
if (!rend_valid_service_id(query))
|
||||||
return -1;
|
return -1;
|
||||||
tor_snprintf(key, sizeof(key), "%d%s", version, query);
|
*e = NULL;
|
||||||
|
if (version != 0) {
|
||||||
|
tor_snprintf(key, sizeof(key), "2%s", query);
|
||||||
*e = strmap_get_lc(rend_cache, key);
|
*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)
|
if (!*e)
|
||||||
return 0;
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user