Merge remote-tracking branch 'tor-gitlab/mr/51'

This commit is contained in:
Nick Mathewson 2020-07-20 16:50:32 -04:00
commit f5d773c600
11 changed files with 399 additions and 292 deletions

View File

@ -194,7 +194,7 @@ get_address_from_config(const or_options_t *options, int warn_severity,
char **hostname_out, tor_addr_t *addr_out)
{
int ret;
bool explicit_ip = false;
bool explicit_ip = false, resolve_failure = false;
int num_valid_addr = 0;
tor_assert(options);
@ -246,6 +246,7 @@ get_address_from_config(const or_options_t *options, int warn_severity,
continue;
} else {
/* Hostname that can't be resolved, this is a fatal error. */
resolve_failure = true;
log_fn(warn_severity, LD_CONFIG,
"Could not resolve local Address '%s'. Failing.", cfg->value);
continue;
@ -253,13 +254,16 @@ get_address_from_config(const or_options_t *options, int warn_severity,
}
if (!num_valid_addr) {
log_fn(warn_severity, LD_CONFIG,
"No Address option found for family %s in configuration.",
fmt_af_family(family));
/* No Address statement for family but one exists since Address is not
* NULL thus we have to stop now and not attempt to send back a guessed
* address. */
return FN_RET_BAIL;
if (resolve_failure) {
/* We found no address but we got a resolution failure. This means we
* can know if the hostname given was v4 or v6 so we can't continue. */
return FN_RET_BAIL;
}
log_info(LD_CONFIG,
"No Address option found for family %s in configuration.",
fmt_af_family(family));
/* No Address statement for family so move on to try next method. */
return FN_RET_NEXT;
}
if (num_valid_addr >= MAX_CONFIG_ADDRESS) {
@ -283,8 +287,8 @@ get_address_from_config(const or_options_t *options, int warn_severity,
}
/* Address can be used. We are done. */
log_fn(warn_severity, LD_CONFIG, "Address found in configuration: %s",
fmt_addr(addr_out));
log_info(LD_CONFIG, "Address found in configuration: %s",
fmt_addr(addr_out));
return FN_RET_OK;
}
@ -346,8 +350,8 @@ get_address_from_hostname(const or_options_t *options, int warn_severity,
*hostname_out = tor_strdup(hostname);
/* Found it! */
log_fn(warn_severity, LD_CONFIG, "Address found from local hostname: %s",
fmt_addr(addr_out));
log_info(LD_CONFIG, "Address found from local hostname: %s",
fmt_addr(addr_out));
return FN_RET_OK;
}
@ -398,8 +402,7 @@ get_address_from_interface(const or_options_t *options, int warn_severity,
*method_out = "INTERFACE";
/* Found it! */
log_fn(warn_severity, LD_CONFIG, "Address found from interface: %s",
fmt_addr(addr_out));
log_info(LD_CONFIG, "Address found from interface: %s", fmt_addr(addr_out));
return FN_RET_OK;
}
@ -729,3 +732,13 @@ is_local_to_resolve_addr, (const tor_addr_t *addr))
return false;
}
}
#ifdef TOR_UNIT_TESTS
void
resolve_addr_reset_suggested(int family)
{
tor_addr_make_unspec(&last_suggested_addrs[af_to_idx(family)]);
}
#endif /* TOR_UNIT_TESTS */

View File

@ -33,6 +33,12 @@ MOCK_DECL(bool, is_local_to_resolve_addr, (const tor_addr_t *addr));
#ifdef RESOLVE_ADDR_PRIVATE
#ifdef TOR_UNIT_TESTS
void resolve_addr_reset_suggested(int family);
#endif /* TOR_UNIT_TESTS */
#endif /* RESOLVE_ADDR_PRIVATE */
#endif /* TOR_CONFIG_RESOLVE_ADDR_H */

View File

