diff options
Diffstat (limited to 'src/app')
-rw-r--r-- | src/app/config/config.c | 523 | ||||
-rw-r--r-- | src/app/config/config.h | 10 | ||||
-rw-r--r-- | src/app/config/include.am | 2 | ||||
-rw-r--r-- | src/app/config/or_options_st.h | 3 | ||||
-rw-r--r-- | src/app/config/resolve_addr.c | 314 | ||||
-rw-r--r-- | src/app/config/resolve_addr.h | 28 | ||||
-rw-r--r-- | src/app/config/statefile.c | 2 | ||||
-rw-r--r-- | src/app/config/testnet.inc | 2 | ||||
-rw-r--r-- | src/app/main/main.c | 38 | ||||
-rw-r--r-- | src/app/main/ntmain.c | 2 | ||||
-rw-r--r-- | src/app/main/shutdown.c | 3 | ||||
-rw-r--r-- | src/app/main/subsysmgr.c | 14 | ||||
-rw-r--r-- | src/app/main/subsysmgr.h | 2 | ||||
-rw-r--r-- | src/app/main/subsystem_list.c | 18 |
14 files changed, 540 insertions, 421 deletions
diff --git a/src/app/config/config.c b/src/app/config/config.c index 7ed60c4745..a0c188adc4 100644 --- a/src/app/config/config.c +++ b/src/app/config/config.c @@ -182,7 +182,7 @@ static const char unix_q_socket_prefix[] = "unix:\""; * *DowloadInitialDelay . */ #ifndef COCCI #define DOWNLOAD_SCHEDULE(name) \ - { #name "DownloadSchedule", #name "DownloadInitialDelay", 0, 1 } + { (#name "DownloadSchedule"), (#name "DownloadInitialDelay"), 0, 1 } #else #define DOWNLOAD_SCHEDULE(name) { NULL, NULL, 0, 1 } #endif /* !defined(COCCI) */ @@ -366,7 +366,7 @@ static const config_var_t option_vars_[] = { #endif /* defined(HAVE_MODULE_RELAY) || defined(TOR_UNIT_TESTS) */ V(ClientPreferIPv6ORPort, AUTOBOOL, "auto"), V(ClientPreferIPv6DirPort, AUTOBOOL, "auto"), - V(ClientAutoIPv6ORPort, BOOL, "0"), + OBSOLETE("ClientAutoIPv6ORPort"), V(ClientRejectInternalAddresses, BOOL, "1"), V(ClientTransportPlugin, LINELIST, NULL), V(ClientUseIPv6, BOOL, "0"), @@ -510,6 +510,8 @@ static const config_var_t option_vars_[] = { LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceEnableIntroDoSBurstPerSec", LINELIST_S, RendConfigLines, NULL), + VAR("HiddenServiceOnionBalanceInstance", + LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceStatistics", BOOL, HiddenServiceStatistics_option, "1"), V(HidServAuth, LINELIST, NULL), V(ClientOnionAuthDir, FILENAME, NULL), @@ -2496,6 +2498,9 @@ static const struct { .command=CMD_IMMEDIATE }, { .name="--nt-service" }, { .name="-nt-service" }, + { .name="--dbg-dump-subsystem-list", + .command=CMD_IMMEDIATE, + .quiet=QUIET_HUSH }, { .name=NULL }, }; @@ -2717,23 +2722,6 @@ list_enabled_modules(void) // test variants in test_parseconf.sh to no useful purpose. } -/** Last value actually set by resolve_my_address. */ -static uint32_t last_resolved_addr = 0; - -/** Accessor for last_resolved_addr from outside this file. */ -uint32_t -get_last_resolved_addr(void) -{ - return last_resolved_addr; -} - -/** Reset last_resolved_addr from outside this file. */ -void -reset_last_resolved_addr(void) -{ - last_resolved_addr = 0; -} - /* Return true if <b>options</b> is using the default authorities, and false * if any authority-related option has been overridden. */ int @@ -2742,277 +2730,6 @@ using_default_dir_authorities(const or_options_t *options) return (!options->DirAuthorities && !options->AlternateDirAuthority); } -/** - * Attempt getting our non-local (as judged by tor_addr_is_internal() - * function) IP address using following techniques, listed in - * order from best (most desirable, try first) to worst (least - * desirable, try if everything else fails). - * - * First, attempt using <b>options-\>Address</b> to get our - * non-local IP address. - * - * If <b>options-\>Address</b> represents a non-local IP address, - * consider it ours. - * - * If <b>options-\>Address</b> is a DNS name that resolves to - * a non-local IP address, consider this IP address ours. - * - * If <b>options-\>Address</b> is NULL, fall back to getting local - * hostname and using it in above-described ways to try and - * get our IP address. - * - * In case local hostname cannot be resolved to a non-local IP - * address, try getting an IP address of network interface - * in hopes it will be non-local one. - * - * Fail if one or more of the following is true: - * - DNS name in <b>options-\>Address</b> cannot be resolved. - * - <b>options-\>Address</b> is a local host address. - * - Attempt at getting local hostname fails. - * - Attempt at getting network interface address fails. - * - * Return 0 if all is well, or -1 if we can't find a suitable - * public IP address. - * - * If we are returning 0: - * - Put our public IP address (in host order) into *<b>addr_out</b>. - * - If <b>method_out</b> is non-NULL, set *<b>method_out</b> to a static - * string describing how we arrived at our answer. - * - "CONFIGURED" - parsed from IP address string in - * <b>options-\>Address</b> - * - "RESOLVED" - resolved from DNS name in <b>options-\>Address</b> - * - "GETHOSTNAME" - resolved from a local hostname. - * - "INTERFACE" - retrieved from a network interface. - * - If <b>hostname_out</b> is non-NULL, and we resolved a hostname to - * get our address, set *<b>hostname_out</b> to a newly allocated string - * holding that hostname. (If we didn't get our address by resolving a - * hostname, set *<b>hostname_out</b> to NULL.) - * - * XXXX ipv6 - */ -int -resolve_my_address(int warn_severity, const or_options_t *options, - uint32_t *addr_out, - const char **method_out, char **hostname_out) -{ - struct in_addr in; - uint32_t addr; /* host order */ - char hostname[256]; - const char *method_used; - const char *hostname_used; - int explicit_ip=1; - int explicit_hostname=1; - int from_interface=0; - char *addr_string = NULL; - const char *address = options->Address; - int notice_severity = warn_severity <= LOG_NOTICE ? - LOG_NOTICE : warn_severity; - - tor_addr_t myaddr; - tor_assert(addr_out); - - /* - * Step one: Fill in 'hostname' to be our best guess. - */ - - if (address && *address) { - strlcpy(hostname, address, sizeof(hostname)); - } else { /* then we need to guess our address */ - explicit_ip = 0; /* it's implicit */ - explicit_hostname = 0; /* it's implicit */ - - if (tor_gethostname(hostname, sizeof(hostname)) < 0) { - log_fn(warn_severity, LD_NET,"Error obtaining local hostname"); - return -1; - } - log_debug(LD_CONFIG, "Guessed local host name as '%s'", hostname); - } - - /* - * Step two: Now that we know 'hostname', parse it or resolve it. If - * it doesn't parse or resolve, look at the interface address. Set 'addr' - * to be our (host-order) 32-bit answer. - */ - - if (tor_inet_aton(hostname, &in) == 0) { - /* then we have to resolve it */ - explicit_ip = 0; - if (tor_lookup_hostname(hostname, &addr)) { /* failed to resolve */ - uint32_t interface_ip; /* host order */ - - if (explicit_hostname) { - log_fn(warn_severity, LD_CONFIG, - "Could not resolve local Address '%s'. Failing.", hostname); - return -1; - } - log_fn(notice_severity, LD_CONFIG, - "Could not resolve guessed local hostname '%s'. " - "Trying something else.", hostname); - if (get_interface_address(warn_severity, &interface_ip)) { - log_fn(warn_severity, LD_CONFIG, - "Could not get local interface IP address. Failing."); - return -1; - } - from_interface = 1; - addr = interface_ip; - log_fn(notice_severity, LD_CONFIG, "Learned IP address '%s' for " - "local interface. Using that.", fmt_addr32(addr)); - strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname)); - } else { /* resolved hostname into addr */ - tor_addr_from_ipv4h(&myaddr, addr); - - if (!explicit_hostname && - tor_addr_is_internal(&myaddr, 0)) { - tor_addr_t interface_ip; - - log_fn(notice_severity, LD_CONFIG, "Guessed local hostname '%s' " - "resolves to a private IP address (%s). Trying something " - "else.", hostname, fmt_addr32(addr)); - - if (get_interface_address6(warn_severity, AF_INET, &interface_ip)<0) { - log_fn(warn_severity, LD_CONFIG, - "Could not get local interface IP address. Too bad."); - } else if (tor_addr_is_internal(&interface_ip, 0)) { - log_fn(notice_severity, LD_CONFIG, - "Interface IP address '%s' is a private address too. " - "Ignoring.", fmt_addr(&interface_ip)); - } else { - from_interface = 1; - addr = tor_addr_to_ipv4h(&interface_ip); - log_fn(notice_severity, LD_CONFIG, - "Learned IP address '%s' for local interface." - " Using that.", fmt_addr32(addr)); - strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname)); - } - } - } - } else { - addr = ntohl(in.s_addr); /* set addr so that addr_string is not - * illformed */ - } - - /* - * Step three: Check whether 'addr' is an internal IP address, and error - * out if it is and we don't want that. - */ - - tor_addr_from_ipv4h(&myaddr,addr); - - addr_string = tor_dup_ip(addr); - if (tor_addr_is_internal(&myaddr, 0)) { - /* make sure we're ok with publishing an internal IP */ - if (using_default_dir_authorities(options)) { - /* if they are using the default authorities, disallow internal IPs - * always. */ - log_fn(warn_severity, LD_CONFIG, - "Address '%s' resolves to private IP address '%s'. " - "Tor servers that use the default DirAuthorities must have " - "public IP addresses.", hostname, addr_string); - tor_free(addr_string); - return -1; - } - if (!explicit_ip) { - /* even if they've set their own authorities, require an explicit IP if - * they're using an internal address. */ - log_fn(warn_severity, LD_CONFIG, "Address '%s' resolves to private " - "IP address '%s'. Please set the Address config option to be " - "the IP address you want to use.", hostname, addr_string); - tor_free(addr_string); - return -1; - } - } - - /* - * Step four: We have a winner! 'addr' is our answer for sure, and - * 'addr_string' is its string form. Fill out the various fields to - * say how we decided it. - */ - - log_debug(LD_CONFIG, "Resolved Address to '%s'.", addr_string); - - if (explicit_ip) { - method_used = "CONFIGURED"; - hostname_used = NULL; - } else if (explicit_hostname) { - method_used = "RESOLVED"; - hostname_used = hostname; - } else if (from_interface) { - method_used = "INTERFACE"; - hostname_used = NULL; - } else { - method_used = "GETHOSTNAME"; - hostname_used = hostname; - } - - *addr_out = addr; - if (method_out) - *method_out = method_used; - if (hostname_out) - *hostname_out = hostname_used ? tor_strdup(hostname_used) : NULL; - - /* - * Step five: Check if the answer has changed since last time (or if - * there was no last time), and if so call various functions to keep - * us up-to-date. - */ - - if (last_resolved_addr && last_resolved_addr != *addr_out) { - /* Leave this as a notice, regardless of the requested severity, - * at least until dynamic IP address support becomes bulletproof. */ - log_notice(LD_NET, - "Your IP address seems to have changed to %s " - "(METHOD=%s%s%s). Updating.", - addr_string, method_used, - hostname_used ? " HOSTNAME=" : "", - hostname_used ? hostname_used : ""); - ip_address_changed(0); - } - - if (last_resolved_addr != *addr_out) { - control_event_server_status(LOG_NOTICE, - "EXTERNAL_ADDRESS ADDRESS=%s METHOD=%s%s%s", - addr_string, method_used, - hostname_used ? " HOSTNAME=" : "", - hostname_used ? hostname_used : ""); - } - last_resolved_addr = *addr_out; - - /* - * And finally, clean up and return success. - */ - - tor_free(addr_string); - return 0; -} - -/** Return true iff <b>addr</b> is judged to be on the same network as us, or - * on a private network. - */ -MOCK_IMPL(int, -is_local_addr, (const tor_addr_t *addr)) -{ - if (tor_addr_is_internal(addr, 0)) - return 1; - /* Check whether ip is on the same /24 as we are. */ - if (get_options()->EnforceDistinctSubnets == 0) - return 0; - if (tor_addr_family(addr) == AF_INET) { - uint32_t ip = tor_addr_to_ipv4h(addr); - - /* It's possible that this next check will hit before the first time - * resolve_my_address actually succeeds. (For clients, it is likely that - * resolve_my_address will never be called at all). In those cases, - * last_resolved_addr will be 0, and so checking to see whether ip is on - * the same /24 as last_resolved_addr will be the same as checking whether - * it was on net 0, which is already done by tor_addr_is_internal. - */ - if ((last_resolved_addr & (uint32_t)0xffffff00ul) - == (ip & (uint32_t)0xffffff00ul)) - return 1; - } - return 0; -} - /** Return a new empty or_options_t. Used for testing. */ or_options_t * options_new(void) @@ -3719,7 +3436,7 @@ options_validate_cb(const void *old_options_, void *options_, char **msg) "UseEntryGuards is disabled, but you have configured one or more " "hidden services on this Tor instance. Your hidden services " "will be very easy to locate using a well-known attack -- see " - "http://freehaven.net/anonbib/#hs-attack06 for details."); + "https://freehaven.net/anonbib/#hs-attack06 for details."); } if (options->NumPrimaryGuards && options->NumEntryGuards && @@ -4194,8 +3911,11 @@ options_validate_cb(const void *old_options_, void *options_, char **msg) * actual maximum value. We clip this value if it's too low, and autodetect * it if it's set to 0. */ STATIC uint64_t -compute_real_max_mem_in_queues(const uint64_t val, int log_guess) +compute_real_max_mem_in_queues(const uint64_t val, bool is_server) { +#define MIN_SERVER_MB 64 +#define MIN_UNWARNED_SERVER_MB 256 +#define MIN_UNWARNED_CLIENT_MB 64 uint64_t result; if (val == 0) { @@ -4253,7 +3973,7 @@ compute_real_max_mem_in_queues(const uint64_t val, int log_guess) result = avail; } } - if (log_guess && ! notice_sent) { + if (is_server && ! notice_sent) { log_notice(LD_CONFIG, "%sMaxMemInQueues is set to %"PRIu64" MB. " "You can override this by setting MaxMemInQueues by hand.", ram ? "Based on detected system memory, " : "", @@ -4261,10 +3981,24 @@ compute_real_max_mem_in_queues(const uint64_t val, int log_guess) notice_sent = 1; } return result; - } else if (val < ONE_GIGABYTE / 4) { - log_warn(LD_CONFIG, "MaxMemInQueues must be at least 256 MB for now. " - "Ideally, have it as large as you can afford."); - return ONE_GIGABYTE / 4; + } else if (is_server && val < ONE_MEGABYTE * MIN_SERVER_MB) { + /* We can't configure less than this much on a server. */ + log_warn(LD_CONFIG, "MaxMemInQueues must be at least %d MB on servers " + "for now. Ideally, have it as large as you can afford.", + MIN_SERVER_MB); + return MIN_SERVER_MB * ONE_MEGABYTE; + } else if (is_server && val < ONE_MEGABYTE * MIN_UNWARNED_SERVER_MB) { + /* On a server, if it's less than this much, we warn that things + * may go badly. */ + log_warn(LD_CONFIG, "MaxMemInQueues is set to a low value; if your " + "relay doesn't work, this may be the reason why."); + return val; + } else if (! is_server && val < ONE_MEGABYTE * MIN_UNWARNED_CLIENT_MB) { + /* On a client, if it's less than this much, we warn that things + * may go badly. */ + log_warn(LD_CONFIG, "MaxMemInQueues is set to a low value; if your " + "client doesn't work, this may be the reason why."); + return val; } else { /* The value was fine all along */ return val; @@ -4601,6 +4335,10 @@ options_init_from_torrc(int argc, char **argv) list_deprecated_options(); return 1; } + if (config_line_find(cmdline_only_options, "--dbg-dump-subsystem-list")) { + subsystems_dump_list(); + return 1; + } if (config_line_find(cmdline_only_options, "--version")) { printf("Tor version %s.\n",get_version()); @@ -5875,18 +5613,28 @@ parse_dir_fallback_line(const char *line, return r; } -/** Allocate and return a new port_cfg_t with reasonable defaults. */ +/** Allocate and return a new port_cfg_t with reasonable defaults. + * + * <b>namelen</b> is the length of the unix socket name + * (typically the filesystem path), not including the trailing NUL. + * It should be 0 for ports that are not zunix sockets. */ port_cfg_t * port_cfg_new(size_t namelen) { tor_assert(namelen <= SIZE_T_CEILING - sizeof(port_cfg_t) - 1); port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t) + namelen + 1); + + /* entry_cfg flags */ cfg->entry_cfg.ipv4_traffic = 1; cfg->entry_cfg.ipv6_traffic = 1; cfg->entry_cfg.prefer_ipv6 = 0; cfg->entry_cfg.dns_request = 1; cfg->entry_cfg.onion_traffic = 1; cfg->entry_cfg.prefer_ipv6_virtaddr = 1; + cfg->entry_cfg.session_group = SESSION_GROUP_UNSET; + cfg->entry_cfg.isolation_flags = ISO_DEFAULT; + + /* Other flags default to 0 due to tor_malloc_zero */ return cfg; } @@ -5995,7 +5743,7 @@ port_cfg_line_extract_addrport(const char *line, size_t sz; *is_unix_out = 1; *addrport_out = NULL; - line += strlen(unix_socket_prefix); /*No q: Keep the quote */ + line += strlen(unix_socket_prefix); /* No 'unix:', but keep the quote */ *rest_out = unescape_string(line, addrport_out, &sz); if (!*rest_out || (*addrport_out && sz != strlen(*addrport_out))) { tor_free(*addrport_out); @@ -6090,11 +5838,12 @@ port_parse_config(smartlist_t *out, const unsigned is_unix_socket = flags & CL_PORT_IS_UNIXSOCKET; int got_zero_port=0, got_nonzero_port=0; char *unix_socket_path = NULL; + port_cfg_t *cfg = NULL; /* If there's no FooPort, then maybe make a default one. */ if (! ports) { if (defaultport && defaultaddr && out) { - port_cfg_t *cfg = port_cfg_new(is_unix_socket ? strlen(defaultaddr) : 0); + cfg = port_cfg_new(is_unix_socket ? strlen(defaultaddr) : 0); cfg->type = listener_type; if (is_unix_socket) { tor_addr_make_unspec(&cfg->addr); @@ -6104,8 +5853,6 @@ port_parse_config(smartlist_t *out, cfg->port = defaultport; tor_addr_parse(&cfg->addr, defaultaddr); } - cfg->entry_cfg.session_group = SESSION_GROUP_UNSET; - cfg->entry_cfg.isolation_flags = ISO_DEFAULT; smartlist_add(out, cfg); } return 0; @@ -6119,28 +5866,12 @@ port_parse_config(smartlist_t *out, for (; ports; ports = ports->next) { tor_addr_t addr; tor_addr_make_unspec(&addr); - - int port; - int sessiongroup = SESSION_GROUP_UNSET; - unsigned isolation = ISO_DEFAULT; - int prefer_no_auth = 0; - int socks_iso_keep_alive = 0; - + int port, ok, + has_used_unix_socket_only_option = 0, + is_unix_tagged_addr = 0; uint16_t ptmp=0; - int ok; - /* This must be kept in sync with port_cfg_new's defaults */ - int no_listen = 0, no_advertise = 0, all_addrs = 0, - bind_ipv4_only = 0, bind_ipv6_only = 0, - ipv4_traffic = 1, ipv6_traffic = 1, prefer_ipv6 = 0, dns_request = 1, - onion_traffic = 1, - cache_ipv4 = 0, use_cached_ipv4 = 0, - cache_ipv6 = 0, use_cached_ipv6 = 0, - prefer_ipv6_automap = 1, world_writable = 0, group_writable = 0, - relax_dirmode_check = 0, - has_used_unix_socket_only_option = 0, extended_errors = 0; - - int is_unix_tagged_addr = 0; const char *rest_of_line = NULL; + if (port_cfg_line_extract_addrport(ports->value, &addrport, &is_unix_tagged_addr, &rest_of_line)<0) { log_warn(LD_CONFIG, "Invalid %sPort line with unparsable address", @@ -6216,17 +5947,20 @@ port_parse_config(smartlist_t *out, } } + /* Default port_cfg_t object initialization */ + cfg = port_cfg_new(unix_socket_path ? strlen(unix_socket_path) : 0); + if (unix_socket_path && default_to_group_writable) - group_writable = 1; + cfg->is_group_writable = 1; /* Now parse the rest of the options, if any. */ if (use_server_options) { /* This is a server port; parse advertising options */ SMARTLIST_FOREACH_BEGIN(elts, char *, elt) { if (!strcasecmp(elt, "NoAdvertise")) { - no_advertise = 1; + cfg->server_cfg.no_advertise = 1; } else if (!strcasecmp(elt, "NoListen")) { - no_listen = 1; + cfg->server_cfg.no_listen = 1; #if 0 /* not implemented yet. */ } else if (!strcasecmp(elt, "AllAddrs")) { @@ -6234,33 +5968,36 @@ port_parse_config(smartlist_t *out, all_addrs = 1; #endif /* 0 */ } else if (!strcasecmp(elt, "IPv4Only")) { - bind_ipv4_only = 1; + cfg->server_cfg.bind_ipv4_only = 1; } else if (!strcasecmp(elt, "IPv6Only")) { - bind_ipv6_only = 1; + cfg->server_cfg.bind_ipv6_only = 1; } else { log_warn(LD_CONFIG, "Unrecognized %sPort option '%s'", portname, escaped(elt)); } } SMARTLIST_FOREACH_END(elt); - if (no_advertise && no_listen) { + if (cfg->server_cfg.no_advertise && cfg->server_cfg.no_listen) { log_warn(LD_CONFIG, "Tried to set both NoListen and NoAdvertise " "on %sPort line '%s'", portname, escaped(ports->value)); goto err; } - if (bind_ipv4_only && bind_ipv6_only) { + if (cfg->server_cfg.bind_ipv4_only && + cfg->server_cfg.bind_ipv6_only) { log_warn(LD_CONFIG, "Tried to set both IPv4Only and IPv6Only " "on %sPort line '%s'", portname, escaped(ports->value)); goto err; } - if (bind_ipv4_only && tor_addr_family(&addr) != AF_INET) { + if (cfg->server_cfg.bind_ipv4_only && + tor_addr_family(&addr) != AF_INET) { log_warn(LD_CONFIG, "Could not interpret %sPort address as IPv4", portname); goto err; } - if (bind_ipv6_only && tor_addr_family(&addr) != AF_INET6) { + if (cfg->server_cfg.bind_ipv6_only && + tor_addr_family(&addr) != AF_INET6) { log_warn(LD_CONFIG, "Could not interpret %sPort address as IPv6", portname); goto err; @@ -6279,12 +6016,12 @@ port_parse_config(smartlist_t *out, portname, escaped(elt)); goto err; } - if (sessiongroup >= 0) { + if (cfg->entry_cfg.session_group >= 0) { log_warn(LD_CONFIG, "Multiple SessionGroup options on %sPort", portname); goto err; } - sessiongroup = group; + cfg->entry_cfg.session_group = group; continue; } @@ -6294,15 +6031,15 @@ port_parse_config(smartlist_t *out, } if (!strcasecmp(elt, "GroupWritable")) { - group_writable = !no; + cfg->is_group_writable = !no; has_used_unix_socket_only_option = 1; continue; } else if (!strcasecmp(elt, "WorldWritable")) { - world_writable = !no; + cfg->is_world_writable = !no; has_used_unix_socket_only_option = 1; continue; } else if (!strcasecmp(elt, "RelaxDirModeCheck")) { - relax_dirmode_check = !no; + cfg->relax_dirmode_check = !no; has_used_unix_socket_only_option = 1; continue; } @@ -6315,19 +6052,19 @@ port_parse_config(smartlist_t *out, if (takes_hostnames) { if (!strcasecmp(elt, "IPv4Traffic")) { - ipv4_traffic = ! no; + cfg->entry_cfg.ipv4_traffic = ! no; continue; } else if (!strcasecmp(elt, "IPv6Traffic")) { - ipv6_traffic = ! no; + cfg->entry_cfg.ipv6_traffic = ! no; continue; } else if (!strcasecmp(elt, "PreferIPv6")) { - prefer_ipv6 = ! no; + cfg->entry_cfg.prefer_ipv6 = ! no; continue; } else if (!strcasecmp(elt, "DNSRequest")) { - dns_request = ! no; + cfg->entry_cfg.dns_request = ! no; continue; } else if (!strcasecmp(elt, "OnionTraffic")) { - onion_traffic = ! no; + cfg->entry_cfg.onion_traffic = ! no; continue; } else if (!strcasecmp(elt, "OnionTrafficOnly")) { /* Only connect to .onion addresses. Equivalent to @@ -6338,46 +6075,50 @@ port_parse_config(smartlist_t *out, "DNSRequest, IPv4Traffic, and/or IPv6Traffic instead.", portname, escaped(elt)); } else { - ipv4_traffic = ipv6_traffic = dns_request = 0; + cfg->entry_cfg.ipv4_traffic = 0; + cfg->entry_cfg.ipv6_traffic = 0; + cfg->entry_cfg.dns_request = 0; } continue; } } if (!strcasecmp(elt, "CacheIPv4DNS")) { warn_client_dns_cache(elt, no); // since 0.2.9.2-alpha - cache_ipv4 = ! no; + cfg->entry_cfg.cache_ipv4_answers = ! no; continue; } else if (!strcasecmp(elt, "CacheIPv6DNS")) { warn_client_dns_cache(elt, no); // since 0.2.9.2-alpha - cache_ipv6 = ! no; + cfg->entry_cfg.cache_ipv6_answers = ! no; continue; } else if (!strcasecmp(elt, "CacheDNS")) { warn_client_dns_cache(elt, no); // since 0.2.9.2-alpha - cache_ipv4 = cache_ipv6 = ! no; + cfg->entry_cfg.cache_ipv4_answers = ! no; + cfg->entry_cfg.cache_ipv6_answers = ! no; continue; } else if (!strcasecmp(elt, "UseIPv4Cache")) { warn_client_dns_cache(elt, no); // since 0.2.9.2-alpha - use_cached_ipv4 = ! no; + cfg->entry_cfg.use_cached_ipv4_answers = ! no; continue; } else if (!strcasecmp(elt, "UseIPv6Cache")) { warn_client_dns_cache(elt, no); // since 0.2.9.2-alpha - use_cached_ipv6 = ! no; + cfg->entry_cfg.use_cached_ipv6_answers = ! 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; + cfg->entry_cfg.use_cached_ipv4_answers = ! no; + cfg->entry_cfg.use_cached_ipv6_answers = ! no; continue; } else if (!strcasecmp(elt, "PreferIPv6Automap")) { - prefer_ipv6_automap = ! no; + cfg->entry_cfg.prefer_ipv6_virtaddr = ! no; continue; } else if (!strcasecmp(elt, "PreferSOCKSNoAuth")) { - prefer_no_auth = ! no; + cfg->entry_cfg.socks_prefer_no_auth = ! no; continue; } else if (!strcasecmp(elt, "KeepAliveIsolateSOCKSAuth")) { - socks_iso_keep_alive = ! no; + cfg->entry_cfg.socks_iso_keep_alive = ! no; continue; } else if (!strcasecmp(elt, "ExtendedErrors")) { - extended_errors = ! no; + cfg->entry_cfg.extended_socks5_codes = ! no; continue; } @@ -6400,9 +6141,9 @@ port_parse_config(smartlist_t *out, } if (no) { - isolation &= ~isoflag; + cfg->entry_cfg.isolation_flags &= ~isoflag; } else { - isolation |= isoflag; + cfg->entry_cfg.isolation_flags |= isoflag; } } SMARTLIST_FOREACH_END(elt); } @@ -6412,51 +6153,51 @@ port_parse_config(smartlist_t *out, else got_zero_port = 1; - if (dns_request == 0 && listener_type == CONN_TYPE_AP_DNS_LISTENER) { + if (cfg->entry_cfg.dns_request == 0 && + listener_type == CONN_TYPE_AP_DNS_LISTENER) { log_warn(LD_CONFIG, "You have a %sPort entry with DNS disabled; that " "won't work.", portname); goto err; } - - if (ipv4_traffic == 0 && ipv6_traffic == 0 && onion_traffic == 0 - && listener_type != CONN_TYPE_AP_DNS_LISTENER) { + if (cfg->entry_cfg.ipv4_traffic == 0 && + cfg->entry_cfg.ipv6_traffic == 0 && + cfg->entry_cfg.onion_traffic == 0 && + listener_type != CONN_TYPE_AP_DNS_LISTENER) { log_warn(LD_CONFIG, "You have a %sPort entry with all of IPv4 and " "IPv6 and .onion disabled; that won't work.", portname); goto err; } - - if (dns_request == 1 && ipv4_traffic == 0 && ipv6_traffic == 0 - && listener_type != CONN_TYPE_AP_DNS_LISTENER) { + if (cfg->entry_cfg.dns_request == 1 && + cfg->entry_cfg.ipv4_traffic == 0 && + cfg->entry_cfg.ipv6_traffic == 0 && + listener_type != CONN_TYPE_AP_DNS_LISTENER) { log_warn(LD_CONFIG, "You have a %sPort entry with DNSRequest enabled, " "but IPv4 and IPv6 disabled; DNS-based sites won't work.", portname); goto err; } - - if ( has_used_unix_socket_only_option && ! unix_socket_path) { + if (has_used_unix_socket_only_option && !unix_socket_path) { log_warn(LD_CONFIG, "You have a %sPort entry with GroupWritable, " "WorldWritable, or RelaxDirModeCheck, but it is not a " "unix socket.", portname); goto err; } - - if (!(isolation & ISO_SOCKSAUTH) && socks_iso_keep_alive) { + if (!(cfg->entry_cfg.isolation_flags & ISO_SOCKSAUTH) && + cfg->entry_cfg.socks_iso_keep_alive) { log_warn(LD_CONFIG, "You have a %sPort entry with both " "NoIsolateSOCKSAuth and KeepAliveIsolateSOCKSAuth set.", portname); goto err; } - - if (unix_socket_path && (isolation & ISO_CLIENTADDR)) { + if (unix_socket_path && + (cfg->entry_cfg.isolation_flags & ISO_CLIENTADDR)) { /* `IsolateClientAddr` is nonsensical in the context of AF_LOCAL. * just silently remove the isolation flag. */ - isolation &= ~ISO_CLIENTADDR; + cfg->entry_cfg.isolation_flags &= ~ISO_CLIENTADDR; } - if (out && port) { size_t namelen = unix_socket_path ? strlen(unix_socket_path) : 0; - port_cfg_t *cfg = port_cfg_new(namelen); if (unix_socket_path) { tor_addr_make_unspec(&cfg->addr); memcpy(cfg->unix_addr, unix_socket_path, namelen + 1); @@ -6467,33 +6208,13 @@ port_parse_config(smartlist_t *out, cfg->port = port; } cfg->type = listener_type; - cfg->is_world_writable = world_writable; - cfg->is_group_writable = group_writable; - cfg->relax_dirmode_check = relax_dirmode_check; - cfg->entry_cfg.isolation_flags = isolation; - cfg->entry_cfg.session_group = sessiongroup; - cfg->server_cfg.no_advertise = no_advertise; - cfg->server_cfg.no_listen = no_listen; - cfg->server_cfg.all_addrs = all_addrs; - cfg->server_cfg.bind_ipv4_only = bind_ipv4_only; - cfg->server_cfg.bind_ipv6_only = bind_ipv6_only; - cfg->entry_cfg.ipv4_traffic = ipv4_traffic; - cfg->entry_cfg.ipv6_traffic = ipv6_traffic; - cfg->entry_cfg.prefer_ipv6 = prefer_ipv6; - cfg->entry_cfg.dns_request = dns_request; - cfg->entry_cfg.onion_traffic = onion_traffic; - cfg->entry_cfg.cache_ipv4_answers = cache_ipv4; - cfg->entry_cfg.cache_ipv6_answers = cache_ipv6; - cfg->entry_cfg.use_cached_ipv4_answers = use_cached_ipv4; - cfg->entry_cfg.use_cached_ipv6_answers = use_cached_ipv6; - cfg->entry_cfg.prefer_ipv6_virtaddr = prefer_ipv6_automap; - cfg->entry_cfg.socks_prefer_no_auth = prefer_no_auth; - if (! (isolation & ISO_SOCKSAUTH)) + if (! (cfg->entry_cfg.isolation_flags & ISO_SOCKSAUTH)) cfg->entry_cfg.socks_prefer_no_auth = 1; - cfg->entry_cfg.socks_iso_keep_alive = socks_iso_keep_alive; - cfg->entry_cfg.extended_socks5_codes = extended_errors; - smartlist_add(out, cfg); + /* out owns cfg now, don't re-use or free it */ + cfg = NULL; + } else { + tor_free(cfg); } SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp)); smartlist_clear(elts); @@ -6519,10 +6240,22 @@ port_parse_config(smartlist_t *out, retval = 0; err: + /* There are two ways we can error out: + * 1. part way through the loop: cfg needs to be freed; + * 2. ending the loop normally: cfg is always NULL. + * In this case, cfg has either been: + * - added to out, then set to NULL, or + * - freed and set to NULL (because out is NULL, or port is 0). + */ + tor_free(cfg); + + /* Free the other variables from the loop. + * elts is always non-NULL here, but it may or may not be empty. */ SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp)); smartlist_free(elts); tor_free(unix_socket_path); tor_free(addrport); + return retval; } diff --git a/src/app/config/config.h b/src/app/config/config.h index 311e27917a..1ba10d1d37 100644 --- a/src/app/config/config.h +++ b/src/app/config/config.h @@ -42,6 +42,8 @@ const char *escaped_safe_str(const char *address); void init_protocol_warning_severity_level(void); int get_protocol_warning_severity_level(void); +#define LOG_PROTOCOL_WARN (get_protocol_warning_severity_level()) + /** An error from options_trial_assign() or options_init_from_string(). */ typedef enum setopt_err_t { SETOPT_OK = 0, @@ -53,12 +55,6 @@ typedef enum setopt_err_t { setopt_err_t options_trial_assign(struct config_line_t *list, unsigned flags, char **msg); -uint32_t get_last_resolved_addr(void); -void reset_last_resolved_addr(void); -int resolve_my_address(int warn_severity, const or_options_t *options, - uint32_t *addr_out, - const char **method_out, char **hostname_out); -MOCK_DECL(int, is_local_addr, (const tor_addr_t *addr)); void options_init(or_options_t *options); #define OPTIONS_DUMP_MINIMAL 1 @@ -298,7 +294,7 @@ STATIC int parse_dir_authority_line(const char *line, STATIC int parse_dir_fallback_line(const char *line, int validate_only); STATIC uint64_t compute_real_max_mem_in_queues(const uint64_t val, - int log_guess); + bool is_server); STATIC int open_and_add_file_log(const log_severity_list_t *severity, const char *fname, int truncate_log); diff --git a/src/app/config/include.am b/src/app/config/include.am index 5d625efecf..14320a6b11 100644 --- a/src/app/config/include.am +++ b/src/app/config/include.am @@ -3,6 +3,7 @@ LIBTOR_APP_A_SOURCES += \ src/app/config/config.c \ src/app/config/quiet_level.c \ + src/app/config/resolve_addr.c \ src/app/config/statefile.c # ADD_C_FILE: INSERT HEADERS HERE. @@ -11,6 +12,7 @@ noinst_HEADERS += \ src/app/config/or_options_st.h \ src/app/config/or_state_st.h \ src/app/config/quiet_level.h \ + src/app/config/resolve_addr.h \ src/app/config/statefile.h \ src/app/config/tor_cmdline_mode.h diff --git a/src/app/config/or_options_st.h b/src/app/config/or_options_st.h index 35ba15a9e2..bf58205f89 100644 --- a/src/app/config/or_options_st.h +++ b/src/app/config/or_options_st.h @@ -662,9 +662,6 @@ struct or_options_t { * accessing this value directly. */ int ClientPreferIPv6DirPort; - /** If true, prefer an IPv4 or IPv6 OR port at random. */ - int ClientAutoIPv6ORPort; - /** The length of time that we think a consensus should be fresh. */ int V3AuthVotingInterval; /** The length of time we think it will take to distribute votes. */ diff --git a/src/app/config/resolve_addr.c b/src/app/config/resolve_addr.c new file mode 100644 index 0000000000..9d1a8e0260 --- /dev/null +++ b/src/app/config/resolve_addr.c @@ -0,0 +1,314 @@ +/* Copyright (c) 2020, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file resolve_addr.c + * \brief Implement resolving address functions + **/ + +#define RESOLVE_ADDR_PRIVATE + +#include "app/config/config.h" +#include "app/config/resolve_addr.h" + +#include "core/mainloop/mainloop.h" + +#include "feature/control/control_events.h" + +#include "lib/net/gethostname.h" +#include "lib/net/resolve.h" + +/** Last value actually set by resolve_my_address. */ +static uint32_t last_resolved_addr = 0; + +/** Accessor for last_resolved_addr from outside this file. */ +uint32_t +get_last_resolved_addr(void) +{ + return last_resolved_addr; +} + +/** Reset last_resolved_addr from outside this file. */ +void +reset_last_resolved_addr(void) +{ + last_resolved_addr = 0; +} + +/** + * Attempt getting our non-local (as judged by tor_addr_is_internal() + * function) IP address using following techniques, listed in + * order from best (most desirable, try first) to worst (least + * desirable, try if everything else fails). + * + * First, attempt using <b>options-\>Address</b> to get our + * non-local IP address. + * + * If <b>options-\>Address</b> represents a non-local IP address, + * consider it ours. + * + * If <b>options-\>Address</b> is a DNS name that resolves to + * a non-local IP address, consider this IP address ours. + * + * If <b>options-\>Address</b> is NULL, fall back to getting local + * hostname and using it in above-described ways to try and + * get our IP address. + * + * In case local hostname cannot be resolved to a non-local IP + * address, try getting an IP address of network interface + * in hopes it will be non-local one. + * + * Fail if one or more of the following is true: + * - DNS name in <b>options-\>Address</b> cannot be resolved. + * - <b>options-\>Address</b> is a local host address. + * - Attempt at getting local hostname fails. + * - Attempt at getting network interface address fails. + * + * Return 0 if all is well, or -1 if we can't find a suitable + * public IP address. + * + * If we are returning 0: + * - Put our public IP address (in host order) into *<b>addr_out</b>. + * - If <b>method_out</b> is non-NULL, set *<b>method_out</b> to a static + * string describing how we arrived at our answer. + * - "CONFIGURED" - parsed from IP address string in + * <b>options-\>Address</b> + * - "RESOLVED" - resolved from DNS name in <b>options-\>Address</b> + * - "GETHOSTNAME" - resolved from a local hostname. + * - "INTERFACE" - retrieved from a network interface. + * - If <b>hostname_out</b> is non-NULL, and we resolved a hostname to + * get our address, set *<b>hostname_out</b> to a newly allocated string + * holding that hostname. (If we didn't get our address by resolving a + * hostname, set *<b>hostname_out</b> to NULL.) + * + * XXXX ipv6 + */ +int +resolve_my_address(int warn_severity, const or_options_t *options, + uint32_t *addr_out, + const char **method_out, char **hostname_out) +{ + struct in_addr in; + uint32_t addr; /* host order */ + char hostname[256]; + const char *method_used; + const char *hostname_used; + int explicit_ip=1; + int explicit_hostname=1; + int from_interface=0; + char *addr_string = NULL; + const char *address = options->Address; + int notice_severity = warn_severity <= LOG_NOTICE ? + LOG_NOTICE : warn_severity; + + tor_addr_t myaddr; + tor_assert(addr_out); + + /* + * Step one: Fill in 'hostname' to be our best guess. + */ + + if (address && *address) { + strlcpy(hostname, address, sizeof(hostname)); + log_debug(LD_CONFIG, "Trying configured Address '%s' as local hostname", + hostname); + } else { /* then we need to guess our address */ + explicit_ip = 0; /* it's implicit */ + explicit_hostname = 0; /* it's implicit */ + + if (tor_gethostname(hostname, sizeof(hostname)) < 0) { + log_fn(warn_severity, LD_NET,"Error obtaining local hostname"); + return -1; + } + log_debug(LD_CONFIG, "Guessed local host name as '%s'", hostname); + } + + /* + * Step two: Now that we know 'hostname', parse it or resolve it. If + * it doesn't parse or resolve, look at the interface address. Set 'addr' + * to be our (host-order) 32-bit answer. + */ + + if (tor_inet_aton(hostname, &in) == 0) { + /* then we have to resolve it */ + log_debug(LD_CONFIG, "Local hostname '%s' is DNS address. " + "Trying to resolve to IP address.", hostname); + explicit_ip = 0; + if (tor_lookup_hostname(hostname, &addr)) { /* failed to resolve */ + uint32_t interface_ip; /* host order */ + + if (explicit_hostname) { + log_fn(warn_severity, LD_CONFIG, + "Could not resolve local Address '%s'. Failing.", hostname); + return -1; + } + log_fn(notice_severity, LD_CONFIG, + "Could not resolve guessed local hostname '%s'. " + "Trying something else.", hostname); + if (get_interface_address(warn_severity, &interface_ip)) { + log_fn(warn_severity, LD_CONFIG, + "Could not get local interface IP address. Failing."); + return -1; + } + from_interface = 1; + addr = interface_ip; + log_fn(notice_severity, LD_CONFIG, "Learned IP address '%s' for " + "local interface. Using that.", fmt_addr32(addr)); + strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname)); + } else { /* resolved hostname into addr */ + tor_addr_from_ipv4h(&myaddr, addr); + + if (!explicit_hostname && + tor_addr_is_internal(&myaddr, 0)) { + tor_addr_t interface_ip; + + log_fn(notice_severity, LD_CONFIG, "Guessed local hostname '%s' " + "resolves to a private IP address (%s). Trying something " + "else.", hostname, fmt_addr32(addr)); + + if (get_interface_address6(warn_severity, AF_INET, &interface_ip)<0) { + log_fn(warn_severity, LD_CONFIG, + "Could not get local interface IP address. Too bad."); + } else if (tor_addr_is_internal(&interface_ip, 0)) { + log_fn(notice_severity, LD_CONFIG, + "Interface IP address '%s' is a private address too. " + "Ignoring.", fmt_addr(&interface_ip)); + } else { + from_interface = 1; + addr = tor_addr_to_ipv4h(&interface_ip); + log_fn(notice_severity, LD_CONFIG, + "Learned IP address '%s' for local interface." + " Using that.", fmt_addr32(addr)); + strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname)); + } + } + } + } else { + log_debug(LD_CONFIG, "Local hostname '%s' is already IP address, " + "skipping DNS resolution", hostname); + addr = ntohl(in.s_addr); /* set addr so that addr_string is not + * illformed */ + } + + /* + * Step three: Check whether 'addr' is an internal IP address, and error + * out if it is and we don't want that. + */ + + tor_addr_from_ipv4h(&myaddr,addr); + + addr_string = tor_dup_ip(addr); + if (addr_string && tor_addr_is_internal(&myaddr, 0)) { + /* make sure we're ok with publishing an internal IP */ + if (using_default_dir_authorities(options)) { + /* if they are using the default authorities, disallow internal IPs + * always. For IPv6 ORPorts, this check is done in + * router_get_advertised_ipv6_or_ap(). See #33681. */ + log_fn(warn_severity, LD_CONFIG, + "Address '%s' resolves to private IP address '%s'. " + "Tor servers that use the default DirAuthorities must have " + "public IP addresses.", hostname, addr_string); + tor_free(addr_string); + return -1; + } + if (!explicit_ip) { + /* even if they've set their own authorities, require an explicit IP if + * they're using an internal address. */ + log_fn(warn_severity, LD_CONFIG, "Address '%s' resolves to private " + "IP address '%s'. Please set the Address config option to be " + "the IP address you want to use.", hostname, addr_string); + tor_free(addr_string); + return -1; + } + } + + /* + * Step four: We have a winner! 'addr' is our answer for sure, and + * 'addr_string' is its string form. Fill out the various fields to + * say how we decided it. + */ + + log_debug(LD_CONFIG, "Resolved Address to '%s'.", addr_string); + + if (explicit_ip) { + method_used = "CONFIGURED"; + hostname_used = NULL; + } else if (explicit_hostname) { + method_used = "RESOLVED"; + hostname_used = hostname; + } else if (from_interface) { + method_used = "INTERFACE"; + hostname_used = NULL; + } else { + method_used = "GETHOSTNAME"; + hostname_used = hostname; + } + + *addr_out = addr; + if (method_out) + *method_out = method_used; + if (hostname_out) + *hostname_out = hostname_used ? tor_strdup(hostname_used) : NULL; + + /* + * Step five: Check if the answer has changed since last time (or if + * there was no last time), and if so call various functions to keep + * us up-to-date. + */ + + if (last_resolved_addr && last_resolved_addr != *addr_out) { + /* Leave this as a notice, regardless of the requested severity, + * at least until dynamic IP address support becomes bulletproof. */ + log_notice(LD_NET, + "Your IP address seems to have changed to %s " + "(METHOD=%s%s%s). Updating.", + addr_string, method_used, + hostname_used ? " HOSTNAME=" : "", + hostname_used ? hostname_used : ""); + ip_address_changed(0); + } + + if (last_resolved_addr != *addr_out) { + control_event_server_status(LOG_NOTICE, + "EXTERNAL_ADDRESS ADDRESS=%s METHOD=%s%s%s", + addr_string, method_used, + hostname_used ? " HOSTNAME=" : "", + hostname_used ? hostname_used : ""); + } + last_resolved_addr = *addr_out; + + /* + * And finally, clean up and return success. + */ + + tor_free(addr_string); + return 0; +} + +/** Return true iff <b>addr</b> is judged to be on the same network as us, or + * on a private network. + */ +MOCK_IMPL(int, +is_local_addr, (const tor_addr_t *addr)) +{ + if (tor_addr_is_internal(addr, 0)) + return 1; + /* Check whether ip is on the same /24 as we are. */ + if (get_options()->EnforceDistinctSubnets == 0) + return 0; + if (tor_addr_family(addr) == AF_INET) { + uint32_t ip = tor_addr_to_ipv4h(addr); + + /* It's possible that this next check will hit before the first time + * resolve_my_address actually succeeds. (For clients, it is likely that + * resolve_my_address will never be called at all). In those cases, + * last_resolved_addr will be 0, and so checking to see whether ip is on + * the same /24 as last_resolved_addr will be the same as checking whether + * it was on net 0, which is already done by tor_addr_is_internal. + */ + if ((last_resolved_addr & (uint32_t)0xffffff00ul) + == (ip & (uint32_t)0xffffff00ul)) + return 1; + } + return 0; +} diff --git a/src/app/config/resolve_addr.h b/src/app/config/resolve_addr.h new file mode 100644 index 0000000000..3747546402 --- /dev/null +++ b/src/app/config/resolve_addr.h @@ -0,0 +1,28 @@ +/* Copyright (c) 2020, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file resolve_addr.h + * \brief Header file for resolve_addr.c. + **/ + +#ifndef TOR_CONFIG_RESOLVE_ADDR_H +#define TOR_CONFIG_RESOLVE_ADDR_H + +#include "app/config/or_options_st.h" + +int resolve_my_address(int warn_severity, const or_options_t *options, + uint32_t *addr_out, + const char **method_out, char **hostname_out); + +uint32_t get_last_resolved_addr(void); +void reset_last_resolved_addr(void); + +MOCK_DECL(int, is_local_addr, (const tor_addr_t *addr)); + +#ifdef RESOLVE_ADDR_PRIVATE + +#endif /* RESOLVE_ADDR_PRIVATE */ + +#endif /* TOR_CONFIG_RESOLVE_ADDR_H */ + diff --git a/src/app/config/statefile.c b/src/app/config/statefile.c index d9667733cc..dcc55f1898 100644 --- a/src/app/config/statefile.c +++ b/src/app/config/statefile.c @@ -78,6 +78,7 @@ DUMMY_TYPECHECK_INSTANCE(or_state_t); VAR(#member, conftype, member, initvalue) /** Array of "state" variables saved to the ~/.tor/state file. */ +// clang-format off static const config_var_t state_vars_[] = { /* Remember to document these in state-contents.txt ! */ @@ -134,6 +135,7 @@ static const config_var_t state_vars_[] = { END_OF_CONFIG_VARS }; +// clang-format on #undef VAR #undef V diff --git a/src/app/config/testnet.inc b/src/app/config/testnet.inc index f146a03cd1..907c35f97c 100644 --- a/src/app/config/testnet.inc +++ b/src/app/config/testnet.inc @@ -1,3 +1,5 @@ +// When modifying, don't forget to update the defaults +// for 'TestingTorNetwork' in 'doc/tor.1.txt' { "DirAllowPrivateAddresses", "1" }, { "EnforceDistinctSubnets", "0" }, { "AssumeReachable", "1" }, diff --git a/src/app/main/main.c b/src/app/main/main.c index 689bc526ab..d7d36bff4e 100644 --- a/src/app/main/main.c +++ b/src/app/main/main.c @@ -294,6 +294,19 @@ process_signal(int sig) } } +#ifdef _WIN32 +/** Activate SIGINT on reciving a control signal in console */ +static BOOL WINAPI +process_win32_console_ctrl(DWORD ctrl_type) +{ + /* Ignore type of the ctrl signal */ + (void) ctrl_type; + + activate_signal(SIGINT); + return TRUE; +} +#endif + /** * Write current memory usage information to the log. */ @@ -414,6 +427,7 @@ dumpstats(int severity) rep_hist_dump_stats(now,severity); rend_service_dump_stats(severity); + hs_service_dump_stats(severity); } #ifdef _WIN32 @@ -496,6 +510,13 @@ handle_signals(void) &signal_handlers[i].signal_value); } } + +#ifdef _WIN32 + /* Windows lacks traditional POSIX signals but WinAPI provides a function + * to handle control signals like Ctrl+C in the console, we can use this to + * simulate the SIGINT signal */ + if (enabled) SetConsoleCtrlHandler(process_win32_console_ctrl, TRUE); +#endif } /* Cause the signal handler for signal_num to be called in the event loop. */ @@ -801,6 +822,9 @@ sandbox_init_filter(void) #define OPEN(name) \ sandbox_cfg_allow_open_filename(&cfg, tor_strdup(name)) +#define OPENDIR(dir) \ + sandbox_cfg_allow_opendir_dirname(&cfg, tor_strdup(dir)) + #define OPEN_DATADIR(name) \ sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname(name)) @@ -817,8 +841,10 @@ sandbox_init_filter(void) OPEN_DATADIR2(name, name2 suffix); \ } while (0) +// KeyDirectory is a directory, but it is only opened in check_private_dir +// which calls open instead of opendir #define OPEN_KEY_DIRECTORY() \ - sandbox_cfg_allow_open_filename(&cfg, tor_strdup(options->KeyDirectory)) + OPEN(options->KeyDirectory) #define OPEN_CACHEDIR(name) \ sandbox_cfg_allow_open_filename(&cfg, get_cachedir_fname(name)) #define OPEN_CACHEDIR_SUFFIX(name, suffix) do { \ @@ -832,6 +858,8 @@ sandbox_init_filter(void) OPEN_KEYDIR(name suffix); \ } while (0) + // DataDirectory is a directory, but it is only opened in check_private_dir + // which calls open instead of opendir OPEN(options->DataDirectory); OPEN_KEY_DIRECTORY(); @@ -879,7 +907,11 @@ sandbox_init_filter(void) } SMARTLIST_FOREACH(options->FilesOpenedByIncludes, char *, f, { - OPEN(f); + if (file_status(f) == FN_DIR) { + OPENDIR(f); + } else { + OPEN(f); + } }); #define RENAME_SUFFIX(name, suffix) \ @@ -992,7 +1024,7 @@ sandbox_init_filter(void) * directory that holds it. */ char *dirname = tor_strdup(port->unix_addr); if (get_parent_directory(dirname) == 0) { - OPEN(dirname); + OPENDIR(dirname); } tor_free(dirname); sandbox_cfg_allow_chmod_filename(&cfg, tor_strdup(port->unix_addr)); diff --git a/src/app/main/ntmain.c b/src/app/main/ntmain.c index 4941199759..5dc0edd591 100644 --- a/src/app/main/ntmain.c +++ b/src/app/main/ntmain.c @@ -603,7 +603,7 @@ nt_service_install(int argc, char **argv) /* Genericity is apparently _so_ last year in Redmond, where some * accounts are accounts that you can look up, and some accounts * are magic and undetectable via the security subsystem. See - * http://msdn2.microsoft.com/en-us/library/ms684188.aspx + * https://msdn2.microsoft.com/en-us/library/ms684188.aspx */ printf("Running on a Post-Win2K OS, so we'll assume that the " "LocalService account exists.\n"); diff --git a/src/app/main/shutdown.c b/src/app/main/shutdown.c index 27d92609eb..aac15246b9 100644 --- a/src/app/main/shutdown.c +++ b/src/app/main/shutdown.c @@ -75,7 +75,8 @@ tor_cleanup(void) /* Remove Extended ORPort cookie authentication file */ { char *cookie_fname = get_ext_or_auth_cookie_file_name(); - tor_remove_file(cookie_fname); + if (cookie_fname) + tor_remove_file(cookie_fname); tor_free(cookie_fname); } if (accounting_is_enabled(options)) diff --git a/src/app/main/subsysmgr.c b/src/app/main/subsysmgr.c index 5807cbbaa4..de601d28cd 100644 --- a/src/app/main/subsysmgr.c +++ b/src/app/main/subsysmgr.c @@ -294,6 +294,20 @@ subsystems_thread_cleanup(void) } /** + * Dump a human- and machine-readable list of all the subsystems to stdout, + * in their initialization order, prefixed with their level. + **/ +void +subsystems_dump_list(void) +{ + for (unsigned i = 0; i < n_tor_subsystems - 1; ++i) { + const subsys_fns_t *sys = tor_subsystems[i]; + printf("% 4d\t%16s\t%s\n", sys->level, sys->name, + sys->location?sys->location:""); + } +} + +/** * Register all subsystem-declared options formats in <b>mgr</b>. * * Return 0 on success, -1 on failure. diff --git a/src/app/main/subsysmgr.h b/src/app/main/subsysmgr.h index 35635a756e..ae0b3df469 100644 --- a/src/app/main/subsysmgr.h +++ b/src/app/main/subsysmgr.h @@ -31,6 +31,8 @@ void subsystems_prefork(void); void subsystems_postfork(void); void subsystems_thread_cleanup(void); +void subsystems_dump_list(void); + struct config_mgr_t; int subsystems_register_options_formats(struct config_mgr_t *mgr); int subsystems_register_state_formats(struct config_mgr_t *mgr); diff --git a/src/app/main/subsystem_list.c b/src/app/main/subsystem_list.c index b4439cdc7b..e32083537f 100644 --- a/src/app/main/subsystem_list.c +++ b/src/app/main/subsystem_list.c @@ -14,9 +14,7 @@ #include "lib/cc/torint.h" #include "core/mainloop/mainloop_sys.h" -#include "core/or/ocirc_event_sys.h" #include "core/or/or_sys.h" -#include "core/or/orconn_event_sys.h" #include "feature/control/btrack_sys.h" #include "lib/compress/compress_sys.h" #include "lib/crypt_ops/crypto_sys.h" @@ -24,7 +22,7 @@ #include "lib/log/log_sys.h" #include "lib/net/network_sys.h" #include "lib/process/process_sys.h" -#include "lib/process/winprocess_sys.h" +#include "lib/llharden/winprocess_sys.h" #include "lib/thread/thread_sys.h" #include "lib/time/time_sys.h" #include "lib/tls/tortls_sys.h" @@ -46,28 +44,26 @@ const subsys_fns_t *tor_subsystems[] = { &sys_torerr, &sys_wallclock, - &sys_threads, &sys_logging, + &sys_threads, &sys_time, - &sys_network, - &sys_compress, &sys_crypto, + &sys_compress, + &sys_network, &sys_tortls, - &sys_process, - - &sys_orconn_event, - &sys_ocirc_event, - &sys_btrack, &sys_evloop, + &sys_process, &sys_mainloop, &sys_or, &sys_relay, + &sys_btrack, + &sys_dirauth, }; |