Loading changes/bug13953 0 → 100644 +3 −0 Original line number Diff line number Diff line o Minor bugfixes (config): - Warn users when descriptor and port addresses are inconsistent. Mitigates bug 13953; patch by teor. src/or/config.c +106 −10 Original line number Diff line number Diff line Loading @@ -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. */ Loading @@ -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) Loading Loading @@ -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; } } Loading @@ -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 Loading src/or/config.h +6 −0 Original line number Diff line number Diff line Loading @@ -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); Loading src/or/router.c +81 −0 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading
changes/bug13953 0 → 100644 +3 −0 Original line number Diff line number Diff line o Minor bugfixes (config): - Warn users when descriptor and port addresses are inconsistent. Mitigates bug 13953; patch by teor.
src/or/config.c +106 −10 Original line number Diff line number Diff line Loading @@ -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. */ Loading @@ -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) Loading Loading @@ -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; } } Loading @@ -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 Loading
src/or/config.h +6 −0 Original line number Diff line number Diff line Loading @@ -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); Loading
src/or/router.c +81 −0 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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