summaryrefslogtreecommitdiff
path: root/src/or
diff options
context:
space:
mode:
Diffstat (limited to 'src/or')
-rw-r--r--src/or/circuitbuild.c9
-rw-r--r--src/or/config.c244
-rw-r--r--src/or/config.h10
-rw-r--r--src/or/confparse.c55
-rw-r--r--src/or/confparse.h15
-rw-r--r--src/or/control.c5
-rw-r--r--src/or/dirvote.c14
-rw-r--r--src/or/dirvote.h2
-rw-r--r--src/or/main.c2
-rw-r--r--src/or/microdesc.c1
-rw-r--r--src/or/or.h5
-rw-r--r--src/or/router.c81
-rw-r--r--src/or/routerlist.c18
-rw-r--r--src/or/routerlist.h2
-rw-r--r--src/or/shared_random.c2
-rw-r--r--src/or/shared_random_state.c5
-rw-r--r--src/or/statefile.c3
17 files changed, 409 insertions, 64 deletions
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index b07ddab945..14d40150db 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -1770,6 +1770,8 @@ pick_tor2web_rendezvous_node(router_crn_flags_t flags,
const node_t *rp_node = NULL;
const int allow_invalid = (flags & CRN_ALLOW_INVALID) != 0;
const int need_desc = (flags & CRN_NEED_DESC) != 0;
+ const int pref_addr = (flags & CRN_PREF_ADDR) != 0;
+ const int direct_conn = (flags & CRN_DIRECT_CONN) != 0;
smartlist_t *whitelisted_live_rps = smartlist_new();
smartlist_t *all_live_nodes = smartlist_new();
@@ -1780,7 +1782,9 @@ pick_tor2web_rendezvous_node(router_crn_flags_t flags,
router_add_running_nodes_to_smartlist(all_live_nodes,
allow_invalid,
0, 0, 0,
- need_desc, 0);
+ need_desc,
+ pref_addr,
+ direct_conn);
/* Filter all_live_nodes to only add live *and* whitelisted RPs to
* the list whitelisted_live_rps. */
@@ -2148,7 +2152,8 @@ choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state)
const or_options_t *options = get_options();
/* If possible, choose an entry server with a preferred address,
* otherwise, choose one with an allowed address */
- router_crn_flags_t flags = CRN_NEED_GUARD|CRN_NEED_DESC|CRN_PREF_ADDR;
+ router_crn_flags_t flags = (CRN_NEED_GUARD|CRN_NEED_DESC|CRN_PREF_ADDR|
+ CRN_DIRECT_CONN);
const node_t *node;
if (state && options->UseEntryGuards &&
diff --git a/src/or/config.c b/src/or/config.c
index df85bc3534..31bf81877d 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -546,7 +546,7 @@ static const config_var_t testing_tor_network_defaults[] = {
"0, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 16, 32, 60"),
V(ClientBootstrapConsensusMaxDownloadTries, UINT, "80"),
V(ClientBootstrapConsensusAuthorityOnlyMaxDownloadTries, UINT, "80"),
- V(ClientDNSRejectInternalAddresses, BOOL,"0"),
+ V(ClientDNSRejectInternalAddresses, BOOL,"0"), // deprecated in 0.2.9.2-alpha
V(ClientRejectInternalAddresses, BOOL, "0"),
V(CountPrivateBandwidth, BOOL, "1"),
V(ExitPolicyRejectPrivate, BOOL, "0"),
@@ -589,6 +589,45 @@ static const config_var_t testing_tor_network_defaults[] = {
#undef V
#undef OBSOLETE
+static const config_deprecation_t option_deprecation_notes_[] = {
+ /* Deprecated since 0.2.9.2-alpha... */
+ { "AllowDotExit", "Unrestricted use of the .exit notation can be used for "
+ "a wide variety of application-level attacks." },
+ { "AllowInvalidNodes", "There is no reason to enable this option; at best "
+ "it will make you easier to track." },
+ { "AllowSingleHopCircuits", "Almost no relays actually allow single-hop "
+ "exits, making this option pointless." },
+ { "AllowSingleHopExits", "Turning this on will make your relay easier "
+ "to abuse." },
+ { "ClientDNSRejectInternalAddresses", "Turning this on makes your client "
+ "easier to fingerprint, and may open you to esoteric attacks." },
+ { "ExcludeSingleHopRelays", "Turning it on makes your client easier to "
+ "fingerprint." },
+ { "FastFirstHopPK", "Changing this option does not make your client more "
+ "secure, but does make it easier to fingerprint." },
+ { "CloseHSClientCircuitsImmediatelyOnTimeout", "This option makes your "
+ "client easier to fingerprint." },
+ { "CloseHSServiceRendCircuitsImmediatelyOnTimeout", "This option makes "
+ "your hidden services easier to fingerprint." },
+ { "WarnUnsafeSocks", "Changing this option makes it easier for you "
+ "to accidentally lose your anonymity by leaking DNS information" },
+ { "TLSECGroup", "The default is a nice secure choice; the other option "
+ "is less secure." },
+ { "UseNTorHandshake", "The ntor handshake should always be used." },
+ { "ControlListenAddress", "Use ControlPort instead." },
+ { "DirListenAddress", "Use DirPort instead, possibly with the "
+ "NoAdvertise sub-option" },
+ { "DNSListenAddress", "Use DNSPort instead." },
+ { "SocksListenAddress", "Use SocksPort instead." },
+ { "TransListenAddress", "Use TransPort instead." },
+ { "NATDListenAddress", "Use NATDPort instead." },
+ { "ORListenAddress", "Use ORPort instead, possibly with the "
+ "NoAdvertise sub-option" },
+ /* End of options deprecated since 0.2.9.2-alpha. */
+
+ { NULL, NULL }
+};
+
#ifdef _WIN32
static char *get_windows_conf_root(void);
#endif
@@ -637,6 +676,7 @@ STATIC config_format_t options_format = {
OR_OPTIONS_MAGIC,
STRUCT_OFFSET(or_options_t, magic_),
option_abbrevs_,
+ option_deprecation_notes_,
option_vars_,
options_validate_cb,
NULL
@@ -747,7 +787,7 @@ set_options(or_options_t *new_val, char **msg)
}
if (old_options != global_options)
- config_free(&options_format, old_options);
+ or_options_free(old_options);
return 0;
}
@@ -911,8 +951,8 @@ static const char *default_authorities[] = {
"dizum orport=443 "
"v3ident=E8A9C45EDE6D711294FADF8E7951F4DE6CA56B58 "
"194.109.206.212:80 7EA6 EAD6 FD83 083C 538F 4403 8BBF A077 587D D755",
- "Tonga orport=443 bridge "
- "82.94.251.203:80 4A0C CD2D DC79 9508 3D73 F5D6 6710 0C8A 5831 F16D",
+ "Bifroest orport=443 bridge "
+ "37.218.247.217:80 1D8F 3A91 C37C 5D1C 4C19 B1AD 1D0C FBE8 BF72 D8E1",
"gabelmoo orport=443 "
"v3ident=ED03BB616EB2F60BEC80151114BB25CEF515B226 "
"ipv6=[2001:638:a000:4140::ffff:189]:443 "
@@ -2029,6 +2069,7 @@ static const struct {
{ "-h", TAKES_NO_ARGUMENT },
{ "--help", TAKES_NO_ARGUMENT },
{ "--list-torrc-options", TAKES_NO_ARGUMENT },
+ { "--list-deprecated-options",TAKES_NO_ARGUMENT },
{ "--nt-service", TAKES_NO_ARGUMENT },
{ "-nt-service", TAKES_NO_ARGUMENT },
{ NULL, 0 },
@@ -2165,31 +2206,30 @@ option_get_assignment(const or_options_t *options, const char *key)
* what went wrong.
*/
setopt_err_t
-options_trial_assign(config_line_t *list, int use_defaults,
- int clear_first, char **msg)
+options_trial_assign(config_line_t *list, unsigned flags, char **msg)
{
int r;
or_options_t *trial_options = config_dup(&options_format, get_options());
if ((r=config_assign(&options_format, trial_options,
- list, use_defaults, clear_first, msg)) < 0) {
- config_free(&options_format, trial_options);
+ list, flags, msg)) < 0) {
+ or_options_free(trial_options);
return r;
}
if (options_validate(get_options_mutable(), trial_options,
global_default_options, 1, msg) < 0) {
- config_free(&options_format, trial_options);
+ or_options_free(trial_options);
return SETOPT_ERR_PARSE; /*XXX make this a separate return value. */
}
if (options_transition_allowed(get_options(), trial_options, msg) < 0) {
- config_free(&options_format, trial_options);
+ or_options_free(trial_options);
return SETOPT_ERR_TRANSITION;
}
if (set_options(trial_options, msg)<0) {
- config_free(&options_format, trial_options);
+ or_options_free(trial_options);
return SETOPT_ERR_SETTING;
}
@@ -2215,7 +2255,6 @@ static void
list_torrc_options(void)
{
int i;
- smartlist_t *lines = smartlist_new();
for (i = 0; option_vars_[i].name; ++i) {
const config_var_t *var = &option_vars_[i];
if (var->type == CONFIG_TYPE_OBSOLETE ||
@@ -2223,7 +2262,16 @@ list_torrc_options(void)
continue;
printf("%s\n", var->name);
}
- smartlist_free(lines);
+}
+
+/** Print all deprecated but non-obsolete torrc options. */
+static void
+list_deprecated_options(void)
+{
+ const config_deprecation_t *d;
+ for (d = option_deprecation_notes_; d->name; ++d) {
+ printf("%s\n", d->name);
+ }
}
/** Last value actually set by resolve_my_address. */
@@ -4677,10 +4725,15 @@ options_init_from_torrc(int argc, char **argv)
exit(0);
}
if (config_line_find(cmdline_only_options, "--list-torrc-options")) {
- /* For documenting validating whether we've documented everything. */
+ /* For validating whether we've documented everything. */
list_torrc_options();
exit(0);
}
+ if (config_line_find(cmdline_only_options, "--list-deprecated-options")) {
+ /* For validating whether what we have deprecated really exists. */
+ list_deprecated_options();
+ exit(0);
+ }
if (config_line_find(cmdline_only_options, "--version")) {
printf("Tor version %s.\n",get_version());
@@ -4859,7 +4912,8 @@ options_init_from_string(const char *cf_defaults, const char *cf,
err = SETOPT_ERR_PARSE;
goto err;
}
- retval = config_assign(&options_format, newoptions, cl, 0, 0, msg);
+ retval = config_assign(&options_format, newoptions, cl,
+ CAL_WARN_DEPRECATIONS, msg);
config_free_lines(cl);
if (retval < 0) {
err = SETOPT_ERR_PARSE;
@@ -4875,7 +4929,7 @@ options_init_from_string(const char *cf_defaults, const char *cf,
/* Go through command-line variables too */
retval = config_assign(&options_format, newoptions,
- global_cmdline_options, 0, 0, msg);
+ global_cmdline_options, CAL_WARN_DEPRECATIONS, msg);
if (retval < 0) {
err = SETOPT_ERR_PARSE;
goto err;
@@ -4900,11 +4954,17 @@ options_init_from_string(const char *cf_defaults, const char *cf,
tor_assert(new_var);
tor_assert(old_var);
old_var->initvalue = new_var->initvalue;
+
+ if ((config_find_deprecation(&options_format, new_var->name))) {
+ log_warn(LD_GENERAL, "Testing options override the deprecated "
+ "option %s. Is that intentional?",
+ new_var->name);
+ }
}
/* Clear newoptions and re-initialize them with new defaults. */
- config_free(&options_format, newoptions);
- config_free(&options_format, newdefaultoptions);
+ or_options_free(newoptions);
+ or_options_free(newdefaultoptions);
newdefaultoptions = NULL;
newoptions = tor_malloc_zero(sizeof(or_options_t));
newoptions->magic_ = OR_OPTIONS_MAGIC;
@@ -4923,7 +4983,7 @@ options_init_from_string(const char *cf_defaults, const char *cf,
err = SETOPT_ERR_PARSE;
goto err;
}
- retval = config_assign(&options_format, newoptions, cl, 0, 0, msg);
+ retval = config_assign(&options_format, newoptions, cl, 0, msg);
config_free_lines(cl);
if (retval < 0) {
err = SETOPT_ERR_PARSE;
@@ -4934,7 +4994,7 @@ options_init_from_string(const char *cf_defaults, const char *cf,
}
/* Assign command-line variables a second time too */
retval = config_assign(&options_format, newoptions,
- global_cmdline_options, 0, 0, msg);
+ global_cmdline_options, 0, msg);
if (retval < 0) {
err = SETOPT_ERR_PARSE;
goto err;
@@ -4957,14 +5017,14 @@ options_init_from_string(const char *cf_defaults, const char *cf,
err = SETOPT_ERR_SETTING;
goto err; /* frees and replaces old options */
}
- config_free(&options_format, global_default_options);
+ or_options_free(global_default_options);
global_default_options = newdefaultoptions;
return SETOPT_OK;
err:
- config_free(&options_format, newoptions);
- config_free(&options_format, newdefaultoptions);
+ or_options_free(newoptions);
+ or_options_free(newdefaultoptions);
if (*msg) {
char *old_msg = *msg;
tor_asprintf(msg, "Failed to parse/validate config: %s", old_msg);
@@ -6146,6 +6206,20 @@ config_parse_unix_port(const char *addrport, char **path_out)
}
#endif /* defined(HAVE_SYS_UN_H) */
+static void
+warn_client_dns_cache(const char *option, int disabling)
+{
+ if (disabling)
+ return;
+
+ warn_deprecated_option(option,
+ "Client-side DNS cacheing enables a wide variety of route-"
+ "capture attacks. If a single bad exit node lies to you about "
+ "an IP address, cacheing that address would make you visit "
+ "an address of the attacker's choice every time you connected "
+ "to your destination.");
+}
+
/**
* Parse port configuration for a single port type.
*
@@ -6514,21 +6588,27 @@ parse_port_config(smartlist_t *out,
}
}
if (!strcasecmp(elt, "CacheIPv4DNS")) {
+ warn_client_dns_cache(elt, no); // since 0.2.9.2-alpha
cache_ipv4 = ! no;
continue;
} else if (!strcasecmp(elt, "CacheIPv6DNS")) {
+ warn_client_dns_cache(elt, no); // since 0.2.9.2-alpha
cache_ipv6 = ! no;
continue;
} else if (!strcasecmp(elt, "CacheDNS")) {
+ warn_client_dns_cache(elt, no); // since 0.2.9.2-alpha
cache_ipv4 = cache_ipv6 = ! no;
continue;
} else if (!strcasecmp(elt, "UseIPv4Cache")) {
+ warn_client_dns_cache(elt, no); // since 0.2.9.2-alpha
use_cached_ipv4 = ! no;
continue;
} else if (!strcasecmp(elt, "UseIPv6Cache")) {
+ warn_client_dns_cache(elt, no); // since 0.2.9.2-alpha
use_cached_ipv6 = ! no;
continue;
} else if (!strcasecmp(elt, "UseDNSCache")) {
+ warn_client_dns_cache(elt, no); // since 0.2.9.2-alpha
use_cached_ipv4 = use_cached_ipv6 = ! no;
continue;
} else if (!strcasecmp(elt, "PreferIPv6Automap")) {
@@ -6848,6 +6928,24 @@ 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. */
@@ -6873,9 +6971,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)
@@ -7009,19 +7105,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;
}
}
@@ -7029,6 +7126,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
diff --git a/src/or/config.h b/src/or/config.h
index a0fe6e4805..7db66a31b9 100644
--- a/src/or/config.h
+++ b/src/or/config.h
@@ -29,8 +29,8 @@ const char *escaped_safe_str_client(const char *address);
const char *escaped_safe_str(const char *address);
const char *get_version(void);
const char *get_short_version(void);
-setopt_err_t options_trial_assign(config_line_t *list, int use_defaults,
- int clear_first, char **msg);
+setopt_err_t options_trial_assign(config_line_t *list, unsigned flags,
+ char **msg);
uint32_t get_last_resolved_addr(void);
void reset_last_resolved_addr(void);
@@ -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);
diff --git a/src/or/confparse.c b/src/or/confparse.c
index 3532b39d93..efcf4f981e 100644
--- a/src/or/confparse.c
+++ b/src/or/confparse.c
@@ -181,6 +181,26 @@ config_free_lines(config_line_t *front)
}
}
+/** If <b>key</b> is a deprecated configuration option, return the message
+ * explaining why it is deprecated (which may be an empty string). Return NULL
+ * if it is not deprecated. The <b>key</b> field must be fully expanded. */
+const char *
+config_find_deprecation(const config_format_t *fmt, const char *key)
+{
+ if (BUG(fmt == NULL) || BUG(key == NULL))
+ return NULL;
+ if (fmt->deprecations == NULL)
+ return NULL;
+
+ const config_deprecation_t *d;
+ for (d = fmt->deprecations; d->name; ++d) {
+ if (!strcasecmp(d->name, key)) {
+ return d->why_deprecated ? d->why_deprecated : "";
+ }
+ }
+ return NULL;
+}
+
/** As config_find_option, but return a non-const pointer. */
config_var_t *
config_find_option_mutable(config_format_t *fmt, const char *key)
@@ -463,6 +483,16 @@ config_mark_lists_fragile(const config_format_t *fmt, void *options)
}
}
+void
+warn_deprecated_option(const char *what, const char *why)
+{
+ const char *space = (why && strlen(why)) ? " " : "";
+ log_warn(LD_CONFIG, "The %s option is deprecated, and will most likely "
+ "be removed in a future version of Tor.%s%s (If you think this is "
+ "a mistake, please let us know!)",
+ what, space, why);
+}
+
/** If <b>c</b> is a syntactically valid configuration line, update
* <b>options</b> with its value and return 0. Otherwise return -1 for bad
* key, -2 for bad value.
@@ -474,9 +504,12 @@ config_mark_lists_fragile(const config_format_t *fmt, void *options)
*/
static int
config_assign_line(const config_format_t *fmt, void *options,
- config_line_t *c, int use_defaults,
- int clear_first, bitarray_t *options_seen, char **msg)
+ config_line_t *c, unsigned flags,
+ bitarray_t *options_seen, char **msg)
{
+ const unsigned use_defaults = flags & CAL_USE_DEFAULTS;
+ const unsigned clear_first = flags & CAL_CLEAR_FIRST;
+ const unsigned warn_deprecations = flags & CAL_WARN_DEPRECATIONS;
const config_var_t *var;
CONFIG_CHECK(fmt, options);
@@ -502,6 +535,12 @@ config_assign_line(const config_format_t *fmt, void *options,
c->key = tor_strdup(var->name);
}
+ const char *deprecation_msg;
+ if (warn_deprecations &&
+ (deprecation_msg = config_find_deprecation(fmt, var->name))) {
+ warn_deprecated_option(var->name, deprecation_msg);
+ }
+
if (!strlen(c->value)) {
/* reset or clear it, then return */
if (!clear_first) {
@@ -604,7 +643,7 @@ config_lines_dup(const config_line_t *inp)
* escape that value. Return NULL if no such key exists. */
config_line_t *
config_get_assigned_option(const config_format_t *fmt, const void *options,
- const char *key, int escape_val)
+ const char *key, int escape_val)
{
const config_var_t *var;
const void *value;
@@ -804,11 +843,13 @@ options_trial_assign() calls config_assign(1, 1)
*/
int
config_assign(const config_format_t *fmt, void *options, config_line_t *list,
- int use_defaults, int clear_first, char **msg)
+ unsigned config_assign_flags, char **msg)
{
config_line_t *p;
bitarray_t *options_seen;
const int n_options = config_count_options(fmt);
+ const unsigned clear_first = config_assign_flags & CAL_CLEAR_FIRST;
+ const unsigned use_defaults = config_assign_flags & CAL_USE_DEFAULTS;
CONFIG_CHECK(fmt, options);
@@ -832,8 +873,8 @@ config_assign(const config_format_t *fmt, void *options, config_line_t *list,
/* pass 3: assign. */
while (list) {
int r;
- if ((r=config_assign_line(fmt, options, list, use_defaults,
- clear_first, options_seen, msg))) {
+ if ((r=config_assign_line(fmt, options, list, config_assign_flags,
+ options_seen, msg))) {
bitarray_free(options_seen);
return r;
}
@@ -1029,7 +1070,7 @@ config_dup(const config_format_t *fmt, const void *old)
line = config_get_assigned_option(fmt, old, fmt->vars[i].name, 0);
if (line) {
char *msg = NULL;
- if (config_assign(fmt, newopts, line, 0, 0, &msg) < 0) {
+ if (config_assign(fmt, newopts, line, 0, &msg) < 0) {
log_err(LD_BUG, "config_get_assigned_option() generated "
"something we couldn't config_assign(): %s", msg);
tor_free(msg);
diff --git a/src/or/confparse.h b/src/or/confparse.h
index ca6fb5ec43..8d915d266b 100644
--- a/src/or/confparse.h
+++ b/src/or/confparse.h
@@ -48,6 +48,11 @@ typedef struct config_abbrev_t {
int warn;
} config_abbrev_t;
+typedef struct config_deprecation_t {
+ const char *name;
+ const char *why_deprecated;
+} config_deprecation_t;
+
/* Handy macro for declaring "In the config file or on the command line,
* you can abbreviate <b>tok</b>s as <b>tok</b>". */
#define PLURAL(tok) { #tok, #tok "s", 0, 0 }
@@ -76,6 +81,7 @@ typedef struct config_format_t {
off_t magic_offset; /**< Offset of the magic value within the struct. */
config_abbrev_t *abbrevs; /**< List of abbreviations that we expand when
* parsing this format. */
+ const config_deprecation_t *deprecations; /** List of deprecated options */
config_var_t *vars; /**< List of variables we recognize, their default
* values, and where we stick them in the structure. */
validate_fn_t validate_fn; /**< Function to validate config. */
@@ -92,6 +98,10 @@ typedef struct config_format_t {
*(uint32_t*)STRUCT_VAR_P(cfg,fmt->magic_offset)); \
STMT_END
+#define CAL_USE_DEFAULTS (1u<<0)
+#define CAL_CLEAR_FIRST (1u<<1)
+#define CAL_WARN_DEPRECATIONS (1u<<2)
+
void *config_new(const config_format_t *fmt);
void config_line_append(config_line_t **lst,
const char *key, const char *val);
@@ -114,9 +124,11 @@ char *config_dump(const config_format_t *fmt, const void *default_options,
int comment_defaults);
int config_assign(const config_format_t *fmt, void *options,
config_line_t *list,
- int use_defaults, int clear_first, char **msg);
+ unsigned flags, char **msg);
config_var_t *config_find_option_mutable(config_format_t *fmt,
const char *key);
+const char *config_find_deprecation(const config_format_t *fmt,
+ const char *key);
const config_var_t *config_find_option(const config_format_t *fmt,
const char *key);
@@ -125,6 +137,7 @@ void config_free_lines(config_line_t *front);
const char *config_expand_abbrev(const config_format_t *fmt,
const char *option,
int command_line, int warn_obsolete);
+void warn_deprecated_option(const char *what, const char *why);
#endif
diff --git a/src/or/control.c b/src/or/control.c
index a67395e3c0..1337af4201 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -871,7 +871,8 @@ control_setconf_helper(control_connection_t *conn, uint32_t len, char *body,
config_line_t *lines=NULL;
char *start = body;
char *errstring = NULL;
- const int clear_first = 1;
+ const unsigned flags =
+ CAL_CLEAR_FIRST | (use_defaults ? CAL_USE_DEFAULTS : 0);
char *config;
smartlist_t *entries = smartlist_new();
@@ -931,7 +932,7 @@ control_setconf_helper(control_connection_t *conn, uint32_t len, char *body,
}
tor_free(config);
- opt_err = options_trial_assign(lines, use_defaults, clear_first, &errstring);
+ opt_err = options_trial_assign(lines, flags, &errstring);
{
const char *msg;
switch (opt_err) {
diff --git a/src/or/dirvote.c b/src/or/dirvote.c
index 94a13e365d..9748f4ae4d 100644
--- a/src/or/dirvote.c
+++ b/src/or/dirvote.c
@@ -2577,7 +2577,7 @@ get_next_valid_after_time(time_t now)
tor_assert(new_voting_schedule);
next_valid_after_time = new_voting_schedule->interval_starts;
- tor_free(new_voting_schedule);
+ voting_schedule_free(new_voting_schedule);
return next_valid_after_time;
}
@@ -2601,7 +2601,7 @@ dirvote_recalculate_timing(const or_options_t *options, time_t now)
/* Fill in the global static struct now */
memcpy(&voting_schedule, new_voting_schedule, sizeof(voting_schedule));
- tor_free(new_voting_schedule);
+ voting_schedule_free(new_voting_schedule);
}
/* Populate and return a new voting_schedule_t that can be used to schedule
@@ -2660,6 +2660,16 @@ get_voting_schedule(const or_options_t *options, time_t now, int severity)
return new_voting_schedule;
}
+/** Frees a voting_schedule_t. This should be used instead of the generic
+ * tor_free. */
+void
+voting_schedule_free(voting_schedule_t *voting_schedule_to_free)
+{
+ if (!voting_schedule_to_free)
+ return;
+ tor_free(voting_schedule_to_free);
+}
+
/** Entry point: Take whatever voting actions are pending as of <b>now</b>. */
void
dirvote_act(const or_options_t *options, time_t now)
diff --git a/src/or/dirvote.h b/src/or/dirvote.h
index 2a83802307..a1f71ce4bb 100644
--- a/src/or/dirvote.h
+++ b/src/or/dirvote.h
@@ -157,6 +157,8 @@ typedef struct {
voting_schedule_t *get_voting_schedule(const or_options_t *options,
time_t now, int severity);
+void voting_schedule_free(voting_schedule_t *voting_schedule_to_free);
+
void dirvote_get_preferred_voting_intervals(vote_timing_t *timing_out);
time_t dirvote_get_start_of_next_interval(time_t now,
int interval,
diff --git a/src/or/main.c b/src/or/main.c
index a1b5954aaf..03c2b7ed58 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -2817,7 +2817,7 @@ tor_init(int argc, char *argv[])
{
const char *version = get_version();
- log_notice(LD_GENERAL, "Tor v%s running on %s with Libevent %s, "
+ log_notice(LD_GENERAL, "Tor %s running on %s with Libevent %s, "
"OpenSSL %s and Zlib %s.", version,
get_uname(),
tor_libevent_get_version_str(),
diff --git a/src/or/microdesc.c b/src/or/microdesc.c
index 130259a29f..a81dc54628 100644
--- a/src/or/microdesc.c
+++ b/src/or/microdesc.c
@@ -108,6 +108,7 @@ dump_microdescriptor(int fd, microdesc_t *md, size_t *annotation_len_out)
md->off = tor_fd_getpos(fd);
written = write_all(fd, md->body, md->bodylen, 0);
if (written != (ssize_t)md->bodylen) {
+ written = written < 0 ? 0 : written;
log_warn(LD_DIR,
"Couldn't dump microdescriptor (wrote %ld out of %lu): %s",
(long)written, (unsigned long)md->bodylen,
diff --git a/src/or/or.h b/src/or/or.h
index 7eaeac8ecd..be58fa0d0a 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -5233,7 +5233,10 @@ typedef enum {
CRN_WEIGHT_AS_EXIT = 1<<5,
CRN_NEED_DESC = 1<<6,
/* On clients, only provide nodes that satisfy ClientPreferIPv6OR */
- CRN_PREF_ADDR = 1<<7
+ CRN_PREF_ADDR = 1<<7,
+ /* On clients, only provide nodes that we can connect to directly, based on
+ * our firewall rules */
+ CRN_DIRECT_CONN = 1<<8
} router_crn_flags_t;
/** Return value for router_add_to_routerlist() and dirserv_add_descriptor() */
diff --git a/src/or/router.c b/src/or/router.c
index bfc2d125fb..e9961d4594 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -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)
+{
+ 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);
+
+ 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);
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index d713fe4854..1773f1d05c 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -2245,7 +2245,7 @@ void
router_add_running_nodes_to_smartlist(smartlist_t *sl, int allow_invalid,
int need_uptime, int need_capacity,
int need_guard, int need_desc,
- int pref_addr)
+ int pref_addr, int direct_conn)
{
const int check_reach = !router_skip_or_reachability(get_options(),
pref_addr);
@@ -2260,10 +2260,10 @@ router_add_running_nodes_to_smartlist(smartlist_t *sl, int allow_invalid,
continue;
if (node_is_unreliable(node, need_uptime, need_capacity, need_guard))
continue;
- /* Choose a node with an OR address that matches the firewall rules */
- if (check_reach && !fascist_firewall_allows_node(node,
- FIREWALL_OR_CONNECTION,
- pref_addr))
+ /* Choose a node with an OR address that matches the firewall rules,
+ * if we are making a direct connection */
+ if (direct_conn && check_reach &&
+ !fascist_firewall_allows_node(node, FIREWALL_OR_CONNECTION, pref_addr))
continue;
smartlist_add(sl, (void *)node);
@@ -2717,6 +2717,7 @@ router_choose_random_node(smartlist_t *excludedsmartlist,
const int weight_for_exit = (flags & CRN_WEIGHT_AS_EXIT) != 0;
const int need_desc = (flags & CRN_NEED_DESC) != 0;
const int pref_addr = (flags & CRN_PREF_ADDR) != 0;
+ const int direct_conn = (flags & CRN_DIRECT_CONN) != 0;
smartlist_t *sl=smartlist_new(),
*excludednodes=smartlist_new();
@@ -2742,7 +2743,8 @@ router_choose_random_node(smartlist_t *excludedsmartlist,
router_add_running_nodes_to_smartlist(sl, allow_invalid,
need_uptime, need_capacity,
- need_guard, need_desc, pref_addr);
+ need_guard, need_desc, pref_addr,
+ direct_conn);
log_debug(LD_CIRC,
"We found %d running nodes.",
smartlist_len(sl));
@@ -4544,10 +4546,10 @@ dir_server_new(int is_authority,
if (nickname)
tor_asprintf(&ent->description, "directory server \"%s\" at %s:%d",
- nickname, hostname, (int)dir_port);
+ nickname, hostname_, (int)dir_port);
else
tor_asprintf(&ent->description, "directory server at %s:%d",
- hostname, (int)dir_port);
+ hostname_, (int)dir_port);
ent->fake_status.addr = ent->addr;
tor_addr_copy(&ent->fake_status.ipv6_addr, &ent->ipv6_addr);
diff --git a/src/or/routerlist.h b/src/or/routerlist.h
index 9765ee7ff4..72ab6d9bf3 100644
--- a/src/or/routerlist.h
+++ b/src/or/routerlist.h
@@ -65,7 +65,7 @@ int routers_have_same_or_addrs(const routerinfo_t *r1, const routerinfo_t *r2);
void router_add_running_nodes_to_smartlist(smartlist_t *sl, int allow_invalid,
int need_uptime, int need_capacity,
int need_guard, int need_desc,
- int pref_addr);
+ int pref_addr, int direct_conn);
const routerinfo_t *routerlist_find_my_routerinfo(void);
uint32_t router_get_advertised_bandwidth(const routerinfo_t *router);
diff --git a/src/or/shared_random.c b/src/or/shared_random.c
index 0a1f24a974..19564f5924 100644
--- a/src/or/shared_random.c
+++ b/src/or/shared_random.c
@@ -1328,7 +1328,7 @@ sr_act_post_consensus(const networkstatus_t *consensus)
get_voting_schedule(options,time(NULL), LOG_NOTICE);
time_t interval_starts = voting_schedule->interval_starts;
sr_state_update(interval_starts);
- tor_free(voting_schedule);
+ voting_schedule_free(voting_schedule);
}
}
diff --git a/src/or/shared_random_state.c b/src/or/shared_random_state.c
index 52a0034db7..87db9031ee 100644
--- a/src/or/shared_random_state.c
+++ b/src/or/shared_random_state.c
@@ -86,6 +86,7 @@ static const config_format_t state_format = {
SR_DISK_STATE_MAGIC,
STRUCT_OFFSET(sr_disk_state_t, magic_),
NULL,
+ NULL,
state_vars,
disk_state_validate_cb,
&state_extra_var,
@@ -150,7 +151,7 @@ get_start_time_of_current_round(time_t now)
voting_interval,
options->TestingV3AuthVotingStartOffset);
- tor_free(new_voting_schedule);
+ voting_schedule_free(new_voting_schedule);
return curr_start;
}
@@ -700,7 +701,7 @@ disk_state_load_from_disk_impl(const char *fname)
}
disk_state = disk_state_new(time(NULL));
- config_assign(&state_format, disk_state, lines, 0, 0, &errmsg);
+ config_assign(&state_format, disk_state, lines, 0, &errmsg);
config_free_lines(lines);
if (errmsg) {
log_warn(LD_DIR, "SR: Reading state error: %s", errmsg);
diff --git a/src/or/statefile.c b/src/or/statefile.c
index 9594d9cec3..adf9d9f038 100644
--- a/src/or/statefile.c
+++ b/src/or/statefile.c
@@ -121,6 +121,7 @@ static const config_format_t state_format = {
OR_STATE_MAGIC,
STRUCT_OFFSET(or_state_t, magic_),
state_abbrevs_,
+ NULL,
state_vars_,
or_state_validate_cb,
&state_extra_var,
@@ -349,7 +350,7 @@ or_state_load(void)
if (config_get_lines(contents, &lines, 0)<0)
goto done;
assign_retval = config_assign(&state_format, new_state,
- lines, 0, 0, &errmsg);
+ lines, 0, &errmsg);
config_free_lines(lines);
if (assign_retval<0)
badstate = 1;