mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-27 22:03:31 +01:00
Merge branch 'bug13953_squashed'
This commit is contained in:
commit
bd45f7c668
3
changes/bug13953
Normal file
3
changes/bug13953
Normal file
@ -0,0 +1,3 @@
|
||||
o Minor bugfixes (config):
|
||||
- Warn users when descriptor and port addresses are inconsistent.
|
||||
Mitigates bug 13953; patch by teor.
|
116
src/or/config.c
116
src/or/config.c
@ -6898,6 +6898,22 @@ parse_ports(or_options_t *options, int validate_only,
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Does port bind to IPv4? */
|
||||
static int port_binds_ipv4(const port_cfg_t *port)
|
||||
{
|
||||
return tor_addr_family(&port->addr) == AF_INET ||
|
||||
(tor_addr_family(&port->addr) == AF_UNSPEC
|
||||
&& !port->server_cfg.bind_ipv6_only);
|
||||
}
|
||||
|
||||
/* Does port bind to IPv6? */
|
||||
static int port_binds_ipv6(const port_cfg_t *port)
|
||||
{
|
||||
return tor_addr_family(&port->addr) == AF_INET6 ||
|
||||
(tor_addr_family(&port->addr) == AF_UNSPEC
|
||||
&& !port->server_cfg.bind_ipv4_only);
|
||||
}
|
||||
|
||||
/** Given a list of <b>port_cfg_t</b> in <b>ports</b>, check them for internal
|
||||
* consistency and warn as appropriate. Set *<b>n_low_ports_out</b> to the
|
||||
* number of sub-1024 ports we will be binding. */
|
||||
@ -6923,9 +6939,7 @@ check_server_ports(const smartlist_t *ports,
|
||||
} else if (port->type == CONN_TYPE_OR_LISTENER) {
|
||||
if (! port->server_cfg.no_advertise) {
|
||||
++n_orport_advertised;
|
||||
if (tor_addr_family(&port->addr) == AF_INET ||
|
||||
(tor_addr_family(&port->addr) == AF_UNSPEC &&
|
||||
!port->server_cfg.bind_ipv6_only))
|
||||
if (port_binds_ipv4(port))
|
||||
++n_orport_advertised_ipv4;
|
||||
}
|
||||
if (! port->server_cfg.no_listen)
|
||||
@ -7059,19 +7073,20 @@ get_first_listener_addrport_string(int listener_type)
|
||||
}
|
||||
|
||||
/** Return the first advertised port of type <b>listener_type</b> in
|
||||
<b>address_family</b>. */
|
||||
* <b>address_family</b>. Returns 0 when no port is found, and when passed
|
||||
* AF_UNSPEC. */
|
||||
int
|
||||
get_first_advertised_port_by_type_af(int listener_type, int address_family)
|
||||
{
|
||||
if (address_family == AF_UNSPEC)
|
||||
return 0;
|
||||
|
||||
const smartlist_t *conf_ports = get_configured_ports();
|
||||
SMARTLIST_FOREACH_BEGIN(conf_ports, const port_cfg_t *, cfg) {
|
||||
if (cfg->type == listener_type &&
|
||||
!cfg->server_cfg.no_advertise &&
|
||||
(tor_addr_family(&cfg->addr) == address_family ||
|
||||
tor_addr_family(&cfg->addr) == AF_UNSPEC)) {
|
||||
if (tor_addr_family(&cfg->addr) != AF_UNSPEC ||
|
||||
(address_family == AF_INET && !cfg->server_cfg.bind_ipv6_only) ||
|
||||
(address_family == AF_INET6 && !cfg->server_cfg.bind_ipv4_only)) {
|
||||
!cfg->server_cfg.no_advertise) {
|
||||
if ((address_family == AF_INET && port_binds_ipv4(cfg)) ||
|
||||
(address_family == AF_INET6 && port_binds_ipv6(cfg))) {
|
||||
return cfg->port;
|
||||
}
|
||||
}
|
||||
@ -7079,6 +7094,87 @@ get_first_advertised_port_by_type_af(int listener_type, int address_family)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Return the first advertised address of type <b>listener_type</b> in
|
||||
* <b>address_family</b>. Returns NULL if there is no advertised address,
|
||||
* and when passed AF_UNSPEC. */
|
||||
const tor_addr_t *
|
||||
get_first_advertised_addr_by_type_af(int listener_type, int address_family)
|
||||
{
|
||||
if (address_family == AF_UNSPEC)
|
||||
return NULL;
|
||||
if (!configured_ports)
|
||||
return NULL;
|
||||
SMARTLIST_FOREACH_BEGIN(configured_ports, const port_cfg_t *, cfg) {
|
||||
if (cfg->type == listener_type &&
|
||||
!cfg->server_cfg.no_advertise) {
|
||||
if ((address_family == AF_INET && port_binds_ipv4(cfg)) ||
|
||||
(address_family == AF_INET6 && port_binds_ipv6(cfg))) {
|
||||
return &cfg->addr;
|
||||
}
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(cfg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Return 1 if a port exists of type <b>listener_type</b> on <b>addr</b> and
|
||||
* <b>port</b>. If <b>check_wildcard</b> is true, INADDR[6]_ANY and AF_UNSPEC
|
||||
* addresses match any address of the appropriate family; and port -1 matches
|
||||
* any port.
|
||||
* To match auto ports, pass CFG_PORT_AUTO. (Does not match on the actual
|
||||
* automatically chosen listener ports.) */
|
||||
int
|
||||
port_exists_by_type_addr_port(int listener_type, const tor_addr_t *addr,
|
||||
int port, int check_wildcard)
|
||||
{
|
||||
if (!configured_ports || !addr)
|
||||
return 0;
|
||||
SMARTLIST_FOREACH_BEGIN(configured_ports, const port_cfg_t *, cfg) {
|
||||
if (cfg->type == listener_type) {
|
||||
if (cfg->port == port || (check_wildcard && port == -1)) {
|
||||
/* Exact match */
|
||||
if (tor_addr_eq(&cfg->addr, addr)) {
|
||||
return 1;
|
||||
}
|
||||
/* Skip wildcard matches if we're not doing them */
|
||||
if (!check_wildcard) {
|
||||
continue;
|
||||
}
|
||||
/* Wildcard matches IPv4 */
|
||||
const int cfg_v4 = port_binds_ipv4(cfg);
|
||||
const int cfg_any_v4 = tor_addr_is_null(&cfg->addr) && cfg_v4;
|
||||
const int addr_v4 = tor_addr_family(addr) == AF_INET ||
|
||||
tor_addr_family(addr) == AF_UNSPEC;
|
||||
const int addr_any_v4 = tor_addr_is_null(&cfg->addr) && addr_v4;
|
||||
if ((cfg_any_v4 && addr_v4) || (cfg_v4 && addr_any_v4)) {
|
||||
return 1;
|
||||
}
|
||||
/* Wildcard matches IPv6 */
|
||||
const int cfg_v6 = port_binds_ipv6(cfg);
|
||||
const int cfg_any_v6 = tor_addr_is_null(&cfg->addr) && cfg_v6;
|
||||
const int addr_v6 = tor_addr_family(addr) == AF_INET6 ||
|
||||
tor_addr_family(addr) == AF_UNSPEC;
|
||||
const int addr_any_v6 = tor_addr_is_null(&cfg->addr) && addr_v6;
|
||||
if ((cfg_any_v6 && addr_v6) || (cfg_v6 && addr_any_v6)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(cfg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Like port_exists_by_type_addr_port, but accepts a host-order IPv4 address
|
||||
* instead. */
|
||||
int
|
||||
port_exists_by_type_addr32h_port(int listener_type, uint32_t addr_ipv4h,
|
||||
int port, int check_wildcard)
|
||||
{
|
||||
tor_addr_t ipv4;
|
||||
tor_addr_from_ipv4h(&ipv4, addr_ipv4h);
|
||||
return port_exists_by_type_addr_port(listener_type, &ipv4, port,
|
||||
check_wildcard);
|
||||
}
|
||||
|
||||
/** Adjust the value of options->DataDirectory, or fill it in if it's
|
||||
* absent. Return 0 on success, -1 on failure. */
|
||||
static int
|
||||
|
@ -89,6 +89,12 @@ int get_first_advertised_port_by_type_af(int listener_type,
|
||||
(get_first_advertised_port_by_type_af(CONN_TYPE_OR_LISTENER, AF_INET))
|
||||
#define get_primary_dir_port() \
|
||||
(get_first_advertised_port_by_type_af(CONN_TYPE_DIR_LISTENER, AF_INET))
|
||||
const tor_addr_t *get_first_advertised_addr_by_type_af(int listener_type,
|
||||
int address_family);
|
||||
int port_exists_by_type_addr_port(int listener_type, const tor_addr_t *addr,
|
||||
int port, int check_wildcard);
|
||||
int port_exists_by_type_addr32h_port(int listener_type, uint32_t addr_ipv4h,
|
||||
int port, int check_wildcard);
|
||||
|
||||
char *get_first_listener_addrport_string(int listener_type);
|
||||
|
||||
|
@ -1963,6 +1963,83 @@ router_pick_published_address,(const or_options_t *options, uint32_t *addr))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Like router_check_descriptor_address_consistency, but specifically for the
|
||||
* 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,
|
||||
int listener_type)
|
||||
{
|
||||
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. */
|
||||
assert(port_addr);
|
||||
|
||||
tor_addr_t desc_addr;
|
||||
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_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);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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.
|
||||
* 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
|
||||
* addresses in the absence of an Address config). This includes
|
||||
* operators who attempt to put their ORPort and DirPort on different
|
||||
* 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).
|
||||
*/
|
||||
static void
|
||||
router_check_descriptor_address_consistency(uint32_t ipv4h_desc_addr)
|
||||
{
|
||||
router_check_descriptor_address_port_consistency(ipv4h_desc_addr,
|
||||
CONN_TYPE_OR_LISTENER);
|
||||
router_check_descriptor_address_port_consistency(ipv4h_desc_addr,
|
||||
CONN_TYPE_DIR_LISTENER);
|
||||
}
|
||||
|
||||
/** Build a fresh routerinfo, signed server descriptor, and extra-info document
|
||||
* for this OR. Set r to the generated routerinfo, e to the generated
|
||||
* extra-info document. Return 0 on success, -1 on temporary error. Failure to
|
||||
@ -1985,6 +2062,10 @@ router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
ri = tor_malloc_zero(sizeof(routerinfo_t));
|
||||
ri->cache_info.routerlist_index = -1;
|
||||
ri->nickname = tor_strdup(options->Nickname);
|
||||
|
Loading…
Reference in New Issue
Block a user