mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-27 22:03:31 +01:00
Merge remote-tracking branch 'tor-github/pr/1827/head' into maint-0.3.5
This commit is contained in:
commit
741edf1b45
4
changes/bug32588
Normal file
4
changes/bug32588
Normal file
@ -0,0 +1,4 @@
|
||||
o Minor bugfixes (relays):
|
||||
- Stop advertising incorrect IPv6 ORPorts in relay and bridge descriptors,
|
||||
when the IPv6 port was configured as "auto".
|
||||
Fixes bug 32588; bugfix on 0.2.3.9-alpha
|
@ -809,9 +809,6 @@ static int normalize_nickname_list(config_line_t **normalized_out,
|
||||
char **msg);
|
||||
static char *get_bindaddr_from_transport_listen_line(const char *line,
|
||||
const char *transport);
|
||||
static int parse_ports(or_options_t *options, int validate_only,
|
||||
char **msg_out, int *n_ports_out,
|
||||
int *world_writable_control_socket);
|
||||
static int check_server_ports(const smartlist_t *ports,
|
||||
const or_options_t *options,
|
||||
int *num_low_ports_out);
|
||||
@ -7375,7 +7372,7 @@ count_real_listeners(const smartlist_t *ports, int listenertype,
|
||||
* If <b>validate_only</b> is false, set configured_client_ports to the
|
||||
* new list of ports parsed from <b>options</b>.
|
||||
**/
|
||||
static int
|
||||
STATIC int
|
||||
parse_ports(or_options_t *options, int validate_only,
|
||||
char **msg, int *n_ports_out,
|
||||
int *world_writable_control_socket)
|
||||
|
@ -295,6 +295,10 @@ STATIC int open_and_add_file_log(const log_severity_list_t *severity,
|
||||
const char *fname,
|
||||
int truncate_log);
|
||||
|
||||
STATIC int parse_ports(or_options_t *options, int validate_only,
|
||||
char **msg, int *n_ports_out,
|
||||
int *world_writable_control_socket);
|
||||
|
||||
#endif /* defined(CONFIG_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_CONFIG_H) */
|
||||
|
@ -1433,6 +1433,50 @@ router_get_advertised_or_port_by_af(const or_options_t *options,
|
||||
return port;
|
||||
}
|
||||
|
||||
/** As router_get_advertised_or_port(), but returns the IPv6 address and
|
||||
* port in ipv6_ap_out, which must not be NULL. Returns a null address and
|
||||
* zero port, if no ORPort is found. */
|
||||
void
|
||||
router_get_advertised_ipv6_or_ap(const or_options_t *options,
|
||||
tor_addr_port_t *ipv6_ap_out)
|
||||
{
|
||||
/* Bug in calling function, we can't return a sensible result, and it
|
||||
* shouldn't use the NULL pointer once we return. */
|
||||
tor_assert(ipv6_ap_out);
|
||||
|
||||
/* If there is no valid IPv6 ORPort, return a null address and port. */
|
||||
tor_addr_make_null(&ipv6_ap_out->addr, AF_INET6);
|
||||
ipv6_ap_out->port = 0;
|
||||
|
||||
const tor_addr_t *addr = get_first_advertised_addr_by_type_af(
|
||||
CONN_TYPE_OR_LISTENER,
|
||||
AF_INET6);
|
||||
const uint16_t port = router_get_advertised_or_port_by_af(
|
||||
options,
|
||||
AF_INET6);
|
||||
|
||||
if (!addr || port == 0) {
|
||||
log_info(LD_CONFIG, "There is no advertised IPv6 ORPort.");
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the relay is configured using the default authorities, disallow
|
||||
* internal IPs. Otherwise, allow them. For IPv4 ORPorts and DirPorts,
|
||||
* this check is done in resolve_my_address(). See #33681. */
|
||||
const int default_auth = using_default_dir_authorities(options);
|
||||
if (tor_addr_is_internal(addr, 0) && default_auth) {
|
||||
log_warn(LD_CONFIG,
|
||||
"Unable to use configured IPv6 ORPort \"%s\" in a "
|
||||
"descriptor. Skipping it. "
|
||||
"Try specifying a globally reachable address explicitly.",
|
||||
fmt_addrport(addr, port));
|
||||
return;
|
||||
}
|
||||
|
||||
tor_addr_copy(&ipv6_ap_out->addr, addr);
|
||||
ipv6_ap_out->port = port;
|
||||
}
|
||||
|
||||
/** Return the port that we should advertise as our DirPort;
|
||||
* this is one of three possibilities:
|
||||
* The one that is passed as <b>dirport</b> if the DirPort option is 0, or
|
||||
@ -1848,34 +1892,11 @@ router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e)
|
||||
sizeof(curve25519_public_key_t));
|
||||
|
||||
/* For now, at most one IPv6 or-address is being advertised. */
|
||||
{
|
||||
const port_cfg_t *ipv6_orport = NULL;
|
||||
SMARTLIST_FOREACH_BEGIN(get_configured_ports(), const port_cfg_t *, p) {
|
||||
if (p->type == CONN_TYPE_OR_LISTENER &&
|
||||
! p->server_cfg.no_advertise &&
|
||||
! p->server_cfg.bind_ipv4_only &&
|
||||
tor_addr_family(&p->addr) == AF_INET6) {
|
||||
/* Like IPv4, if the relay is configured using the default
|
||||
* authorities, disallow internal IPs. Otherwise, allow them. */
|
||||
const int default_auth = using_default_dir_authorities(options);
|
||||
if (! tor_addr_is_internal(&p->addr, 0) || ! default_auth) {
|
||||
ipv6_orport = p;
|
||||
break;
|
||||
} else {
|
||||
char addrbuf[TOR_ADDR_BUF_LEN];
|
||||
log_warn(LD_CONFIG,
|
||||
"Unable to use configured IPv6 address \"%s\" in a "
|
||||
"descriptor. Skipping it. "
|
||||
"Try specifying a globally reachable address explicitly.",
|
||||
tor_addr_to_str(addrbuf, &p->addr, sizeof(addrbuf), 1));
|
||||
}
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(p);
|
||||
if (ipv6_orport) {
|
||||
tor_addr_copy(&ri->ipv6_addr, &ipv6_orport->addr);
|
||||
ri->ipv6_orport = ipv6_orport->port;
|
||||
}
|
||||
}
|
||||
tor_addr_port_t ipv6_orport;
|
||||
router_get_advertised_ipv6_or_ap(options, &ipv6_orport);
|
||||
/* If there is no valud 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,
|
||||
|
@ -59,6 +59,8 @@ int init_keys_client(void);
|
||||
uint16_t router_get_active_listener_port_by_type_af(int listener_type,
|
||||
sa_family_t family);
|
||||
uint16_t router_get_advertised_or_port(const or_options_t *options);
|
||||
void router_get_advertised_ipv6_or_ap(const or_options_t *options,
|
||||
tor_addr_port_t *ipv6_ap_out);
|
||||
uint16_t router_get_advertised_or_port_by_af(const or_options_t *options,
|
||||
sa_family_t family);
|
||||
uint16_t router_get_advertised_dir_port(const or_options_t *options,
|
||||
|
@ -4860,6 +4860,71 @@ test_config_parse_port_config__ports__server_options(void *data)
|
||||
config_free_lines(config_port_valid); config_port_valid = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
test_config_get_first_advertised(void *data)
|
||||
{
|
||||
(void)data;
|
||||
int r, w=0, n=0;
|
||||
char *msg=NULL;
|
||||
or_options_t *opts = options_new();
|
||||
int port;
|
||||
const tor_addr_t *addr;
|
||||
|
||||
// no ports are configured? We get NULL.
|
||||
port = get_first_advertised_port_by_type_af(CONN_TYPE_OR_LISTENER,
|
||||
AF_INET);
|
||||
tt_int_op(port, OP_EQ, 0);
|
||||
addr = get_first_advertised_addr_by_type_af(CONN_TYPE_OR_LISTENER,
|
||||
AF_INET);
|
||||
tt_ptr_op(addr, OP_EQ, NULL);
|
||||
|
||||
port = get_first_advertised_port_by_type_af(CONN_TYPE_OR_LISTENER,
|
||||
AF_INET6);
|
||||
tt_int_op(port, OP_EQ, 0);
|
||||
addr = get_first_advertised_addr_by_type_af(CONN_TYPE_OR_LISTENER,
|
||||
AF_INET6);
|
||||
tt_ptr_op(addr, OP_EQ, NULL);
|
||||
|
||||
config_line_append(&opts->ORPort_lines, "ORPort", "[1234::5678]:8080");
|
||||
config_line_append(&opts->ORPort_lines, "ORPort",
|
||||
"1.2.3.4:9999 noadvertise");
|
||||
config_line_append(&opts->ORPort_lines, "ORPort",
|
||||
"5.6.7.8:9911 nolisten");
|
||||
|
||||
r = parse_ports(opts, 0, &msg, &n, &w);
|
||||
tt_assert(r == 0);
|
||||
|
||||
// UNSPEC gets us nothing.
|
||||
port = get_first_advertised_port_by_type_af(CONN_TYPE_OR_LISTENER,
|
||||
AF_UNSPEC);
|
||||
tt_int_op(port, OP_EQ, 0);
|
||||
addr = get_first_advertised_addr_by_type_af(CONN_TYPE_OR_LISTENER,
|
||||
AF_UNSPEC);
|
||||
tt_ptr_op(addr, OP_EQ, NULL);
|
||||
|
||||
// Try AF_INET.
|
||||
port = get_first_advertised_port_by_type_af(CONN_TYPE_OR_LISTENER,
|
||||
AF_INET);
|
||||
tt_int_op(port, OP_EQ, 9911);
|
||||
addr = get_first_advertised_addr_by_type_af(CONN_TYPE_OR_LISTENER,
|
||||
AF_INET);
|
||||
tt_ptr_op(addr, OP_NE, NULL);
|
||||
tt_str_op(fmt_addrport(addr,port), OP_EQ, "5.6.7.8:9911");
|
||||
|
||||
// Try AF_INET6
|
||||
port = get_first_advertised_port_by_type_af(CONN_TYPE_OR_LISTENER,
|
||||
AF_INET6);
|
||||
tt_int_op(port, OP_EQ, 8080);
|
||||
addr = get_first_advertised_addr_by_type_af(CONN_TYPE_OR_LISTENER,
|
||||
AF_INET6);
|
||||
tt_ptr_op(addr, OP_NE, NULL);
|
||||
tt_str_op(fmt_addrport(addr,port), OP_EQ, "[1234::5678]:8080");
|
||||
|
||||
done:
|
||||
or_options_free(opts);
|
||||
config_free_all();
|
||||
}
|
||||
|
||||
static void
|
||||
test_config_parse_log_severity(void *data)
|
||||
{
|
||||
@ -5920,6 +5985,7 @@ struct testcase_t config_tests[] = {
|
||||
CONFIG_TEST(parse_port_config__ports__no_ports_given, 0),
|
||||
CONFIG_TEST(parse_port_config__ports__server_options, 0),
|
||||
CONFIG_TEST(parse_port_config__ports__ports_given, 0),
|
||||
CONFIG_TEST(get_first_advertised, TT_FORK),
|
||||
CONFIG_TEST(parse_log_severity, 0),
|
||||
CONFIG_TEST(include_limit, 0),
|
||||
CONFIG_TEST(include_does_not_exist, 0),
|
||||
|
@ -7,9 +7,12 @@
|
||||
* \brief Unittests for code in router.c
|
||||
**/
|
||||
|
||||
#define CONFIG_PRIVATE
|
||||
#define CONNECTION_PRIVATE
|
||||
#include "core/or/or.h"
|
||||
#include "app/config/config.h"
|
||||
#include "core/mainloop/mainloop.h"
|
||||
#include "core/mainloop/connection.h"
|
||||
#include "feature/hibernate/hibernate.h"
|
||||
#include "feature/nodelist/routerinfo_st.h"
|
||||
#include "feature/nodelist/routerlist.h"
|
||||
@ -17,6 +20,9 @@
|
||||
#include "feature/stats/rephist.h"
|
||||
#include "lib/crypt_ops/crypto_curve25519.h"
|
||||
#include "lib/crypt_ops/crypto_ed25519.h"
|
||||
#include "lib/encoding/confline.h"
|
||||
|
||||
#include "core/or/listener_connection_st.h"
|
||||
|
||||
/* Test suite stuff */
|
||||
#include "test/test.h"
|
||||
@ -231,11 +237,124 @@ test_router_check_descriptor_bandwidth_changed(void *arg)
|
||||
UNMOCK(we_are_hibernating);
|
||||
}
|
||||
|
||||
static smartlist_t *fake_connection_array = NULL;
|
||||
static smartlist_t *
|
||||
mock_get_connection_array(void)
|
||||
{
|
||||
return fake_connection_array;
|
||||
}
|
||||
|
||||
static void
|
||||
test_router_get_advertised_or_port(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
int r, w=0, n=0;
|
||||
char *msg=NULL;
|
||||
or_options_t *opts = options_new();
|
||||
listener_connection_t *listener = NULL;
|
||||
tor_addr_port_t ipv6;
|
||||
|
||||
// Test one failing case of router_get_advertised_ipv6_or_ap().
|
||||
router_get_advertised_ipv6_or_ap(opts, &ipv6);
|
||||
tt_str_op(fmt_addrport(&ipv6.addr, ipv6.port), OP_EQ, "[::]:0");
|
||||
|
||||
// And one failing case of router_get_advertised_or_port().
|
||||
tt_int_op(0, OP_EQ, router_get_advertised_or_port_by_af(opts, AF_INET));
|
||||
tt_int_op(0, OP_EQ, router_get_advertised_or_port(opts));
|
||||
|
||||
// Set up a couple of configured ports.
|
||||
config_line_append(&opts->ORPort_lines, "ORPort", "[1234::5678]:auto");
|
||||
config_line_append(&opts->ORPort_lines, "ORPort", "5.6.7.8:9999");
|
||||
r = parse_ports(opts, 0, &msg, &n, &w);
|
||||
tt_assert(r == 0);
|
||||
|
||||
// There are no listeners, so the "auto" case will turn up no results.
|
||||
tt_int_op(0, OP_EQ, router_get_advertised_or_port_by_af(opts, AF_INET6));
|
||||
router_get_advertised_ipv6_or_ap(opts, &ipv6);
|
||||
tt_str_op(fmt_addrport(&ipv6.addr, ipv6.port), OP_EQ, "[::]:0");
|
||||
|
||||
// This will return the matching value from the configured port.
|
||||
tt_int_op(9999, OP_EQ, router_get_advertised_or_port_by_af(opts, AF_INET));
|
||||
tt_int_op(9999, OP_EQ, router_get_advertised_or_port(opts));
|
||||
|
||||
// Now set up a dummy listener.
|
||||
MOCK(get_connection_array, mock_get_connection_array);
|
||||
fake_connection_array = smartlist_new();
|
||||
listener = listener_connection_new(CONN_TYPE_OR_LISTENER, AF_INET6);
|
||||
TO_CONN(listener)->port = 54321;
|
||||
smartlist_add(fake_connection_array, TO_CONN(listener));
|
||||
|
||||
// We should get a port this time.
|
||||
tt_int_op(54321, OP_EQ, router_get_advertised_or_port_by_af(opts, AF_INET6));
|
||||
|
||||
// Test one succeeding case of router_get_advertised_ipv6_or_ap().
|
||||
router_get_advertised_ipv6_or_ap(opts, &ipv6);
|
||||
tt_str_op(fmt_addrport(&ipv6.addr, ipv6.port), OP_EQ,
|
||||
"[1234::5678]:54321");
|
||||
|
||||
// This will return the matching value from the configured port.
|
||||
tt_int_op(9999, OP_EQ, router_get_advertised_or_port_by_af(opts, AF_INET));
|
||||
tt_int_op(9999, OP_EQ, router_get_advertised_or_port(opts));
|
||||
|
||||
done:
|
||||
or_options_free(opts);
|
||||
config_free_all();
|
||||
smartlist_free(fake_connection_array);
|
||||
connection_free_minimal(TO_CONN(listener));
|
||||
UNMOCK(get_connection_array);
|
||||
}
|
||||
|
||||
static void
|
||||
test_router_get_advertised_or_port_localhost(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
int r, w=0, n=0;
|
||||
char *msg=NULL;
|
||||
or_options_t *opts = options_new();
|
||||
tor_addr_port_t ipv6;
|
||||
|
||||
// Set up a couple of configured ports on localhost.
|
||||
config_line_append(&opts->ORPort_lines, "ORPort", "[::1]:9999");
|
||||
config_line_append(&opts->ORPort_lines, "ORPort", "127.0.0.1:8888");
|
||||
r = parse_ports(opts, 0, &msg, &n, &w);
|
||||
tt_assert(r == 0);
|
||||
|
||||
// We should refuse to advertise them, since we have default dirauths.
|
||||
router_get_advertised_ipv6_or_ap(opts, &ipv6);
|
||||
tt_str_op(fmt_addrport(&ipv6.addr, ipv6.port), OP_EQ, "[::]:0");
|
||||
// But the lower-level function should still report the correct value
|
||||
tt_int_op(9999, OP_EQ, router_get_advertised_or_port_by_af(opts, AF_INET6));
|
||||
|
||||
// The IPv4 checks are done in resolve_my_address(), which doesn't use
|
||||
// ORPorts so we can't test them here. (See #33681.) Both these lower-level
|
||||
// functions should still report the correct value.
|
||||
tt_int_op(8888, OP_EQ, router_get_advertised_or_port_by_af(opts, AF_INET));
|
||||
tt_int_op(8888, OP_EQ, router_get_advertised_or_port(opts));
|
||||
|
||||
// Now try with a fake authority set up.
|
||||
config_line_append(&opts->DirAuthorities, "DirAuthority",
|
||||
"127.0.0.1:1066 "
|
||||
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
|
||||
tt_int_op(9999, OP_EQ, router_get_advertised_or_port_by_af(opts, AF_INET6));
|
||||
router_get_advertised_ipv6_or_ap(opts, &ipv6);
|
||||
tt_str_op(fmt_addrport(&ipv6.addr, ipv6.port), OP_EQ, "[::1]:9999");
|
||||
|
||||
tt_int_op(8888, OP_EQ, router_get_advertised_or_port_by_af(opts, AF_INET));
|
||||
tt_int_op(8888, OP_EQ, router_get_advertised_or_port(opts));
|
||||
|
||||
done:
|
||||
or_options_free(opts);
|
||||
config_free_all();
|
||||
}
|
||||
|
||||
#define ROUTER_TEST(name, flags) \
|
||||
{ #name, test_router_ ## name, flags, NULL, NULL }
|
||||
|
||||
struct testcase_t router_tests[] = {
|
||||
ROUTER_TEST(check_descriptor_bandwidth_changed, TT_FORK),
|
||||
ROUTER_TEST(dump_router_to_string_no_bridge_distribution_method, TT_FORK),
|
||||
ROUTER_TEST(get_advertised_or_port, TT_FORK),
|
||||
ROUTER_TEST(get_advertised_or_port_localhost, TT_FORK),
|
||||
END_OF_TESTCASES
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user