@ -1643,17 +1643,26 @@ pt_get_extra_info_descriptor_string(void)
SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) {
char *transport_args = NULL;
const char *addrport = NULL;
/* If the transport proxy returned "0.0.0.0" as its address, and
* we know our external IP address, use it. Otherwise, use the
* returned address. */
const char *addrport = NULL;
uint32_t external_ip_address = 0;
if (tor_addr_is_null(&t->addr) &&
router_pick_published_address(get_options(),
&external_ip_address, 0) >= 0) {
if (tor_addr_is_null(&t->addr)) {
tor_addr_t addr;
tor_addr_from_ipv4h(&addr, external_ip_address);
/* Attempt to find the IPv4 and then attempt to find the IPv6 if we
* can't find it. */
bool found = relay_find_addr_to_publish(get_options(), AF_INET,
RELAY_FIND_ADDR_NO_FLAG,
&addr);
if (!found) {
found = relay_find_addr_to_publish(get_options(), AF_INET6,
RELAY_FIND_ADDR_NO_FLAG, &addr);
}
if (!found) {
log_err(LD_PT, "Unable to find address for transport %s", t->name);
continue;
}
addrport = fmt_addrport(&addr, t->port);
} else {
addrport = fmt_addrport(&t->addr, t->port);

View File

@ -132,12 +132,13 @@ getinfo_helper_misc(control_connection_t *conn, const char *question,
} else if (!strcmp(question, "features/names")) {
*answer = tor_strdup("VERBOSE_NAMES EXTENDED_EVENTS");
} else if (!strcmp(question, "address")) {
uint32_t addr;
if (router_pick_published_address(get_options(), &addr, 0) < 0) {
tor_addr_t addr;
if (!relay_find_addr_to_publish(get_options(), AF_INET,
RELAY_FIND_ADDR_CACHE_ONLY, &addr)) {
*errmsg = "Address unknown";
return -1;
}
*answer = tor_dup_ip(addr);
*answer = tor_addr_to_str_dup(&addr);
tor_assert_nonfatal(*answer);
} else if (!strcmp(question, "traffic/read")) {
tor_asprintf(answer, "%"PRIu64, (get_bytes_read()));

View File

@ -2106,7 +2106,13 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
if (conn->dirconn_direct) {
char *guess = http_get_header(headers, X_ADDRESS_HEADER);
if (guess) {
router_new_address_suggestion(guess, conn);
tor_addr_t addr;
if (tor_addr_parse(&addr, guess) < 0) {
log_debug(LD_DIR, "Malformed X-Your-Address-Is header %s. Ignoring.",
escaped(guess));
} else {
relay_address_new_suggestion(&addr, &TO_CONN(conn)->addr, NULL);
}
tor_free(guess);
}
}

View File

@ -40,15 +40,19 @@ int
dirclient_fetches_from_authorities(const or_options_t *options)
{
const routerinfo_t *me;
uint32_t addr;
int refuseunknown;
if (options->FetchDirInfoEarly)
return 1;
if (options->BridgeRelay == 1)
return 0;
if (server_mode(options) &&
router_pick_published_address(options, &addr, 1) < 0)
return 1; /* we don't know our IP address; ask an authority. */
/* We don't know our IP address; ask an authority. IPv4 is still mandatory
* to have thus if we don't have it, we ought to learn it from an authority
* through the NETINFO cell or the HTTP header it sends us back.
*
* Note that at the moment, relay do a direct connection so no NETINFO cell
* for now. */
if (server_mode(options) && !relay_has_address_set(AF_INET))
return 1;
refuseunknown = ! router_my_exit_policy_is_reject_star() &&
should_refuse_unknown_exits(options);
if (!dir_server_mode(options) && !refuseunknown)

View File

@ -20,29 +20,12 @@
#include "feature/relay/router.h"
#include "feature/relay/routermode.h"
/** The most recently guessed value of our IP address, based on directory
* headers. */
static tor_addr_t last_guessed_ip = TOR_ADDR_NULL;
/** We failed to resolve our address locally, but we'd like to build
* a descriptor and publish / test reachability. If we have a guess
* about our address based on directory headers, answer it and return
* 0; else return -1. */
static int
router_guess_address_from_dir_headers(uint32_t *guess)
{
if (!tor_addr_is_null(&last_guessed_ip)) {
*guess = tor_addr_to_ipv4h(&last_guessed_ip);
return 0;
}
return -1;
}
/** Consider the address suggestion suggested_addr as a possible one to use as
* our address.
*
* This is called when a valid NETINFO cell is recevied containing a candidate
* for our address.
* This is called when a valid NETINFO cell is received containing a candidate
* for our address or when a directory sends us back the X-Your-Address-Is
* header.
*
* The suggested address is ignored if it does NOT come from a trusted source.
* At the moment, we only look a trusted directory authorities.
@ -51,6 +34,9 @@ router_guess_address_from_dir_headers(uint32_t *guess)
* given peer_addr which is the address from the endpoint that sent the
* NETINFO cell.
*
* The identity_digest is NULL if this is an address suggested by a directory
* since this is a plaintext connection.
*
* The suggested address is set in our suggested address cache if everything
* passes. */
void
@ -62,7 +48,6 @@ relay_address_new_suggestion(const tor_addr_t *suggested_addr,
tor_assert(suggested_addr);
tor_assert(peer_addr);
tor_assert(identity_digest);
/* Non server should just ignore this suggestion. Clients don't need to
* learn their address let alone cache it. */
@ -73,7 +58,7 @@ relay_address_new_suggestion(const tor_addr_t *suggested_addr,
/* Is the peer a trusted source? Ignore anything coming from non trusted
* source. In this case, we only look at trusted directory authorities. */
if (!router_addr_is_trusted_dir(peer_addr) ||
!router_digest_is_trusted_dir(identity_digest)) {
(identity_digest && !router_digest_is_trusted_dir(identity_digest))) {
return;
}
@ -95,110 +80,67 @@ relay_address_new_suggestion(const tor_addr_t *suggested_addr,
resolved_addr_set_suggested(suggested_addr);
}
/** A directory server <b>d_conn</b> told us our IP address is
* <b>suggestion</b>.
* If this address is different from the one we think we are now, and
* if our computer doesn't actually know its IP address, then switch. */
void
router_new_address_suggestion(const char *suggestion,
const dir_connection_t *d_conn)
{
tor_addr_t addr, my_addr, last_resolved_addr;
const or_options_t *options = get_options();
/* first, learn what the IP address actually is */
if (tor_addr_parse(&addr, suggestion) == -1) {
log_debug(LD_DIR, "Malformed X-Your-Address-Is header %s. Ignoring.",
escaped(suggestion));
return;
}
log_debug(LD_DIR, "Got X-Your-Address-Is: %s.", suggestion);
if (!server_mode(options)) {
tor_addr_copy(&last_guessed_ip, &addr);
return;
}
/* XXXX ipv6 */
resolved_addr_get_last(AF_INET, &last_resolved_addr);
if (!tor_addr_is_null(&last_resolved_addr)) {
/* Lets use this one. */
tor_addr_copy(&last_guessed_ip, &last_resolved_addr);
return;
}
/* Attempt to find our address. */
if (find_my_address(options, AF_INET, LOG_INFO, &my_addr, NULL, NULL)) {
/* We're all set -- we already know our address. Great. */
tor_addr_copy(&last_guessed_ip, &my_addr); /* store it in case we
need it later */
return;
}
/* Consider the suggestion from the directory. */
if (tor_addr_is_internal(&addr, 0)) {
/* Don't believe anybody who says our IP is, say, 127.0.0.1. */
return;
}
if (tor_addr_eq(&d_conn->base_.addr, &addr)) {
/* Don't believe anybody who says our IP is their IP. */
log_debug(LD_DIR, "A directory server told us our IP address is %s, "
"but they are just reporting their own IP address. Ignoring.",
suggestion);
return;
}
/* Okay. We can't resolve our own address, and X-Your-Address-Is is giving
* us an answer different from what we had the last time we managed to
* resolve it. */
if (!tor_addr_eq(&last_guessed_ip, &addr)) {
control_event_server_status(LOG_NOTICE,
"EXTERNAL_ADDRESS ADDRESS=%s METHOD=DIRSERV",
suggestion);
log_addr_has_changed(LOG_NOTICE, &last_guessed_ip, &addr,
d_conn->base_.address);
ip_address_changed(0);
tor_addr_copy(&last_guessed_ip, &addr); /* router_rebuild_descriptor()
will fetch it */
}
}
/** Make a current best guess at our address, either because
* it's configured in torrc, or because we've learned it from
* dirserver headers. Place the answer in *<b>addr</b> and return
* 0 on success, else return -1 if we have no guess.
/** Find our address to be published in our descriptor. Three places are
* looked at:
*
* If <b>cache_only</b> is true, just return any cached answers, and
* don't try to get any new answers.
*/
MOCK_IMPL(int,
router_pick_published_address, (const or_options_t *options, uint32_t *addr,
int cache_only))
* 1. Resolved cache. Populated by find_my_address() during the relay
* periodic event that attempts to learn if our address has changed.
*
* 2. If flags is set with RELAY_FIND_ADDR_CACHE_ONLY, only the resolved
* and suggested cache are looked at. No address discovery will be done.
*
* 3. Finally, if all fails, use the suggested address cache which is
* populated by the NETINFO cell content or HTTP header from a
* directory.
*
* Return true on success and addr_out contains the address to use for the
* given family. On failure to find the address, false is returned and
* addr_out is set to an AF_UNSPEC address. */
MOCK_IMPL(bool,
relay_find_addr_to_publish, (const or_options_t *options, int family,
int flags, tor_addr_t *addr_out))
{
tor_addr_t last_resolved_addr;
tor_assert(options);
tor_assert(addr_out);
/* First, check the cached output from find_my_address(). */
resolved_addr_get_last(AF_INET, &last_resolved_addr);
if (!tor_addr_is_null(&last_resolved_addr)) {
*addr = tor_addr_to_ipv4h(&last_resolved_addr);
return 0;
tor_addr_make_unspec(addr_out);
/* First, check our resolved address cache. It should contain the address
* we've discovered from the periodic relay event. */
resolved_addr_get_last(family, addr_out);
if (!tor_addr_is_null(addr_out)) {
goto found;
}
/* Second, consider doing a resolve attempt right here. */
if (!cache_only) {
tor_addr_t my_addr;
if (find_my_address(options, AF_INET, LOG_INFO, &my_addr, NULL, NULL)) {
log_info(LD_CONFIG,"Success: chose address '%s'.", fmt_addr(&my_addr));
*addr = tor_addr_to_ipv4h(&my_addr);
return 0;
/* Second, attempt to find our address. The following can do a DNS resolve
* thus only do it when the no cache only flag is flipped. */
if (!(flags & RELAY_FIND_ADDR_CACHE_ONLY)) {
if (find_my_address(options, family, LOG_INFO, addr_out, NULL, NULL)) {
goto found;
}
}
/* Third, check the cached output from router_new_address_suggestion(). */
if (router_guess_address_from_dir_headers(addr) >= 0)
return 0;
/* Third, consider address from our suggestion cache. */
resolved_addr_get_suggested(family, addr_out);
if (!tor_addr_is_null(addr_out)) {
goto found;
}
/* We have no useful cached answers. Return failure. */
return -1;
/* No publishable address was found. */
return false;
found:
return true;
}
/** Return true iff this relay has an address set for the given family.
*
* This only checks the caches so it will not trigger a full discovery of the
* address. */
bool
relay_has_address_set(int family)
{
tor_addr_t addr;
return relay_find_addr_to_publish(get_options(), family,
RELAY_FIND_ADDR_CACHE_ONLY, &addr);
}

View File

@ -9,16 +9,21 @@
#ifndef TOR_RELAY_FIND_ADDR_H
#define TOR_RELAY_FIND_ADDR_H
MOCK_DECL(int, router_pick_published_address,
(const or_options_t *options, uint32_t *addr, int cache_only));
void router_new_address_suggestion(const char *suggestion,
const dir_connection_t *d_conn);
typedef enum {
RELAY_FIND_ADDR_NO_FLAG = (1U << 0),
RELAY_FIND_ADDR_CACHE_ONLY = (1U << 1),
} relay_find_addr_flags_t;
void relay_address_new_suggestion(const tor_addr_t *suggested_addr,
const tor_addr_t *peer_addr,
const char *identity_digest);
MOCK_DECL(bool, relay_find_addr_to_publish,
(const or_options_t *options, int family, int flags,
tor_addr_t *addr_out));
bool relay_has_address_set(int family);
#ifdef RELAY_FIND_ADDR_PRIVATE
#endif /* RELAY_FIND_ADDR_PRIVATE */

View File

@ -38,6 +38,7 @@
#include "feature/relay/dns.h"
#include "feature/relay/relay_config.h"
#include "feature/relay/relay_find_addr.h"
#include "feature/relay/relay_periodic.h"
#include "feature/relay/router.h"
#include "feature/relay/routerkeys.h"
#include "feature/relay/routermode.h"
@ -1757,16 +1758,6 @@ router_get_my_routerinfo_with_err,(int *err))
return NULL;
}
if (!desc_clean_since) {
int rebuild_err = router_rebuild_descriptor(0);
if (rebuild_err < 0) {
if (err)
*err = rebuild_err;
return NULL;
}
}
if (!desc_routerinfo) {
if (err)
*err = TOR_ROUTERINFO_ERROR_DESC_REBUILDING;
@ -1822,54 +1813,55 @@ router_get_descriptor_gen_reason(void)
* ORPort or DirPort.
* listener_type is either CONN_TYPE_OR_LISTENER or CONN_TYPE_DIR_LISTENER. */
static void
router_check_descriptor_address_port_consistency(uint32_t ipv4h_desc_addr,
router_check_descriptor_address_port_consistency(const tor_addr_t *addr,
int listener_type)
{
int family, port_cfg;
tor_assert(addr);
tor_assert(listener_type == CONN_TYPE_OR_LISTENER ||
listener_type == CONN_TYPE_DIR_LISTENER);
/* The first advertised Port may be the magic constant CFG_AUTO_PORT.
*/
int port_v4_cfg = get_first_advertised_port_by_type_af(listener_type,
AF_INET);
if (port_v4_cfg != 0 &&
!port_exists_by_type_addr32h_port(listener_type,
ipv4h_desc_addr, port_v4_cfg, 1)) {
const tor_addr_t *port_addr = get_first_advertised_addr_by_type_af(
listener_type,
AF_INET);
/* If we're building a descriptor with no advertised address,
* something is terribly wrong. */
tor_assert(port_addr);
family = tor_addr_family(addr);
/* The first advertised Port may be the magic constant CFG_AUTO_PORT. */
port_cfg = get_first_advertised_port_by_type_af(listener_type, family);
if (port_cfg != 0 &&
!port_exists_by_type_addr_port(listener_type, addr, port_cfg, 1)) {
const tor_addr_t *port_addr =
get_first_advertised_addr_by_type_af(listener_type, family);
/* If we're building a descriptor with no advertised address,
* something is terribly wrong. */
tor_assert(port_addr);
tor_addr_t desc_addr;
char port_addr_str[TOR_ADDR_BUF_LEN];
char desc_addr_str[TOR_ADDR_BUF_LEN];
char port_addr_str[TOR_ADDR_BUF_LEN];
char desc_addr_str[TOR_ADDR_BUF_LEN];
tor_addr_to_str(port_addr_str, port_addr, TOR_ADDR_BUF_LEN, 0);
tor_addr_to_str(port_addr_str, port_addr, TOR_ADDR_BUF_LEN, 0);
tor_addr_to_str(desc_addr_str, addr, TOR_ADDR_BUF_LEN, 0);
tor_addr_from_ipv4h(&desc_addr, ipv4h_desc_addr);
tor_addr_to_str(desc_addr_str, &desc_addr, TOR_ADDR_BUF_LEN, 0);
const char *listener_str = (listener_type == CONN_TYPE_OR_LISTENER ?
"OR" : "Dir");
log_warn(LD_CONFIG, "The IPv4 %sPort address %s does not match the "
"descriptor address %s. If you have a static public IPv4 "
"address, use 'Address <IPv4>' and 'OutboundBindAddress "
"<IPv4>'. If you are behind a NAT, use two %sPort lines: "
"'%sPort <PublicPort> NoListen' and '%sPort <InternalPort> "
"NoAdvertise'.",
listener_str, port_addr_str, desc_addr_str, listener_str,
listener_str, listener_str);
}
const char *listener_str = (listener_type == CONN_TYPE_OR_LISTENER ?
"OR" : "Dir");
const char *af_str = fmt_af_family(family);
log_warn(LD_CONFIG, "The %s %sPort address %s does not match the "
"descriptor address %s. If you have a static public IPv4 "
"address, use 'Address <%s>' and 'OutboundBindAddress "
"<%s>'. If you are behind a NAT, use two %sPort lines: "
"'%sPort <PublicPort> NoListen' and '%sPort <InternalPort> "
"NoAdvertise'.",
af_str, listener_str, port_addr_str, desc_addr_str, af_str,
af_str, listener_str, listener_str, listener_str);
}
}
/* Tor relays only have one IPv4 address in the descriptor, which is derived
* from the Address torrc option, or guessed using various methods in
* router_pick_published_address().
* Warn the operator if there is no ORPort on the descriptor address
* ipv4h_desc_addr.
/** Tor relays only have one IPv4 or/and one IPv6 address in the descriptor,
* which is derived from the Address torrc option, or guessed using various
* methods in relay_find_addr_to_publish().
*
* Warn the operator if there is no ORPort associated with the given address
* in addr.
*
* Warn the operator if there is no DirPort on the descriptor address.
*
* This catches a few common config errors:
* - operators who expect ORPorts and DirPorts to be advertised on the
* ports' listen addresses, rather than the torrc Address (or guessed
@ -1878,20 +1870,22 @@ router_check_descriptor_address_port_consistency(uint32_t ipv4h_desc_addr,
* addresses;
* - discrepancies between guessed addresses and configured listen
* addresses (when the Address option isn't set).
*
* If a listener is listening on all IPv4 addresses, it is assumed that it
* is listening on the configured Address, and no messages are logged.
*
* If an operators has specified NoAdvertise ORPorts in a NAT setting,
* no messages are logged, unless they have specified other advertised
* addresses.
*
* The message tells operators to configure an ORPort and DirPort that match
* the Address (using NoListen if needed).
*/
* the Address (using NoListen if needed). */
static void
router_check_descriptor_address_consistency(uint32_t ipv4h_desc_addr)
router_check_descriptor_address_consistency(const tor_addr_t *addr)
{
router_check_descriptor_address_port_consistency(ipv4h_desc_addr,
router_check_descriptor_address_port_consistency(addr,
CONN_TYPE_OR_LISTENER);
router_check_descriptor_address_port_consistency(ipv4h_desc_addr,
router_check_descriptor_address_port_consistency(addr,
CONN_TYPE_DIR_LISTENER);
}
@ -2033,7 +2027,7 @@ MOCK_IMPL(STATIC int,
router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out))
{
routerinfo_t *ri = NULL;
uint32_t addr;
tor_addr_t ipv4_addr, ipv6_addr;
char platform[256];
int hibernating = we_are_hibernating();
const or_options_t *options = get_options();
@ -2044,22 +2038,41 @@ router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out))
goto err;
}
if (router_pick_published_address(options, &addr, 0) < 0) {
/* Find our resolved address both IPv4 and IPv6. In case the address is not
* found, the object is set to an UNSPEC address. */
bool have_v4 = relay_find_addr_to_publish(options, AF_INET,
RELAY_FIND_ADDR_NO_FLAG,
&ipv4_addr);
bool have_v6 = relay_find_addr_to_publish(options, AF_INET6,
RELAY_FIND_ADDR_NO_FLAG,
&ipv6_addr);
/* Tor requires a relay to have an IPv4 so bail if we can't find it. */
if (!have_v4) {
log_warn(LD_CONFIG, "Don't know my address while generating descriptor");
result = TOR_ROUTERINFO_ERROR_NO_EXT_ADDR;
goto err;
}
/* Log a message if the address in the descriptor doesn't match the ORPort
* and DirPort addresses configured by the operator. */
router_check_descriptor_address_consistency(addr);
router_check_descriptor_address_consistency(&ipv4_addr);
router_check_descriptor_address_consistency(&ipv6_addr);
ri = tor_malloc_zero(sizeof(routerinfo_t));
ri->cache_info.routerlist_index = -1;
ri->nickname = tor_strdup(options->Nickname);
tor_addr_from_ipv4h(&ri->ipv4_addr, addr);
ri->ipv4_orport = router_get_advertised_or_port(options);
/* IPv4. */
tor_addr_copy(&ri->ipv4_addr, &ipv4_addr);
ri->ipv4_orport = router_get_advertised_or_port_by_af(options, AF_INET);
ri->ipv4_dirport = router_get_advertised_dir_port(options, 0);
/* IPv6. */
if (have_v6) {
tor_addr_copy(&ri->ipv6_addr, &ipv6_addr);
ri->ipv6_orport = router_get_advertised_or_port_by_af(options, AF_INET6);
}
ri->supports_tunnelled_dir_requests =
directory_permits_begindir_requests(options);
ri->cache_info.published_on = time(NULL);
@ -2071,13 +2084,6 @@ router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out))
tor_memdup(&get_current_curve25519_keypair()->pubkey,
sizeof(curve25519_public_key_t));
/* For now, at most one IPv6 or-address is being advertised. */
tor_addr_port_t ipv6_orport;
router_get_advertised_ipv6_or_ap(options, &ipv6_orport);
/* If there is no valid IPv6 ORPort, the address and port are null. */
tor_addr_copy(&ri->ipv6_addr, &ipv6_orport.addr);
ri->ipv6_orport = ipv6_orport.port;
ri->identity_pkey = crypto_pk_dup_key(get_server_identity_key());
if (BUG(crypto_pk_get_digest(ri->identity_pkey,
ri->cache_info.identity_digest) < 0)) {
@ -2389,21 +2395,10 @@ router_rebuild_descriptor(int force)
int err = 0;
routerinfo_t *ri;
extrainfo_t *ei;
uint32_t addr;
const or_options_t *options = get_options();
if (desc_clean_since && !force)
return 0;
if (router_pick_published_address(options, &addr, 0) < 0 ||
router_get_advertised_or_port(options) == 0) {
/* Stop trying to rebuild our descriptor every second. We'll
* learn that it's time to try again when ip_address_changed()
* marks it dirty. */
desc_clean_since = time(NULL);
return TOR_ROUTERINFO_ERROR_DESC_REBUILDING;
}
log_info(LD_OR, "Rebuilding relay descriptor%s", force ? " (forced)" : "");
err = router_build_fresh_descriptor(&ri, &ei);
@ -2503,11 +2498,13 @@ mark_my_descriptor_dirty(const char *reason)
if (BUG(reason == NULL)) {
reason = "marked descriptor dirty for unspecified reason";
}
if (server_mode(options) && options->PublishServerDescriptor_)
if (server_mode(options) && options->PublishServerDescriptor_) {
log_info(LD_OR, "Decided to publish new relay descriptor: %s", reason);
}
desc_clean_since = 0;
if (!desc_dirty_reason)
desc_dirty_reason = reason;
reschedule_descriptor_update_check();
}
/** How frequently will we republish our descriptor because of large (factor

View File

@ -1290,10 +1290,6 @@ test_config_find_my_address_mixed(void *arg)
"2a01:4f8:fff0:4f:266:37ff:fe2c:5d19");
tor_addr_parse(&test_addr, "2a01:4f8:fff0:4f:266:37ff:fe2c:5d19");
/* IPv4 address not guessed since one Address statement exists. */
retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
&method_used, &hostname_out);
VALIDATE_FOUND_ADDRESS(false, NULL, NULL);
/* IPv6 address should be found and considered configured. */
retval = find_my_address(options, AF_INET6, LOG_NOTICE, &resolved_addr,
&method_used, &hostname_out);
@ -1542,49 +1538,6 @@ test_config_find_my_address(void *arg)
VALIDATE_FOUND_ADDRESS(false, NULL, NULL);
CLEANUP_FOUND_ADDRESS;
/*
* Case 6: Another address family is configured. Expected to fail.
*/
if (p->family == AF_INET) {
config_line_append(&options->Address, "Address", "4242::4242");
} else {
config_line_append(&options->Address, "Address", "1.1.1.1");
}
setup_full_capture_of_logs(LOG_NOTICE);
retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
&method_used, &hostname_out);
expect_log_msg_containing("No Address option found for family");
teardown_capture_of_logs();
VALIDATE_FOUND_ADDRESS(false, NULL, NULL);
CLEANUP_FOUND_ADDRESS;
/*
* Case 7: Address is a non resolvable hostname. Expected to fail.
*/
MOCK(tor_addr_lookup, tor_addr_lookup_failure);
config_line_append(&options->Address, "Address", "www.torproject.org");
prev_n_hostname_failure = n_hostname_failure;
setup_full_capture_of_logs(LOG_NOTICE);
retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
&method_used, &hostname_out);
expect_log_msg_containing("Could not resolve local Address "
"'www.torproject.org'. Failing.");
teardown_capture_of_logs();
tt_int_op(n_hostname_failure, OP_EQ, ++prev_n_hostname_failure);
VALIDATE_FOUND_ADDRESS(false, NULL, NULL);
CLEANUP_FOUND_ADDRESS;
UNMOCK(tor_addr_lookup);
/*
* Case 8:
* 1. Address is NULL
@ -3889,16 +3842,17 @@ test_config_default_dir_servers(void *arg)
or_options_free(opts);
}
static int mock_router_pick_published_address_result = 0;
static bool mock_relay_find_addr_to_publish_result = true;
static int
mock_router_pick_published_address(const or_options_t *options,
uint32_t *addr, int cache_only)
static bool
mock_relay_find_addr_to_publish(const or_options_t *options, int family,
int flags, tor_addr_t *addr_out)
{
(void)options;
(void)addr;
(void)cache_only;
return mock_router_pick_published_address_result;
(void) options;
(void) family;
(void) flags;
(void) addr_out;
return mock_relay_find_addr_to_publish_result;
}
static int mock_router_my_exit_policy_is_reject_star_result = 0;
@ -3934,11 +3888,11 @@ test_config_directory_fetch(void *arg)
or_options_t *options = options_new();
routerinfo_t routerinfo;
memset(&routerinfo, 0, sizeof(routerinfo));
mock_router_pick_published_address_result = -1;
mock_relay_find_addr_to_publish_result = false;
mock_router_my_exit_policy_is_reject_star_result = 1;
mock_advertised_server_mode_result = 0;
mock_router_get_my_routerinfo_result = NULL;
MOCK(router_pick_published_address, mock_router_pick_published_address);
MOCK(relay_find_addr_to_publish, mock_relay_find_addr_to_publish);
MOCK(router_my_exit_policy_is_reject_star,
mock_router_my_exit_policy_is_reject_star);
MOCK(advertised_server_mode, mock_advertised_server_mode);
@ -3994,14 +3948,14 @@ test_config_directory_fetch(void *arg)
options = options_new();
options->ORPort_set = 1;
mock_router_pick_published_address_result = -1;
mock_relay_find_addr_to_publish_result = false;
tt_assert(server_mode(options) == 1);
tt_assert(public_server_mode(options) == 1);
tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 1);
tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
OP_EQ, 0);
mock_router_pick_published_address_result = 0;
mock_relay_find_addr_to_publish_result = true;
tt_assert(server_mode(options) == 1);
tt_assert(public_server_mode(options) == 1);
tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 0);
@ -4015,7 +3969,7 @@ test_config_directory_fetch(void *arg)
options = options_new();
options->ORPort_set = 1;
options->ExitRelay = 1;
mock_router_pick_published_address_result = 0;
mock_relay_find_addr_to_publish_result = true;
mock_router_my_exit_policy_is_reject_star_result = 0;
mock_advertised_server_mode_result = 1;
mock_router_get_my_routerinfo_result = &routerinfo;
@ -4030,7 +3984,7 @@ test_config_directory_fetch(void *arg)
OP_EQ, 0);
options->RefuseUnknownExits = 0;
mock_router_pick_published_address_result = 0;
mock_relay_find_addr_to_publish_result = true;
tt_assert(server_mode(options) == 1);
tt_assert(public_server_mode(options) == 1);
tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 0);
@ -4047,7 +4001,7 @@ test_config_directory_fetch(void *arg)
options->DirPort_set = 1;
options->ORPort_set = 1;
options->DirCache = 1;
mock_router_pick_published_address_result = 0;
mock_relay_find_addr_to_publish_result = true;
mock_router_my_exit_policy_is_reject_star_result = 1;
mock_advertised_server_mode_result = 1;
@ -4098,7 +4052,7 @@ test_config_directory_fetch(void *arg)
done:
or_options_free(options);
UNMOCK(router_pick_published_address);
UNMOCK(relay_find_addr_to_publish);
UNMOCK(router_get_my_routerinfo);
UNMOCK(advertised_server_mode);
UNMOCK(router_my_exit_policy_is_reject_star);

View File

@ -17,6 +17,14 @@
#include "core/or/cell_st.h"
#include "core/or/or_circuit_st.h"
#define RESOLVE_ADDR_PRIVATE
#include "feature/nodelist/dirlist.h"
#include "feature/relay/relay_find_addr.h"
#include "feature/relay/routermode.h"
#include "feature/dirclient/dir_server_st.h"
#include "app/config/resolve_addr.h"
/* Test suite stuff */
#include "test/test.h"
#include "test/fakechans.h"
@ -24,6 +32,13 @@
static void test_relay_append_cell_to_circuit_queue(void *arg);
static int
mock_server_mode_true(const or_options_t *options)
{
(void) options;
return 1;
}
static void
assert_circuit_ok_mock(const circuit_t *c)
{
@ -192,10 +207,165 @@ test_relay_append_cell_to_circuit_queue(void *arg)
return;
}
static void
test_suggested_address(void *arg)
{
int ret;
const char *untrusted_id = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
dir_server_t *ds = NULL;
tor_addr_t ipv4_addr, ipv6_addr, cache_addr;
tor_addr_t trusted_addr, untrusted_addr;
tor_addr_port_t trusted_ap_v6 = { .port = 443 };
(void) arg;
MOCK(server_mode, mock_server_mode_true);
/* Unstrusted relay source. */
ret = tor_addr_parse(&untrusted_addr, "8.8.8.8");
tt_int_op(ret, OP_EQ, AF_INET);
/* Add gabelmoo as a trusted directory authority. */
ret = tor_addr_parse(&trusted_addr, "[2001:638:a000:4140::ffff:189]");
tt_int_op(ret, OP_EQ, AF_INET6);
tor_addr_copy(&trusted_ap_v6.addr, &trusted_addr);
ds = trusted_dir_server_new("gabelmoo", "131.188.40.189", 80, 443,
&trusted_ap_v6,
"F2044413DAC2E02E3D6BCF4735A19BCA1DE97281",
"ED03BB616EB2F60BEC80151114BB25CEF515B226",
V3_DIRINFO, 1.0);
tt_assert(ds);
dir_server_add(ds);
/* 1. Valid IPv4 from a trusted authority (gabelmoo). */
ret = tor_addr_parse(&ipv4_addr, "1.2.3.4");
relay_address_new_suggestion(&ipv4_addr, &ds->ipv4_addr, ds->digest);
resolved_addr_get_suggested(AF_INET, &cache_addr);
tt_assert(tor_addr_eq(&cache_addr, &ipv4_addr));
resolve_addr_reset_suggested(AF_INET);
/* 2. Valid IPv6 from a trusted authority (gabelmoo). */
ret = tor_addr_parse(&ipv6_addr, "[4242::4242]");
relay_address_new_suggestion(&ipv6_addr, &ds->ipv6_addr, ds->digest);
resolved_addr_get_suggested(AF_INET6, &cache_addr);
tt_assert(tor_addr_eq(&cache_addr, &ipv6_addr));
resolve_addr_reset_suggested(AF_INET6);
/* 3. Valid IPv4 but untrusted source. */
ret = tor_addr_parse(&ipv4_addr, "1.2.3.4");
relay_address_new_suggestion(&ipv4_addr, &untrusted_addr, untrusted_id);
resolved_addr_get_suggested(AF_INET, &cache_addr);
tt_assert(tor_addr_is_unspec(&cache_addr));
/* 4. Valid IPv6 but untrusted source. */
ret = tor_addr_parse(&ipv6_addr, "[4242::4242]");
relay_address_new_suggestion(&ipv6_addr, &untrusted_addr, untrusted_id);
resolved_addr_get_suggested(AF_INET6, &cache_addr);
tt_assert(tor_addr_is_unspec(&cache_addr));
/* 5. Internal IPv4 from a trusted authority (gabelmoo). */
ret = tor_addr_parse(&ipv4_addr, "127.0.0.1");
relay_address_new_suggestion(&ipv4_addr, &ds->ipv4_addr, ds->digest);
resolved_addr_get_suggested(AF_INET, &cache_addr);
tt_assert(tor_addr_is_unspec(&cache_addr));
/* 6. Internal IPv6 from a trusted authority (gabelmoo). */
ret = tor_addr_parse(&ipv6_addr, "[::1]");
relay_address_new_suggestion(&ipv6_addr, &ds->ipv6_addr, ds->digest);
resolved_addr_get_suggested(AF_INET6, &cache_addr);
tt_assert(tor_addr_is_unspec(&cache_addr));
/* 7. IPv4 from a trusted authority (gabelmoo). */
relay_address_new_suggestion(&ds->ipv4_addr, &ds->ipv4_addr, ds->digest);
resolved_addr_get_suggested(AF_INET, &cache_addr);
tt_assert(tor_addr_is_unspec(&cache_addr));
/* 8. IPv6 from a trusted authority (gabelmoo). */
relay_address_new_suggestion(&ds->ipv6_addr, &ds->ipv6_addr, ds->digest);
resolved_addr_get_suggested(AF_INET6, &cache_addr);
tt_assert(tor_addr_is_unspec(&cache_addr));
done:
dirlist_free_all();
UNMOCK(server_mode);
}
static void
test_find_addr_to_publish(void *arg)
{
int family;
bool ret;
tor_addr_t ipv4_addr, ipv6_addr, cache_addr;
or_options_t options;
(void) arg;
/* Populate our resolved cache with a valid IPv4 and IPv6. */
family = tor_addr_parse(&ipv4_addr, "1.2.3.4");
tt_int_op(family, OP_EQ, AF_INET);
resolved_addr_set_last(&ipv4_addr, "NA", NULL);
resolved_addr_get_last(AF_INET, &cache_addr);
tt_assert(tor_addr_eq(&ipv4_addr, &cache_addr));
family = tor_addr_parse(&ipv6_addr, "[4242::4242]");
tt_int_op(family, OP_EQ, AF_INET6);
resolved_addr_set_last(&ipv6_addr, "NA", NULL);
resolved_addr_get_last(AF_INET6, &cache_addr);
tt_assert(tor_addr_eq(&ipv6_addr, &cache_addr));
/* 1. Address located in the resolved cache. */
ret = relay_find_addr_to_publish(&options, AF_INET,
RELAY_FIND_ADDR_CACHE_ONLY, &cache_addr);
tt_assert(ret);
tt_assert(tor_addr_eq(&ipv4_addr, &cache_addr));
ret = relay_find_addr_to_publish(&options, AF_INET6,
RELAY_FIND_ADDR_CACHE_ONLY, &cache_addr);
tt_assert(ret);
tt_assert(tor_addr_eq(&ipv6_addr, &cache_addr));
resolved_addr_reset_last(AF_INET);
resolved_addr_reset_last(AF_INET6);
/* 2. No IP in the resolve cache, go to the suggested cache. We will ignore
* the find_my_address() code path because that is extensively tested in
* another unit tests. */
resolved_addr_set_suggested(&ipv4_addr);
ret = relay_find_addr_to_publish(&options, AF_INET,
RELAY_FIND_ADDR_CACHE_ONLY, &cache_addr);
tt_assert(ret);
tt_assert(tor_addr_eq(&ipv4_addr, &cache_addr));
resolved_addr_set_suggested(&ipv6_addr);
ret = relay_find_addr_to_publish(&options, AF_INET6,
RELAY_FIND_ADDR_CACHE_ONLY, &cache_addr);
tt_assert(ret);
tt_assert(tor_addr_eq(&ipv6_addr, &cache_addr));
resolve_addr_reset_suggested(AF_INET);
resolve_addr_reset_suggested(AF_INET6);
/* 3. No IP anywhere. */
ret = relay_find_addr_to_publish(&options, AF_INET,
RELAY_FIND_ADDR_CACHE_ONLY, &cache_addr);
tt_assert(!ret);
ret = relay_find_addr_to_publish(&options, AF_INET6,
RELAY_FIND_ADDR_CACHE_ONLY, &cache_addr);
tt_assert(!ret);
done:
;
}
struct testcase_t relay_tests[] = {
{ "append_cell_to_circuit_queue", test_relay_append_cell_to_circuit_queue,
TT_FORK, NULL, NULL },
{ "close_circ_rephist", test_relay_close_circuit,
TT_FORK, NULL, NULL },
{ "suggested_address", test_suggested_address,
TT_FORK, NULL, NULL },
{ "find_addr_to_publish", test_find_addr_to_publish,
TT_FORK, NULL, NULL },
END_OF_TESTCASES
};