/** Called when we're trying to connect an ap conn; sends an INTRODUCE1 cell * down introcirc if possible. */ int rend_client_send_introduction(origin_circuit_t *introcirc, origin_circuit_t *rendcirc) { const or_options_t *options = get_options(); size_t payload_len; int r, v3_shift = 0; char payload[RELAY_PAYLOAD_SIZE]; char tmp[RELAY_PAYLOAD_SIZE]; rend_cache_entry_t *entry = NULL; crypt_path_t *cpath; off_t dh_offset; crypto_pk_t *intro_key = NULL; int status = 0; const char *onion_address; tor_assert(introcirc->base_.purpose == CIRCUIT_PURPOSE_C_INTRODUCING); tor_assert(rendcirc->base_.purpose == CIRCUIT_PURPOSE_C_REND_READY); tor_assert(introcirc->rend_data); tor_assert(rendcirc->rend_data); tor_assert(!rend_cmp_service_ids(rend_data_get_address(introcirc->rend_data), rend_data_get_address(rendcirc->rend_data))); assert_circ_anonymity_ok(introcirc, options); assert_circ_anonymity_ok(rendcirc, options); onion_address = rend_data_get_address(introcirc->rend_data); r = rend_cache_lookup_entry(onion_address, -1, &entry); /* An invalid onion address is not possible else we have a big issue. */ tor_assert(r != -EINVAL); if (r < 0 || !rend_client_any_intro_points_usable(entry)) { /* If the descriptor is not found or the intro points are not usable * anymore, trigger a fetch. */ log_info(LD_REND, "query %s didn't have valid rend desc in cache. " "Refetching descriptor.", safe_str_client(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, onion_address))) { connection_ap_mark_as_waiting_for_renddesc(TO_ENTRY_CONN(conn)); } } status = -1; goto cleanup; } /* first 20 bytes of payload are the hash of the service's pk */ intro_key = NULL; SMARTLIST_FOREACH(entry->parsed->intro_nodes, rend_intro_point_t *, intro, { if (tor_memeq(introcirc->build_state->chosen_exit->identity_digest, intro->extend_info->identity_digest, DIGEST_LEN)) { intro_key = intro->intro_key; break; } });
/** Called when we're trying to connect an ap conn; sends an INTRODUCE1 cell * down introcirc if possible. */ int rend_client_send_introduction(origin_circuit_t *introcirc, origin_circuit_t *rendcirc) { size_t payload_len; int r, v3_shift = 0; char payload[RELAY_PAYLOAD_SIZE]; char tmp[RELAY_PAYLOAD_SIZE]; rend_cache_entry_t *entry; crypt_path_t *cpath; off_t dh_offset; crypto_pk_t *intro_key = NULL; int status = 0; tor_assert(introcirc->_base.purpose == CIRCUIT_PURPOSE_C_INTRODUCING); tor_assert(rendcirc->_base.purpose == CIRCUIT_PURPOSE_C_REND_READY); tor_assert(introcirc->rend_data); tor_assert(rendcirc->rend_data); tor_assert(!rend_cmp_service_ids(introcirc->rend_data->onion_address, rendcirc->rend_data->onion_address)); #ifndef NON_ANONYMOUS_MODE_ENABLED tor_assert(!(introcirc->build_state->onehop_tunnel)); tor_assert(!(rendcirc->build_state->onehop_tunnel)); #endif if (rend_cache_lookup_entry(introcirc->rend_data->onion_address, -1, &entry) < 1) { 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; } } status = -1; goto cleanup; } /* 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, { if (tor_memeq(introcirc->build_state->chosen_exit->identity_digest, intro->extend_info->identity_digest, DIGEST_LEN)) { intro_key = intro->intro_key; break; } });
static void test_rend_cache_lookup_entry(void *data) { int ret; rend_data_t *mock_rend_query = NULL; char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1]; rend_cache_entry_t *entry = NULL; rend_encoded_v2_service_descriptor_t *desc_holder = NULL; char *service_id = NULL; (void)data; rend_cache_init(); generate_desc(RECENT_TIME, &desc_holder, &service_id, 3); ret = rend_cache_lookup_entry("abababababababab", 0, NULL); tt_int_op(ret, OP_EQ, -ENOENT); ret = rend_cache_lookup_entry("invalid query", 2, NULL); tt_int_op(ret, OP_EQ, -EINVAL); ret = rend_cache_lookup_entry("abababababababab", 2, NULL); tt_int_op(ret, OP_EQ, -ENOENT); ret = rend_cache_lookup_entry("abababababababab", 4224, NULL); tt_int_op(ret, OP_EQ, -ENOENT); mock_rend_query = mock_rend_data(service_id); base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, mock_rend_query, NULL); ret = rend_cache_lookup_entry(service_id, 2, NULL); tt_int_op(ret, OP_EQ, 0); ret = rend_cache_lookup_entry(service_id, 2, &entry); tt_int_op(ret, OP_EQ, 0); tt_assert(entry); tt_int_op(entry->len, OP_EQ, strlen(desc_holder->desc_str)); tt_str_op(entry->desc, OP_EQ, desc_holder->desc_str); done: rend_encoded_v2_service_descriptor_free(desc_holder); tor_free(service_id); rend_cache_free_all(); rend_data_free(mock_rend_query); }
/** Called when we're trying to connect an ap conn; sends an INTRODUCE1 cell * down introcirc if possible. */ int rend_client_send_introduction(origin_circuit_t *introcirc, origin_circuit_t *rendcirc) { size_t payload_len; int r, v3_shift = 0; char payload[RELAY_PAYLOAD_SIZE]; char tmp[RELAY_PAYLOAD_SIZE]; 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(introcirc->rend_data); tor_assert(rendcirc->rend_data); tor_assert(!rend_cmp_service_ids(introcirc->rend_data->onion_address, rendcirc->rend_data->onion_address)); 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 err; } /* first 20 bytes of payload are the hash of Bob's pk */ if (entry->parsed->version == 0) { /* un-versioned 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) { /** XXX This case probably means that the intro point vanished while * we were building a circuit to it. In the future, we should find * out how that happened and whether we should kill the circuits to * removed intro points immediately. See task 1073. */ int num_intro_points = smartlist_len(entry->parsed->intro_nodes); if (rend_cache_lookup_entry(introcirc->rend_data->onion_address, 0, &entry) > 0) { log_info(LD_REND, "We have both a v0 and a v2 rend desc for this " "service. The v2 desc doesn't contain the introduction " "point (and key) to send an INTRODUCE1/2 cell to this " "introduction point. Assuming the introduction point " "is for v0 rend clients and using the service key " "from the v0 desc instead. (This is probably a bug, " "because we shouldn't even have both a v0 and a v2 " "descriptor for the same service.)"); /* See flyspray task 1024. */ intro_key = entry->parsed->pk; } else { 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; } } }