diff options
-rw-r--r-- | src/or/config.c | 1 | ||||
-rw-r--r-- | src/or/or.h | 2 | ||||
-rw-r--r-- | src/or/rendmid.c | 16 | ||||
-rw-r--r-- | src/or/rendservice.c | 184 |
4 files changed, 155 insertions, 48 deletions
diff --git a/src/or/config.c b/src/or/config.c index d2981771c..443ebcac8 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -348,6 +348,7 @@ static config_var_t option_vars_[] = { V(PerConnBWBurst, MEMUNIT, "0"), V(PerConnBWRate, MEMUNIT, "0"), V(PidFile, STRING, NULL), + V(IntroPointAcceptMutipleConnections, BOOL, "0"), V(TestingTorNetwork, BOOL, "0"), V(TestingMinExitFlagThreshold, MEMUNIT, "0"), V(TestingMinFastFlagThreshold, MEMUNIT, "0"), diff --git a/src/or/or.h b/src/or/or.h index c47ae23ed..14097da6e 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -4020,6 +4020,8 @@ typedef struct { * of certain configuration options. */ int TestingTorNetwork; + int IntroPointAcceptMutipleConnections; + /** Minimum value for the Exit flag threshold on testing networks. */ uint64_t TestingMinExitFlagThreshold; diff --git a/src/or/rendmid.c b/src/or/rendmid.c index 1bd11f6dc..8741397fc 100644 --- a/src/or/rendmid.c +++ b/src/or/rendmid.c @@ -92,13 +92,15 @@ rend_mid_establish_intro(or_circuit_t *circ, const uint8_t *request, base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1, pk_digest, REND_SERVICE_ID_LEN); - /* Close any other intro circuits with the same pk. */ - c = NULL; - while ((c = circuit_get_intro_point(pk_digest))) { - log_info(LD_REND, "Replacing old circuit for service %s", - safe_str(serviceid)); - circuit_mark_for_close(TO_CIRCUIT(c), END_CIRC_REASON_FINISHED); - /* Now it's marked, and it won't be returned next time. */ + if (!get_options()->IntroPointAcceptMutipleConnections) { + /* Close any other intro circuits with the same pk. */ + c = NULL; + while ((c = circuit_get_intro_point(pk_digest))) { + log_info(LD_REND, "Replacing old circuit for service %s", + safe_str(serviceid)); + circuit_mark_for_close(TO_CIRCUIT(c), END_CIRC_REASON_FINISHED); + /* Now it's marked, and it won't be returned next time. */ + } } /* Acknowledge the request. */ diff --git a/src/or/rendservice.c b/src/or/rendservice.c index 500efaf20..89b12a35c 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -14,6 +14,7 @@ #include "circuitbuild.h" #include "circuitlist.h" #include "circuituse.h" +#include "connection.h" #include "config.h" #include "directory.h" #include "networkstatus.h" @@ -106,6 +107,8 @@ typedef struct rend_service_t { char service_id[REND_SERVICE_ID_LEN_BASE32+1]; /**< Onion address without * '.onion' */ char pk_digest[DIGEST_LEN]; /**< Hash of permanent hidden-service key. */ + time_t descriptor_fetch_time; /**< The last time the service descriptor was + * fetched, 0 if it has not been */ smartlist_t *intro_nodes; /**< List of rend_intro_point_t's we have, * or are trying to establish. */ time_t intro_period_started; /**< Start of the current period to build @@ -3126,47 +3129,146 @@ rend_services_introduce(void) * to. XXXX This is daft. */ prev_intro_nodes = smartlist_len(service->intro_nodes); - /* We have enough directory information to start establishing our - * intro points. We want to end up with n_intro_points_wanted - * intro points, but if we're just starting, we launch two extra - * circuits and use the first n_intro_points_wanted that complete. - * - * The ones after the first three will be converted to 'general' - * internal circuits in rend_service_intro_has_opened(), and then - * we'll drop them from the list of intro points next time we - * go through the above "find out which introduction points we have - * in progress" loop. */ - n_intro_points_to_open = (service->n_intro_points_wanted + - (prev_intro_nodes == 0 ? 2 : 0)); - for (j = (int)n_intro_points_unexpired; - j < (int)n_intro_points_to_open; - ++j) { /* XXXX remove casts */ - router_crn_flags_t flags = CRN_NEED_UPTIME|CRN_NEED_DESC; - if (get_options()->AllowInvalid_ & ALLOW_INVALID_INTRODUCTION) - flags |= CRN_ALLOW_INVALID; - node = router_choose_random_node(intro_nodes, - options->ExcludeNodes, flags); - if (!node) { - log_warn(LD_REND, - "Could only establish %d introduction points for %s; " - "wanted %u.", - smartlist_len(service->intro_nodes), service->service_id, - n_intro_points_to_open); - break; - } - intro_point_set_changed = 1; - smartlist_add(intro_nodes, (void*)node); - intro = tor_malloc_zero(sizeof(rend_intro_point_t)); - intro->extend_info = extend_info_from_node(node, 0); - intro->intro_key = crypto_pk_new(); - tor_assert(!crypto_pk_generate_key(intro->intro_key)); - intro->time_published = -1; - intro->time_to_expire = -1; - intro->time_expiring = -1; - smartlist_add(service->intro_nodes, intro); - log_info(LD_REND, "Picked router %s as an intro point for %s.", - safe_str_client(node_describe(node)), - safe_str_client(service->service_id)); + log_info(LD_REND, "Checking for existing descriptor"); + log_info(LD_REND, "pk_digest %s", safe_str_client(service->service_id)); + + rend_cache_entry_t *entry; + int descriptor_available = (rend_cache_lookup_entry(service->service_id, -1, &entry) == 1); + + if (descriptor_available) { + // Need to think about connecting to these introduction points now + log_info(LD_REND, "Descriptor available for %s", safe_str_client(service->service_id)); + + SMARTLIST_FOREACH(entry->parsed->intro_nodes, rend_intro_point_t *, intro, { + log_info(LD_REND, "Found router %s as an existing intro point for %s.", + safe_str_client(node_describe(node)), + safe_str_client(service->service_id)); + + int existing = 0; + + SMARTLIST_FOREACH(service->intro_nodes, rend_intro_point_t *, existing_intro, { + // Unsure if this is the correct way to check + if (strcasecmp(existing_intro->extend_info->identity_digest, intro->extend_info->identity_digest) == 0) { + existing = 1; + // break, unsure if works + } + }); + + if (existing == 0) { + log_info(LD_REND, "Also connecting to %s.", + safe_str_client(node_describe(node))); + + rend_intro_point_t *new_intro = tor_malloc_zero(sizeof(rend_intro_point_t)); + memcpy((void*) new_intro, intro, sizeof(rend_intro_point_t)); + + intro->intro_key = crypto_pk_new(); + tor_assert(!crypto_pk_generate_key(intro->intro_key)); + intro->time_published = -1; + intro->time_to_expire = -1; + intro->time_expiring = -1; + + smartlist_add(service->intro_nodes, intro); + + intro_point_set_changed = 1; + } else { + log_info(LD_REND, "Already connected to %s, ignoring.", + safe_str_client(node_describe(node))); + } + }); + + log_info(LD_REND, "Finished checking introduction points for %s", safe_str_client(service->service_id)); + } else { + // If the descriptor has not been fetched recently + if (now > service->descriptor_fetch_time+(60*5)) { + // Example from rendclient.c:168 + + log_info(LD_REND, + "query %s didn't have valid rend desc in cache. " + "Fetching descriptor.", + safe_str_client(service->service_id)); + + rend_data_t *rend_data = tor_malloc_zero(sizeof(rend_data_t)); // remember to free + + strlcpy(rend_data->onion_address, service->service_id, + sizeof(rend_data->onion_address)); + + memcpy((void*) &rend_data->auth_type, + (void*) &service->auth_type, + sizeof(rend_auth_type_t)); + + rend_client_refetch_v2_renddesc(rend_data); + + service->descriptor_fetch_time = now; + + { // TODO: Unsure what this does? + connection_t *conn; + + while ((conn = connection_get_by_type_state_rendquery(CONN_TYPE_AP, + AP_CONN_STATE_CIRCUIT_WAIT, // Waiting for a circuit + rend_data->onion_address))) { + conn->state = AP_CONN_STATE_RENDDESC_WAIT; // Change state to waiting to receive the descriptor + } + } + } else { // Descriptor has been recently fetched + if (now > service->descriptor_fetch_time+30) { + // Forget about trying to get the descriptor + + log_info(LD_REND, + "query %s didn't have valid rend desc in cache. " + "Connecting to random introduction points", + safe_str_client(service->service_id)); + + /* We have enough directory information to start establishing our + * intro points. We want to end up with n_intro_points_wanted + * intro points, but if we're just starting, we launch two extra + * circuits and use the first n_intro_points_wanted that complete. + * + * The ones after the first three will be converted to 'general' + * internal circuits in rend_service_intro_has_opened(), and then + * we'll drop them from the list of intro points next time we + * go through the above "find out which introduction points we have + * in progress" loop. */ + n_intro_points_to_open = (service->n_intro_points_wanted + + (prev_intro_nodes == 0 ? 2 : 0)); + for (j = (int)n_intro_points_unexpired; + j < (int)n_intro_points_to_open; + ++j) { /* XXXX remove casts */ + router_crn_flags_t flags = CRN_NEED_UPTIME|CRN_NEED_DESC; + if (get_options()->AllowInvalid_ & ALLOW_INVALID_INTRODUCTION) + flags |= CRN_ALLOW_INVALID; + node = router_choose_random_node(intro_nodes, + options->ExcludeNodes, flags); + if (!node) { + log_warn(LD_REND, + "Could only establish %d introduction points for %s; " + "wanted %u.", + smartlist_len(service->intro_nodes), service->service_id, + n_intro_points_to_open); + break; + } + intro_point_set_changed = 1; + smartlist_add(intro_nodes, (void*)node); + intro = tor_malloc_zero(sizeof(rend_intro_point_t)); + intro->extend_info = extend_info_from_node(node, 0); + intro->intro_key = crypto_pk_new(); + tor_assert(!crypto_pk_generate_key(intro->intro_key)); + intro->time_published = -1; + intro->time_to_expire = -1; + intro->time_expiring = -1; + smartlist_add(service->intro_nodes, intro); + log_info(LD_REND, "Picked router %s as an intro point for %s.", + safe_str_client(node_describe(node)), + safe_str_client(service->service_id)); + } + } else { + // Continue wating for the descriptor + log_info(LD_REND, + "query %s didn't have valid rend desc in cache. " + "Waiting for descriptor", + safe_str_client(service->service_id)); + continue; + } + } } /* If there's no need to launch new circuits, stop here. */ |