diff options
author | Roger Dingledine <arma@torproject.org> | 2012-09-04 19:05:31 -0400 |
---|---|---|
committer | Roger Dingledine <arma@torproject.org> | 2012-09-04 19:05:31 -0400 |
commit | 33c82ebf51cf2dc106e5de788111e775533aa76a (patch) | |
tree | a6d0ba28e237bc1ed39b203132b9b6ede5559ae8 /src | |
parent | f5541ea4fe0aabe1d2aba49de43a08bbf4cd6bad (diff) | |
parent | 4bd90e20b92fbe2b93fc53e24254f00e663d057e (diff) | |
download | tor-33c82ebf51cf2dc106e5de788111e775533aa76a.tar.gz tor-33c82ebf51cf2dc106e5de788111e775533aa76a.zip |
Merge branch 'maint-0.2.3' into release-0.2.3
Diffstat (limited to 'src')
-rw-r--r-- | src/common/OpenBSD_malloc_Linux.c | 40 | ||||
-rw-r--r-- | src/or/circuitbuild.c | 249 | ||||
-rw-r--r-- | src/or/config.c | 226 | ||||
-rw-r--r-- | src/or/config.h | 5 | ||||
-rw-r--r-- | src/or/control.c | 15 | ||||
-rw-r--r-- | src/or/directory.c | 2 | ||||
-rw-r--r-- | src/or/directory.h | 2 | ||||
-rw-r--r-- | src/or/dirserv.c | 12 | ||||
-rw-r--r-- | src/or/dirvote.c | 49 | ||||
-rw-r--r-- | src/or/dns.c | 16 | ||||
-rw-r--r-- | src/or/microdesc.c | 9 | ||||
-rw-r--r-- | src/or/or.h | 60 | ||||
-rw-r--r-- | src/or/policies.c | 6 | ||||
-rw-r--r-- | src/or/relay.c | 14 | ||||
-rw-r--r-- | src/or/router.c | 5 | ||||
-rw-r--r-- | src/or/routerlist.c | 2 | ||||
-rw-r--r-- | src/or/routerparse.c | 7 |
17 files changed, 546 insertions, 173 deletions
diff --git a/src/common/OpenBSD_malloc_Linux.c b/src/common/OpenBSD_malloc_Linux.c index 92ca9c0066..da82729811 100644 --- a/src/common/OpenBSD_malloc_Linux.c +++ b/src/common/OpenBSD_malloc_Linux.c @@ -14,6 +14,10 @@ * ---------------------------------------------------------------------------- */ +/* We use this macro to remove some code that we don't actually want, + * rather than to fix its warnings. */ +#define BUILDING_FOR_TOR + /* * Defining MALLOC_EXTRA_SANITY will enable extra checks which are * related to internal conditions and consistency in malloc.c. This has @@ -79,6 +83,7 @@ static size_t g_alignment = 0; extern int __libc_enable_secure; +#ifndef HAVE_ISSETUGID static int issetugid(void) { if (__libc_enable_secure) return 1; @@ -86,8 +91,10 @@ static int issetugid(void) if (getgid() != getegid()) return 1; return 0; } +#endif #define PGSHIFT 12 +#undef MADV_FREE #define MADV_FREE MADV_DONTNEED #include <pthread.h> static pthread_mutex_t gen_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -443,6 +450,7 @@ extern char *__progname; static void wrterror(const char *p) { +#ifndef BUILDING_FOR_TOR const char *q = " error: "; struct iovec iov[5]; @@ -457,7 +465,9 @@ wrterror(const char *p) iov[4].iov_base = (char*)"\n"; iov[4].iov_len = 1; writev(STDERR_FILENO, iov, 5); - +#else + (void)p; +#endif suicide = 1; #ifdef MALLOC_STATS if (malloc_stats) @@ -471,14 +481,17 @@ wrterror(const char *p) static void wrtwarning(const char *p) { +#ifndef BUILDING_FOR_TOR const char *q = " warning: "; struct iovec iov[5]; +#endif if (malloc_abort) wrterror(p); else if (malloc_silent) return; +#ifndef BUILDING_FOR_TOR iov[0].iov_base = __progname; iov[0].iov_len = strlen(__progname); iov[1].iov_base = (char*)malloc_func; @@ -489,8 +502,11 @@ wrtwarning(const char *p) iov[3].iov_len = strlen(p); iov[4].iov_base = (char*)"\n"; iov[4].iov_len = 1; - - writev(STDERR_FILENO, iov, 5); + + (void) writev(STDERR_FILENO, iov, 5); +#else + (void)p; +#endif } #ifdef MALLOC_STATS @@ -665,7 +681,7 @@ malloc_init(void) for (i = 0; i < 3; i++) { switch (i) { case 0: - j = readlink("/etc/malloc.conf", b, sizeof b - 1); + j = (int) readlink("/etc/malloc.conf", b, sizeof b - 1); if (j <= 0) continue; b[j] = '\0'; @@ -1145,9 +1161,10 @@ malloc_bytes(size_t size) if (size == 0) j = 0; else { + size_t ii; j = 1; - i = size - 1; - while (i >>= 1) + ii = size - 1; + while (ii >>= 1) j++; } @@ -1971,6 +1988,7 @@ calloc(size_t num, size_t size) return(p); } +#ifndef BUILDING_FOR_TOR static int ispowerof2 (size_t a) { size_t b; for (b = 1ULL << (sizeof(size_t)*NBBY - 1); b > 1; b >>= 1) @@ -1978,7 +1996,9 @@ static int ispowerof2 (size_t a) { return 1; return 0; } +#endif +#ifndef BUILDING_FOR_TOR int posix_memalign(void **memptr, size_t alignment, size_t size) { void *r; @@ -2015,18 +2035,20 @@ void *valloc(size_t size) posix_memalign(&r, malloc_pagesize, size); return r; } +#endif size_t malloc_good_size(size_t size) { if (size == 0) { return 1; } else if (size <= malloc_maxsize) { - int i, j; + int j; + size_t ii; /* round up to the nearest power of 2, with same approach * as malloc_bytes() uses. */ j = 1; - i = size - 1; - while (i >>= 1) + ii = size - 1; + while (ii >>= 1) j++; return ((size_t)1) << j; } else { diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index b82cce9881..e5576018a6 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -135,6 +135,9 @@ static entry_guard_t *entry_guard_get_by_id_digest(const char *digest); static void bridge_free(bridge_info_t *bridge); +static int entry_guard_inc_first_hop_count(entry_guard_t *guard); +static void pathbias_count_success(origin_circuit_t *circ); + /** * This function decides if CBT learning should be disabled. It returns * true if one or more of the following four conditions are met: @@ -1624,7 +1627,7 @@ circuit_build_times_set_timeout(circuit_build_times_t *cbt) return; if (cbt->timeout_ms < circuit_build_times_min_timeout()) { - log_warn(LD_CIRC, "Set buildtimeout to low value %fms. Setting to %dms", + log_info(LD_CIRC, "Set buildtimeout to low value %fms. Setting to %dms", cbt->timeout_ms, circuit_build_times_min_timeout()); cbt->timeout_ms = circuit_build_times_min_timeout(); if (cbt->close_ms < cbt->timeout_ms) { @@ -2285,28 +2288,11 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) } log_info(LD_CIRC,"circuit built!"); circuit_reset_failure_count(0); - /* Don't count cannibalized or onehop circs for path bias */ + if (circ->build_state->onehop_tunnel || circ->has_opened) { control_event_bootstrap(BOOTSTRAP_STATUS_REQUESTING_STATUS, 0); - } else { - entry_guard_t *guard = - entry_guard_get_by_id_digest(circ->_base.n_conn->identity_digest); - - if (guard) { - guard->circuit_successes++; - - log_info(LD_PROTOCOL, "Got success count %u/%u for guard %s=%s", - guard->circuit_successes, guard->first_hops, - guard->nickname, hex_str(guard->identity, DIGEST_LEN)); - - if (guard->first_hops < guard->circuit_successes) { - log_warn(LD_BUG, "Unexpectedly high circuit_successes (%u/%u) " - "for guard %s", - guard->circuit_successes, guard->first_hops, - guard->nickname); - } - } } + if (!can_complete_circuit && !circ->build_state->onehop_tunnel) { const or_options_t *options = get_options(); can_complete_circuit=1; @@ -2322,6 +2308,8 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) consider_testing_reachability(1, 1); } } + + pathbias_count_success(circ); circuit_rep_hist_note_result(circ); circuit_has_opened(circ); /* do other actions as necessary */ @@ -2444,6 +2432,13 @@ circuit_extend(cell_t *cell, circuit_t *circ) return -1; } + if (tor_addr_is_internal(&n_addr, 0) && + !get_options()->ExtendAllowPrivateAddresses) { + log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, + "Client asked me to extend to a private address"); + return -1; + } + /* Check if they asked us for 0000..0000. We support using * an empty fingerprint for the first hop (e.g. for a bridge relay), * but we don't want to let people send us extend cells for empty @@ -2621,6 +2616,194 @@ pathbias_get_scale_factor(const or_options_t *options) DFLT_PATH_BIAS_SCALE_THRESHOLD, 1, INT32_MAX); } +static const char * +pathbias_state_to_string(path_state_t state) +{ + switch (state) { + case PATH_STATE_NEW_CIRC: + return "new"; + case PATH_STATE_DID_FIRST_HOP: + return "first hop"; + case PATH_STATE_SUCCEEDED: + return "succeeded"; + } + + return "unknown"; +} + +/** + * Check our circuit state to see if this is a successful first hop. + * If so, record it in the current guard's path bias first_hop count. + * + * Also check for several potential error cases for bug #6475. + */ +static int +pathbias_count_first_hop(origin_circuit_t *circ) +{ +#define FIRST_HOP_NOTICE_INTERVAL (600) + static ratelim_t first_hop_notice_limit = + RATELIM_INIT(FIRST_HOP_NOTICE_INTERVAL); + char *rate_msg = NULL; + + /* Completely ignore one hop circuits */ + if (circ->build_state->onehop_tunnel) { + tor_assert(circ->build_state->desired_path_len == 1); + return 0; + } + + if (circ->cpath->state == CPATH_STATE_AWAITING_KEYS) { + /* Help track down the real cause of bug #6475: */ + if (circ->has_opened && circ->path_state != PATH_STATE_DID_FIRST_HOP) { + if ((rate_msg = rate_limit_log(&first_hop_notice_limit, + approx_time()))) { + log_info(LD_BUG, + "Opened circuit is in strange path state %s. " + "Circuit is a %s currently %s. %s", + pathbias_state_to_string(circ->path_state), + circuit_purpose_to_string(circ->_base.purpose), + circuit_state_to_string(circ->_base.state), + rate_msg); + } + } + + /* Don't count cannibalized circs for path bias */ + if (!circ->has_opened) { + entry_guard_t *guard; + + guard = entry_guard_get_by_id_digest( + circ->_base.n_conn->identity_digest); + if (guard) { + if (circ->path_state == PATH_STATE_NEW_CIRC) { + circ->path_state = PATH_STATE_DID_FIRST_HOP; + + if (entry_guard_inc_first_hop_count(guard) < 0) { + /* Bogus guard; we already warned. */ + return -END_CIRC_REASON_TORPROTOCOL; + } + } else { + if ((rate_msg = rate_limit_log(&first_hop_notice_limit, + approx_time()))) { + log_info(LD_BUG, + "Unopened circuit has strange path state %s. " + "Circuit is a %s currently %s. %s", + pathbias_state_to_string(circ->path_state), + circuit_purpose_to_string(circ->_base.purpose), + circuit_state_to_string(circ->_base.state), + rate_msg); + } + } + } else { + if ((rate_msg = rate_limit_log(&first_hop_notice_limit, + approx_time()))) { + log_info(LD_BUG, + "Unopened circuit has no known guard. " + "Circuit is a %s currently %s. %s", + circuit_purpose_to_string(circ->_base.purpose), + circuit_state_to_string(circ->_base.state), + rate_msg); + } + } + } + } else { + /* Help track down the real cause of bug #6475: */ + if (circ->path_state == PATH_STATE_NEW_CIRC) { + if ((rate_msg = rate_limit_log(&first_hop_notice_limit, + approx_time()))) { + log_info(LD_BUG, + "A %s circuit is in cpath state %d (opened: %d). " + "Circuit is a %s currently %s. %s", + pathbias_state_to_string(circ->path_state), + circ->cpath->state, circ->has_opened, + circuit_purpose_to_string(circ->_base.purpose), + circuit_state_to_string(circ->_base.state), + rate_msg); + } + } + } + + return 0; +} + +/** + * Check our circuit state to see if this is a successful circuit + * completion. If so, record it in the current guard's path bias + * success count. + * + * Also check for several potential error cases for bug #6475. + */ +static void +pathbias_count_success(origin_circuit_t *circ) +{ +#define SUCCESS_NOTICE_INTERVAL (600) + static ratelim_t success_notice_limit = + RATELIM_INIT(SUCCESS_NOTICE_INTERVAL); + char *rate_msg = NULL; + + /* Ignore one hop circuits */ + if (circ->build_state->onehop_tunnel) { + tor_assert(circ->build_state->desired_path_len == 1); + return; + } + + /* Don't count cannibalized/reused circs for path bias */ + if (!circ->has_opened) { + entry_guard_t *guard = + entry_guard_get_by_id_digest(circ->_base.n_conn->identity_digest); + + if (guard) { + if (circ->path_state == PATH_STATE_DID_FIRST_HOP) { + circ->path_state = PATH_STATE_SUCCEEDED; + guard->circuit_successes++; + + log_info(LD_PROTOCOL, "Got success count %u/%u for guard %s=%s", + guard->circuit_successes, guard->first_hops, + guard->nickname, hex_str(guard->identity, DIGEST_LEN)); + } else { + if ((rate_msg = rate_limit_log(&success_notice_limit, + approx_time()))) { + log_info(LD_BUG, + "Succeeded circuit is in strange path state %s. " + "Circuit is a %s currently %s. %s", + pathbias_state_to_string(circ->path_state), + circuit_purpose_to_string(circ->_base.purpose), + circuit_state_to_string(circ->_base.state), + rate_msg); + } + } + + if (guard->first_hops < guard->circuit_successes) { + log_info(LD_BUG, "Unexpectedly high circuit_successes (%u/%u) " + "for guard %s=%s", + guard->circuit_successes, guard->first_hops, + guard->nickname, hex_str(guard->identity, DIGEST_LEN)); + } + } else { + if ((rate_msg = rate_limit_log(&success_notice_limit, + approx_time()))) { + log_info(LD_BUG, + "Completed circuit has no known guard. " + "Circuit is a %s currently %s. %s", + circuit_purpose_to_string(circ->_base.purpose), + circuit_state_to_string(circ->_base.state), + rate_msg); + } + } + } else { + if (circ->path_state != PATH_STATE_SUCCEEDED) { + if ((rate_msg = rate_limit_log(&success_notice_limit, + approx_time()))) { + log_info(LD_BUG, + "Opened circuit is in strange path state %s. " + "Circuit is a %s currently %s. %s", + pathbias_state_to_string(circ->path_state), + circuit_purpose_to_string(circ->_base.purpose), + circuit_state_to_string(circ->_base.state), + rate_msg); + } + } + } +} + /** Increment the number of times we successfully extended a circuit to * 'guard', first checking if the failure rate is high enough that we should * eliminate the guard. Return -1 if the guard looks no good; return 0 if the @@ -2639,7 +2822,7 @@ entry_guard_inc_first_hop_count(entry_guard_t *guard) if (guard->circuit_successes/((double)guard->first_hops) < pathbias_get_disable_rate(options)) { - log_warn(LD_PROTOCOL, + log_info(LD_PROTOCOL, "Extremely low circuit success rate %u/%u for guard %s=%s. " "This might indicate an attack, or a bug.", guard->circuit_successes, guard->first_hops, guard->nickname, @@ -2652,7 +2835,7 @@ entry_guard_inc_first_hop_count(entry_guard_t *guard) < pathbias_get_notice_rate(options) && !guard->path_bias_notice) { guard->path_bias_notice = 1; - log_notice(LD_PROTOCOL, + log_info(LD_PROTOCOL, "Low circuit success rate %u/%u for guard %s=%s.", guard->circuit_successes, guard->first_hops, guard->nickname, hex_str(guard->identity, DIGEST_LEN)); @@ -2666,8 +2849,9 @@ entry_guard_inc_first_hop_count(entry_guard_t *guard) guard->circuit_successes /= scale_factor; } guard->first_hops++; - log_info(LD_PROTOCOL, "Got success count %u/%u for guard %s", - guard->circuit_successes, guard->first_hops, guard->nickname); + log_info(LD_PROTOCOL, "Got success count %u/%u for guard %s=%s", + guard->circuit_successes, guard->first_hops, guard->nickname, + hex_str(guard->identity, DIGEST_LEN)); return 0; } @@ -2687,22 +2871,13 @@ circuit_finish_handshake(origin_circuit_t *circ, uint8_t reply_type, { char keys[CPATH_KEY_MATERIAL_LEN]; crypt_path_t *hop; + int rv; + + if ((rv = pathbias_count_first_hop(circ)) < 0) + return rv; if (circ->cpath->state == CPATH_STATE_AWAITING_KEYS) { hop = circ->cpath; - /* Don't count cannibalized or onehop circs for path bias */ - if (!circ->has_opened && !circ->build_state->onehop_tunnel) { - entry_guard_t *guard; - - guard = entry_guard_get_by_id_digest( - circ->_base.n_conn->identity_digest); - if (guard) { - if (entry_guard_inc_first_hop_count(guard) < 0) { - /* Bogus guard; we already warned. */ - return -END_CIRC_REASON_TORPROTOCOL; - } - } - } } else { hop = onion_next_hop_in_cpath(circ->cpath); if (!hop) { /* got an extended when we're all done? */ diff --git a/src/or/config.c b/src/or/config.c index a369297518..b9170f4200 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -168,6 +168,9 @@ typedef struct config_var_t { /** An entry for config_vars: "The option <b>name</b> is obsolete." */ #define OBSOLETE(name) { name, CONFIG_TYPE_OBSOLETE, 0, NULL } +#define VPORT(member,conftype,initvalue) \ + VAR(#member, conftype, member ## _lines, initvalue) + /** Array of configuration options. Until we disallow nonstandard * abbreviations, order is significant, since the first matching option will * be chosen first. @@ -229,7 +232,7 @@ static config_var_t _option_vars[] = { V(ConstrainedSockSize, MEMUNIT, "8192"), V(ContactInfo, STRING, NULL), V(ControlListenAddress, LINELIST, NULL), - V(ControlPort, LINELIST, NULL), + VPORT(ControlPort, LINELIST, NULL), V(ControlPortFileGroupReadable,BOOL, "0"), V(ControlPortWriteToFile, FILENAME, NULL), V(ControlSocket, LINELIST, NULL), @@ -246,7 +249,7 @@ static config_var_t _option_vars[] = { V(DirListenAddress, LINELIST, NULL), OBSOLETE("DirFetchPeriod"), V(DirPolicy, LINELIST, NULL), - V(DirPort, LINELIST, NULL), + VPORT(DirPort, LINELIST, NULL), V(DirPortFrontPage, FILENAME, NULL), OBSOLETE("DirPostPeriod"), OBSOLETE("DirRecordUsageByCountry"), @@ -259,7 +262,7 @@ static config_var_t _option_vars[] = { V(DisableDebuggerAttachment, BOOL, "1"), V(DisableIOCP, BOOL, "1"), V(DynamicDHGroups, BOOL, "0"), - V(DNSPort, LINELIST, NULL), + VPORT(DNSPort, LINELIST, NULL), V(DNSListenAddress, LINELIST, NULL), V(DownloadExtraInfo, BOOL, "0"), V(EnforceDistinctSubnets, BOOL, "1"), @@ -273,6 +276,7 @@ static config_var_t _option_vars[] = { V(ExitPolicy, LINELIST, NULL), V(ExitPolicyRejectPrivate, BOOL, "1"), V(ExitPortStatistics, BOOL, "0"), + V(ExtendAllowPrivateAddresses, BOOL, "0"), V(ExtraInfoStatistics, BOOL, "1"), #if defined (WINCE) @@ -345,7 +349,7 @@ static config_var_t _option_vars[] = { V(NewCircuitPeriod, INTERVAL, "30 seconds"), VAR("NamingAuthoritativeDirectory",BOOL, NamingAuthoritativeDir, "0"), V(NATDListenAddress, LINELIST, NULL), - V(NATDPort, LINELIST, NULL), + VPORT(NATDPort, LINELIST, NULL), V(Nickname, STRING, NULL), V(WarnUnsafeSocks, BOOL, "1"), OBSOLETE("NoPublish"), @@ -353,7 +357,7 @@ static config_var_t _option_vars[] = { V(NumCPUs, UINT, "0"), V(NumEntryGuards, UINT, "3"), V(ORListenAddress, LINELIST, NULL), - V(ORPort, LINELIST, NULL), + VPORT(ORPort, LINELIST, NULL), V(OutboundBindAddress, STRING, NULL), V(PathBiasCircThreshold, INT, "-1"), @@ -406,7 +410,7 @@ static config_var_t _option_vars[] = { V(ShutdownWaitLength, INTERVAL, "30 seconds"), V(SocksListenAddress, LINELIST, NULL), V(SocksPolicy, LINELIST, NULL), - V(SocksPort, LINELIST, NULL), + VPORT(SocksPort, LINELIST, NULL), V(SocksTimeout, INTERVAL, "2 minutes"), OBSOLETE("StatusFetchPeriod"), V(StrictNodes, BOOL, "0"), @@ -419,7 +423,7 @@ static config_var_t _option_vars[] = { V(TrackHostExitsExpire, INTERVAL, "30 minutes"), OBSOLETE("TrafficShaping"), V(TransListenAddress, LINELIST, NULL), - V(TransPort, LINELIST, NULL), + VPORT(TransPort, LINELIST, NULL), V(TunnelDirConns, BOOL, "1"), V(UpdateBridgesFromAuthority, BOOL, "0"), V(UseBridges, BOOL, "0"), @@ -460,7 +464,7 @@ static config_var_t _option_vars[] = { /** Override default values with these if the user sets the TestingTorNetwork * option. */ static const config_var_t testing_tor_network_defaults[] = { - V(ServerDNSAllowBrokenConfig, BOOL, "1"), + V(ServerDNSAllowBrokenConfig, BOOL, "1"), V(DirAllowPrivateAddresses, BOOL, "1"), V(EnforceDistinctSubnets, BOOL, "0"), V(AssumeReachable, BOOL, "1"), @@ -470,6 +474,7 @@ static const config_var_t testing_tor_network_defaults[] = { V(ClientRejectInternalAddresses, BOOL, "0"), V(CountPrivateBandwidth, BOOL, "1"), V(ExitPolicyRejectPrivate, BOOL, "0"), + V(ExtendAllowPrivateAddresses, BOOL, "1"), V(V3AuthVotingInterval, INTERVAL, "5 minutes"), V(V3AuthVoteDelay, INTERVAL, "20 seconds"), V(V3AuthDistDelay, INTERVAL, "20 seconds"), @@ -622,7 +627,7 @@ static int parse_dir_server_line(const char *line, dirinfo_type_t required_type, int validate_only); static void port_cfg_free(port_cfg_t *port); -static int parse_ports(const or_options_t *options, int validate_only, +static int parse_ports(or_options_t *options, int validate_only, char **msg_out, int *n_ports_out); static int check_server_ports(const smartlist_t *ports, const or_options_t *options); @@ -1167,7 +1172,7 @@ options_act_reversible(const or_options_t *old_options, char **msg) #if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H) /* Open /dev/pf before dropping privileges. */ - if (options->TransPort) { + if (options->TransPort_set) { if (get_pf_socket() < 0) { *msg = tor_strdup("Unable to open /dev/pf for transparent proxy."); goto rollback; @@ -1650,7 +1655,7 @@ options_act(const or_options_t *old_options) int was_relay = 0; if (options->BridgeRelay) { time_t int_start = time(NULL); - if (config_lines_eq(old_options->ORPort, options->ORPort)) { + if (config_lines_eq(old_options->ORPort_lines,options->ORPort_lines)) { int_start += RELAY_BRIDGE_STATS_DELAY; was_relay = 1; } @@ -1734,7 +1739,7 @@ options_act(const or_options_t *old_options) } else { options->DirReqStatistics = 0; /* Don't warn Tor clients, they don't use statistics */ - if (options->ORPort) + if (options->ORPort_set) log_notice(LD_CONFIG, "Configured to measure directory request " "statistics, but no GeoIP database found. " "Please specify a GeoIP database using the " @@ -3448,7 +3453,8 @@ options_validate(or_options_t *old_options, or_options_t *options, "Tor will still run, but probably won't do anything."); #ifndef USE_TRANSPARENT - if (options->TransPort || options->TransListenAddress) + /* XXXX024 I think we can remove this TransListenAddress */ + if (options->TransPort_set || options->TransListenAddress) REJECT("TransPort and TransListenAddress are disabled in this build."); #endif @@ -3518,10 +3524,10 @@ options_validate(or_options_t *old_options, or_options_t *options, } } - if (options->AuthoritativeDir && !options->DirPort) + if (options->AuthoritativeDir && !options->DirPort_set) REJECT("Running as authoritative directory, but no DirPort set."); - if (options->AuthoritativeDir && !options->ORPort) + if (options->AuthoritativeDir && !options->ORPort_set) REJECT("Running as authoritative directory, but no ORPort set."); if (options->AuthoritativeDir && options->ClientOnly) @@ -3708,11 +3714,12 @@ options_validate(or_options_t *old_options, or_options_t *options, "PublishServerDescriptor line."); } - if (options->BridgeRelay && options->DirPort) { + if (options->BridgeRelay && options->DirPort_set) { log_warn(LD_CONFIG, "Can't set a DirPort on a bridge relay; disabling " "DirPort"); - config_free_lines(options->DirPort); - options->DirPort = NULL; + config_free_lines(options->DirPort_lines); + options->DirPort_lines = NULL; + options->DirPort_set = 0; } if (options->MinUptimeHidServDirectoryV2 < 0) { @@ -3987,7 +3994,7 @@ options_validate(or_options_t *old_options, or_options_t *options, } } - if (options->ControlPort && !options->HashedControlPassword && + if (options->ControlPort_set && !options->HashedControlPassword && !options->HashedControlSessionPassword && !options->CookieAuthentication) { log_warn(LD_CONFIG, "ControlPort is open, but no authentication method " @@ -4067,7 +4074,7 @@ options_validate(or_options_t *old_options, or_options_t *options, MIN_CONSTRAINED_TCP_BUFFER, MAX_CONSTRAINED_TCP_BUFFER); return -1; } - if (options->DirPort) { + if (options->DirPort_set) { /* Providing cached directory entries while system TCP buffers are scarce * will exacerbate the socket errors. Suggest that this be disabled. */ COMPLAIN("You have requested constrained socket buffers while also " @@ -4226,7 +4233,7 @@ options_validate(or_options_t *old_options, or_options_t *options, } }); - if (options->BridgeRelay == 1 && ! options->ORPort) + if (options->BridgeRelay == 1 && ! options->ORPort_set) REJECT("BridgeRelay is 1, ORPort is not set. This is an invalid " "combination."); @@ -4326,7 +4333,7 @@ options_transition_affects_workers(const or_options_t *old_options, { if (!opt_streq(old_options->DataDirectory, new_options->DataDirectory) || old_options->NumCPUs != new_options->NumCPUs || - !config_lines_eq(old_options->ORPort, new_options->ORPort) || + !config_lines_eq(old_options->ORPort_lines, new_options->ORPort_lines) || old_options->ServerDNSSearchDomains != new_options->ServerDNSSearchDomains || old_options->_SafeLogging != new_options->_SafeLogging || @@ -4356,8 +4363,10 @@ options_transition_affects_descriptor(const or_options_t *old_options, !config_lines_eq(old_options->ExitPolicy,new_options->ExitPolicy) || old_options->ExitPolicyRejectPrivate != new_options->ExitPolicyRejectPrivate || - !config_lines_eq(old_options->ORPort, new_options->ORPort) || - !config_lines_eq(old_options->DirPort, new_options->DirPort) || + !config_lines_eq(old_options->ORPort_lines, + new_options->ORPort_lines) || + !config_lines_eq(old_options->DirPort_lines, + new_options->DirPort_lines) || old_options->ClientOnly != new_options->ClientOnly || old_options->DisableNetwork != new_options->DisableNetwork || old_options->_PublishServerDescriptor != @@ -4864,12 +4873,11 @@ config_register_addressmaps(const or_options_t *options) { smartlist_t *elts; config_line_t *opt; - char *from, *to; + const char *from, *to, *msg; addressmap_clear_configured(); elts = smartlist_new(); for (opt = options->AddressMap; opt; opt = opt->next) { - int from_wildcard = 0, to_wildcard = 0; smartlist_split_string(elts, opt->value, NULL, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2); if (smartlist_len(elts) < 2) { @@ -4887,11 +4895,39 @@ config_register_addressmaps(const or_options_t *options) goto cleanup; } - if (!strcmp(to, "*") || !strcmp(from, "*")) { - log_warn(LD_CONFIG,"MapAddress '%s' is unsupported - can't remap from " - "or to *. Ignoring.",opt->value); + if (addressmap_register_auto(from, to, 0, ADDRMAPSRC_TORRC, &msg) < 0) { + log_warn(LD_CONFIG,"MapAddress '%s' failed: %s. Ignoring.", opt->value, + msg); goto cleanup; } + + if (smartlist_len(elts) > 2) + log_warn(LD_CONFIG,"Ignoring extra arguments to MapAddress."); + + cleanup: + SMARTLIST_FOREACH(elts, char*, cp, tor_free(cp)); + smartlist_clear(elts); + } + smartlist_free(elts); +} + +/** As addressmap_register(), but detect the wildcarded status of "from" and + * "to", and do not steal a reference to <b>to</b>. */ +/* XXXX024 move to connection_edge.c */ +int +addressmap_register_auto(const char *from, const char *to, + time_t expires, + addressmap_entry_source_t addrmap_source, + const char **msg) +{ + int from_wildcard = 0, to_wildcard = 0; + + *msg = "whoops, forgot the error message"; + if (1) { + if (!strcmp(to, "*") || !strcmp(from, "*")) { + *msg = "can't remap from or to *"; + return -1; + } /* Detect asterisks in expressions of type: '*.example.com' */ if (!strncmp(from,"*.",2)) { from += 2; @@ -4903,30 +4939,20 @@ config_register_addressmaps(const or_options_t *options) } if (to_wildcard && !from_wildcard) { - log_warn(LD_CONFIG, - "Skipping invalid argument '%s' to MapAddress: " - "can only use wildcard (i.e. '*.') if 'from' address " - "uses wildcard also", opt->value); - goto cleanup; + *msg = "can only use wildcard (i.e. '*.') if 'from' address " + "uses wildcard also"; + return -1; } if (address_is_invalid_destination(to, 1)) { - log_warn(LD_CONFIG, - "Skipping invalid argument '%s' to MapAddress", opt->value); - goto cleanup; + *msg = "destination is invalid"; + return -1; } - addressmap_register(from, tor_strdup(to), 0, ADDRMAPSRC_TORRC, + addressmap_register(from, tor_strdup(to), expires, addrmap_source, from_wildcard, to_wildcard); - - if (smartlist_len(elts) > 2) - log_warn(LD_CONFIG,"Ignoring extra arguments to MapAddress."); - - cleanup: - SMARTLIST_FOREACH(elts, char*, cp, tor_free(cp)); - smartlist_clear(elts); } - smartlist_free(elts); + return 0; } /** @@ -5643,13 +5669,13 @@ warn_nonlocal_controller_ports(smartlist_t *ports, unsigned forbid) */ static int parse_port_config(smartlist_t *out, - const config_line_t *ports, - const config_line_t *listenaddrs, - const char *portname, - int listener_type, - const char *defaultaddr, - int defaultport, - unsigned flags) + const config_line_t *ports, + const config_line_t *listenaddrs, + const char *portname, + int listener_type, + const char *defaultaddr, + int defaultport, + unsigned flags) { smartlist_t *elts; int retval = -1; @@ -5660,6 +5686,7 @@ parse_port_config(smartlist_t *out, const unsigned forbid_nonlocal = flags & CL_PORT_FORBID_NONLOCAL; const unsigned allow_spurious_listenaddr = flags & CL_PORT_ALLOW_EXTRA_LISTENADDR; + int got_zero_port=0, got_nonzero_port=0; /* FooListenAddress is deprecated; let's make it work like it used to work, * though. */ @@ -5687,7 +5714,7 @@ parse_port_config(smartlist_t *out, if (mainport == 0) { if (allow_spurious_listenaddr) - return 1; + return 1; /*DOCDOC*/ log_warn(LD_CONFIG, "%sPort must be defined if %sListenAddress is used", portname, portname); return -1; @@ -5912,6 +5939,11 @@ parse_port_config(smartlist_t *out, } SMARTLIST_FOREACH_END(elt); } + if (port) + got_nonzero_port = 1; + else + got_zero_port = 1; + if (out && port) { port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t)); tor_addr_copy(&cfg->addr, &addr); @@ -5938,6 +5970,13 @@ parse_port_config(smartlist_t *out, warn_nonlocal_client_ports(out, portname); } + if (got_zero_port && got_nonzero_port) { + log_warn(LD_CONFIG, "You specified a nonzero %sPort along with '%sPort 0' " + "in the same configuration. Did you mean to disable %sPort or " + "not?", portname, portname, portname); + goto err; + } + retval = 0; err: SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp)); @@ -5968,16 +6007,34 @@ parse_unix_socket_config(smartlist_t *out, const config_line_t *cfg, return 0; } +/** Return the number of ports which are actually going to listen with type + * <b>listenertype</b>. Do not count no_listen ports. Do not count unix + * sockets. */ +static int +count_real_listeners(const smartlist_t *ports, int listenertype) +{ + int n = 0; + SMARTLIST_FOREACH_BEGIN(ports, port_cfg_t *, port) { + if (port->no_listen || port->is_unix_addr) + continue; + if (port->type != listenertype) + continue; + ++n; + } SMARTLIST_FOREACH_END(port); + return n; +} + /** Parse all client port types (Socks, DNS, Trans, NATD) from - * <b>options</b>. On success, set *<b>n_ports_out</b> to the number of - * ports that are listed and return 0. On failure, set *<b>msg</b> to a + * <b>options</b>. On success, set *<b>n_ports_out</b> to the number + * of ports that are listed, update the *Port_set values in + * <b>options</b>, and return 0. On failure, set *<b>msg</b> to a * description of the problem and return -1. * * If <b>validate_only</b> is false, set configured_client_ports to the * new list of ports parsed from <b>options</b>. **/ static int -parse_ports(const or_options_t *options, int validate_only, +parse_ports(or_options_t *options, int validate_only, char **msg, int *n_ports_out) { smartlist_t *ports; @@ -5988,7 +6045,7 @@ parse_ports(const or_options_t *options, int validate_only, *n_ports_out = 0; if (parse_port_config(ports, - options->SocksPort, options->SocksListenAddress, + options->SocksPort_lines, options->SocksListenAddress, "Socks", CONN_TYPE_AP_LISTENER, "127.0.0.1", 9050, CL_PORT_WARN_NONLOCAL|CL_PORT_ALLOW_EXTRA_LISTENADDR) < 0) { @@ -5996,26 +6053,26 @@ parse_ports(const or_options_t *options, int validate_only, goto err; } if (parse_port_config(ports, - options->DNSPort, options->DNSListenAddress, - "DNS", CONN_TYPE_AP_DNS_LISTENER, - "127.0.0.1", 0, - CL_PORT_WARN_NONLOCAL) < 0) { + options->DNSPort_lines, options->DNSListenAddress, + "DNS", CONN_TYPE_AP_DNS_LISTENER, + "127.0.0.1", 0, + CL_PORT_WARN_NONLOCAL) < 0) { *msg = tor_strdup("Invalid DNSPort/DNSListenAddress configuration"); goto err; } if (parse_port_config(ports, - options->TransPort, options->TransListenAddress, - "Trans", CONN_TYPE_AP_TRANS_LISTENER, - "127.0.0.1", 0, - CL_PORT_WARN_NONLOCAL) < 0) { + options->TransPort_lines, options->TransListenAddress, + "Trans", CONN_TYPE_AP_TRANS_LISTENER, + "127.0.0.1", 0, + CL_PORT_WARN_NONLOCAL) < 0) { *msg = tor_strdup("Invalid TransPort/TransListenAddress configuration"); goto err; } if (parse_port_config(ports, - options->NATDPort, options->NATDListenAddress, - "NATD", CONN_TYPE_AP_NATD_LISTENER, - "127.0.0.1", 0, - CL_PORT_WARN_NONLOCAL) < 0) { + options->NATDPort_lines, options->NATDListenAddress, + "NATD", CONN_TYPE_AP_NATD_LISTENER, + "127.0.0.1", 0, + CL_PORT_WARN_NONLOCAL) < 0) { *msg = tor_strdup("Invalid NatdPort/NatdListenAddress configuration"); goto err; } @@ -6028,7 +6085,8 @@ parse_ports(const or_options_t *options, int validate_only, control_port_flags |= CL_PORT_FORBID_NONLOCAL; if (parse_port_config(ports, - options->ControlPort, options->ControlListenAddress, + options->ControlPort_lines, + options->ControlListenAddress, "Control", CONN_TYPE_CONTROL_LISTENER, "127.0.0.1", 0, control_port_flags) < 0) { @@ -6045,7 +6103,7 @@ parse_ports(const or_options_t *options, int validate_only, } if (! options->ClientOnly) { if (parse_port_config(ports, - options->ORPort, options->ORListenAddress, + options->ORPort_lines, options->ORListenAddress, "OR", CONN_TYPE_OR_LISTENER, "0.0.0.0", 0, CL_PORT_SERVER_OPTIONS) < 0) { @@ -6053,7 +6111,7 @@ parse_ports(const or_options_t *options, int validate_only, goto err; } if (parse_port_config(ports, - options->DirPort, options->DirListenAddress, + options->DirPort_lines, options->DirListenAddress, "Dir", CONN_TYPE_DIR_LISTENER, "0.0.0.0", 0, CL_PORT_SERVER_OPTIONS) < 0) { @@ -6069,6 +6127,25 @@ parse_ports(const or_options_t *options, int validate_only, *n_ports_out = smartlist_len(ports); + retval = 0; + + /* Update the *Port_set options. The !! here is to force a boolean out of + an integer. */ + options->ORPort_set = + !! count_real_listeners(ports, CONN_TYPE_OR_LISTENER); + options->SocksPort_set = + !! count_real_listeners(ports, CONN_TYPE_AP_LISTENER); + options->TransPort_set = + !! count_real_listeners(ports, CONN_TYPE_AP_TRANS_LISTENER); + options->NATDPort_set = + !! count_real_listeners(ports, CONN_TYPE_AP_NATD_LISTENER); + options->ControlPort_set = + !! count_real_listeners(ports, CONN_TYPE_CONTROL_LISTENER); + options->DirPort_set = + !! count_real_listeners(ports, CONN_TYPE_DIR_LISTENER); + options->DNSPort_set = + !! count_real_listeners(ports, CONN_TYPE_AP_DNS_LISTENER); + if (!validate_only) { if (configured_ports) { SMARTLIST_FOREACH(configured_ports, @@ -6079,7 +6156,6 @@ parse_ports(const or_options_t *options, int validate_only, ports = NULL; /* prevent free below. */ } - retval = 0; err: if (ports) { SMARTLIST_FOREACH(ports, port_cfg_t *, p, port_cfg_free(p)); @@ -6620,7 +6696,7 @@ init_libevent(const or_options_t *options) suppress_libevent_log_msg(NULL); tor_check_libevent_version(tor_libevent_get_method(), - get_options()->ORPort != NULL, + server_mode(get_options()), &badness); if (badness) { const char *v = tor_libevent_get_version_str(); diff --git a/src/or/config.h b/src/or/config.h index ce7e319746..dd76edcf1d 100644 --- a/src/or/config.h +++ b/src/or/config.h @@ -96,6 +96,11 @@ or_options_t *options_new(void); #endif void config_register_addressmaps(const or_options_t *options); +/* XXXX024 move to connection_edge.h */ +int addressmap_register_auto(const char *from, const char *to, + time_t expires, + addressmap_entry_source_t addrmap_source, + const char **msg); #endif diff --git a/src/or/control.c b/src/or/control.c index ce571f99f3..913d18a7fc 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -1366,9 +1366,18 @@ handle_control_mapaddress(control_connection_t *conn, uint32_t len, smartlist_add_asprintf(reply, "250-%s=%s", address, to); } } else { - addressmap_register(from, tor_strdup(to), 1, - ADDRMAPSRC_CONTROLLER, 0, 0); - smartlist_add_asprintf(reply, "250-%s", line); + const char *msg; + if (addressmap_register_auto(from, to, 1, + ADDRMAPSRC_CONTROLLER, &msg) < 0) { + smartlist_add_asprintf(reply, + "512-syntax error: invalid address mapping " + " '%s': %s", line, msg); + log_warn(LD_CONTROL, + "Skipping invalid argument '%s' in MapAddress msg: %s", + line, msg); + } else { + smartlist_add_asprintf(reply, "250-%s", line); + } } } else { smartlist_add_asprintf(reply, "512-syntax error: mapping '%s' is " diff --git a/src/or/directory.c b/src/or/directory.c index f58aab256b..40344e6b05 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -3732,7 +3732,7 @@ download_status_reset(download_status_t *dls) const int *schedule; size_t schedule_len; - find_dl_schedule_and_len(dls, get_options()->DirPort != NULL, + find_dl_schedule_and_len(dls, get_options()->DirPort_set, &schedule, &schedule_len); dls->n_download_failures = 0; diff --git a/src/or/directory.h b/src/or/directory.h index 584fe84311..1ca1c5a6e0 100644 --- a/src/or/directory.h +++ b/src/or/directory.h @@ -80,7 +80,7 @@ time_t download_status_increment_failure(download_status_t *dls, * the optional status code <b>sc</b>. */ #define download_status_failed(dls, sc) \ download_status_increment_failure((dls), (sc), NULL, \ - get_options()->DirPort!=NULL, time(NULL)) + get_options()->DirPort_set, time(NULL)) void download_status_reset(download_status_t *dls); static int download_status_is_ready(download_status_t *dls, time_t now, diff --git a/src/or/dirserv.c b/src/or/dirserv.c index e21f5113f2..f1c9c6232d 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -1214,7 +1214,7 @@ directory_fetches_from_authorities(const or_options_t *options) return 1; /* we don't know our IP address; ask an authority. */ refuseunknown = ! router_my_exit_policy_is_reject_star() && should_refuse_unknown_exits(options); - if (options->DirPort == NULL && !refuseunknown) + if (!options->DirPort_set && !refuseunknown) return 0; if (!server_mode(options) || !advertised_server_mode()) return 0; @@ -1250,7 +1250,7 @@ directory_fetches_dir_info_later(const or_options_t *options) int directory_caches_v2_dir_info(const or_options_t *options) { - return options->DirPort != NULL; + return options->DirPort_set; } /** Return true iff we want to fetch and keep certificates for authorities @@ -1259,7 +1259,7 @@ directory_caches_v2_dir_info(const or_options_t *options) int directory_caches_unknown_auth_certs(const or_options_t *options) { - return options->DirPort || options->BridgeRelay; + return options->DirPort_set || options->BridgeRelay; } /** Return 1 if we want to keep descriptors, networkstatuses, etc around @@ -1268,7 +1268,7 @@ directory_caches_unknown_auth_certs(const or_options_t *options) int directory_caches_dir_info(const or_options_t *options) { - if (options->BridgeRelay || options->DirPort) + if (options->BridgeRelay || options->DirPort_set) return 1; if (!server_mode(options) || !advertised_server_mode()) return 0; @@ -1284,7 +1284,7 @@ directory_caches_dir_info(const or_options_t *options) int directory_permits_begindir_requests(const or_options_t *options) { - return options->BridgeRelay != 0 || options->DirPort != NULL; + return options->BridgeRelay != 0 || options->DirPort_set; } /** Return 1 if we want to allow controllers to ask us directory @@ -1293,7 +1293,7 @@ directory_permits_begindir_requests(const or_options_t *options) int directory_permits_controller_requests(const or_options_t *options) { - return options->DirPort != NULL; + return options->DirPort_set; } /** Return 1 if we have no need to fetch new descriptors. This generally diff --git a/src/or/dirvote.c b/src/or/dirvote.c index 79958739a5..b3de90b5c0 100644 --- a/src/or/dirvote.c +++ b/src/or/dirvote.c @@ -54,7 +54,7 @@ static int dirvote_publish_consensus(void); static char *make_consensus_method_list(int low, int high, const char *sep); /** The highest consensus method that we currently support. */ -#define MAX_SUPPORTED_CONSENSUS_METHOD 12 +#define MAX_SUPPORTED_CONSENSUS_METHOD 13 /** Lowest consensus method that contains a 'directory-footer' marker */ #define MIN_METHOD_FOR_FOOTER 9 @@ -72,6 +72,10 @@ static char *make_consensus_method_list(int low, int high, const char *sep); * for a param. */ #define MIN_METHOD_FOR_MAJORITY_PARAMS 12 +/** Lowest consensus method where microdesc consensuses omit any entry + * with no microdesc. */ +#define MIN_METHOD_FOR_MANDATORY_MICRODESC 13 + /* ===== * Voting * =====*/ @@ -1752,6 +1756,7 @@ networkstatus_compute_consensus(smartlist_t *votes, rs = compute_routerstatus_consensus(matching_descs, consensus_method, microdesc_digest); /* Copy bits of that into rs_out. */ + memset(&rs_out, 0, sizeof(rs_out)); tor_assert(fast_memeq(lowest_id, rs->status.identity_digest,DIGEST_LEN)); memcpy(rs_out.identity_digest, lowest_id, DIGEST_LEN); memcpy(rs_out.descriptor_digest, rs->status.descriptor_digest, @@ -1935,6 +1940,13 @@ networkstatus_compute_consensus(smartlist_t *votes, } } + if (flavor == FLAV_MICRODESC && + consensus_method >= MIN_METHOD_FOR_MANDATORY_MICRODESC && + tor_digest256_is_zero(microdesc_digest)) { + /* With no microdescriptor digest, we omit the entry entirely. */ + continue; + } + { char buf[4096]; /* Okay!! Now we can write the descriptor... */ @@ -3502,9 +3514,9 @@ dirvote_create_microdescriptor(const routerinfo_t *ri) { microdesc_t *result = NULL; char *key = NULL, *summary = NULL, *family = NULL; - char buf[1024]; size_t keylen; - char *out = buf, *end = buf+sizeof(buf); + smartlist_t *chunks = smartlist_new(); + char *output = NULL; if (crypto_pk_write_public_key_to_string(ri->onion_pkey, &key, &keylen)<0) goto done; @@ -3512,23 +3524,19 @@ dirvote_create_microdescriptor(const routerinfo_t *ri) if (ri->declared_family) family = smartlist_join_strings(ri->declared_family, " ", 0, NULL); - if (tor_snprintf(out, end-out, "onion-key\n%s", key)<0) - goto done; - out += strlen(out); - if (family) { - if (tor_snprintf(out, end-out, "family %s\n", family)<0) - goto done; - out += strlen(out); - } - if (summary && strcmp(summary, "reject 1-65535")) { - if (tor_snprintf(out, end-out, "p %s\n", summary)<0) - goto done; - out += strlen(out); - } - *out = '\0'; /* Make sure it's nul-terminated. This should be a no-op */ + smartlist_add_asprintf(chunks, "onion-key\n%s", key); + + if (family) + smartlist_add_asprintf(chunks, "family %s\n", family); + + if (summary && strcmp(summary, "reject 1-65535")) + smartlist_add_asprintf(chunks, "p %s\n", summary); + + output = smartlist_join_strings(chunks, "", 0, NULL); { - smartlist_t *lst = microdescs_parse_from_string(buf, out, 0, 1); + smartlist_t *lst = microdescs_parse_from_string(output, + output+strlen(output), 0, 1); if (smartlist_len(lst) != 1) { log_warn(LD_DIR, "We generated a microdescriptor we couldn't parse."); SMARTLIST_FOREACH(lst, microdesc_t *, md, microdesc_free(md)); @@ -3540,9 +3548,14 @@ dirvote_create_microdescriptor(const routerinfo_t *ri) } done: + tor_free(output); tor_free(key); tor_free(summary); tor_free(family); + if (chunks) { + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_free(chunks); + } return result; } diff --git a/src/or/dns.c b/src/or/dns.c index 3e88fad68c..78893bfbed 100644 --- a/src/or/dns.c +++ b/src/or/dns.c @@ -450,16 +450,17 @@ purge_expired_resolves(time_t now) if (resolve->pending_connections) { log_debug(LD_EXIT, "Closing pending connections on timed-out DNS resolve!"); - tor_fragile_assert(); while (resolve->pending_connections) { pend = resolve->pending_connections; resolve->pending_connections = pend->next; /* Connections should only be pending if they have no socket. */ tor_assert(!SOCKET_OK(pend->conn->_base.s)); pendconn = pend->conn; - connection_edge_end(pendconn, END_STREAM_REASON_TIMEOUT); - circuit_detach_stream(circuit_get_by_edge_conn(pendconn), pendconn); - connection_free(TO_CONN(pendconn)); + if (!pendconn->_base.marked_for_close) { + connection_edge_end(pendconn, END_STREAM_REASON_TIMEOUT); + circuit_detach_stream(circuit_get_by_edge_conn(pendconn), pendconn); + connection_free(TO_CONN(pendconn)); + } tor_free(pend); } } @@ -1091,6 +1092,13 @@ dns_found_answer(const char *address, uint8_t is_reverse, uint32_t addr, pendconn = pend->conn; /* don't pass complex things to the connection_mark_for_close macro */ assert_connection_ok(TO_CONN(pendconn),time(NULL)); + if (pendconn->_base.marked_for_close) { + /* prevent double-remove. */ + pendconn->_base.state = EXIT_CONN_STATE_RESOLVEFAILED; + resolve->pending_connections = pend->next; + tor_free(pend); + continue; + } tor_addr_from_ipv4h(&pendconn->_base.addr, addr); pendconn->address_ttl = ttl; diff --git a/src/or/microdesc.c b/src/or/microdesc.c index 9395a9a051..b4d22c1c62 100644 --- a/src/or/microdesc.c +++ b/src/or/microdesc.c @@ -643,13 +643,8 @@ microdesc_list_missing_digest256(networkstatus_t *ns, microdesc_cache_t *cache, continue; if (skip && digestmap_get(skip, rs->descriptor_digest)) continue; - if (tor_mem_is_zero(rs->descriptor_digest, DIGEST256_LEN)) { - log_info(LD_BUG, "Found an entry in networkstatus with no " - "microdescriptor digest. (Router %s=%s at %s:%d.)", - rs->nickname, hex_str(rs->identity_digest, DIGEST_LEN), - fmt_addr32(rs->addr), rs->or_port); + if (tor_mem_is_zero(rs->descriptor_digest, DIGEST256_LEN)) continue; - } /* XXXX Also skip if we're a noncache and wouldn't use this router. * XXXX NM Microdesc */ @@ -658,7 +653,7 @@ microdesc_list_missing_digest256(networkstatus_t *ns, microdesc_cache_t *cache, return result; } -/** Launch download requests for mircodescriptors as appropriate. +/** Launch download requests for microdescriptors as appropriate. * * Specifically, we should launch download requests if we are configured to * download mirodescriptors, and there are some microdescriptors listed the diff --git a/src/or/or.h b/src/or/or.h index 3a53e5ed86..9074083a04 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2596,6 +2596,23 @@ typedef struct circuit_t { * circuit. */ #define MAX_RELAY_EARLY_CELLS_PER_CIRCUIT 8 +/** + * Describes the circuit building process in simplified terms based + * on the path bias accounting state for a circuit. Created to prevent + * overcounting due to unknown cases of circuit reuse. See Bug #6475. + */ +typedef enum { + /** This circuit is "new". It has not yet completed a first hop + * or been counted by the path bias code. */ + PATH_STATE_NEW_CIRC = 0, + /** This circuit has completed a first hop, and has been counted by + * the path bias logic. */ + PATH_STATE_DID_FIRST_HOP = 1, + /** This circuit has been completely built, and has been counted as + * successful by the path bias logic. */ + PATH_STATE_SUCCEEDED = 2, +} path_state_t; + /** An origin_circuit_t holds data necessary to build and use a circuit. */ typedef struct origin_circuit_t { @@ -2629,6 +2646,10 @@ typedef struct origin_circuit_t { * cannibalized circuits. */ unsigned int has_opened : 1; + /** Kludge to help us prevent the warn in bug #6475 and eventually + * debug why we are not seeing first hops in some cases. */ + path_state_t path_state : 2; + /** Set iff this is a hidden-service circuit which has timed out * according to our current circuit-build timeout, but which has * been kept around because it might still succeed in connecting to @@ -3008,23 +3029,46 @@ typedef struct { config_line_t *RecommendedVersions; config_line_t *RecommendedClientVersions; config_line_t *RecommendedServerVersions; - /** Whether dirservers refuse router descriptors with private IPs. */ + /** Whether dirservers allow router descriptors with private IPs. */ int DirAllowPrivateAddresses; + /** Whether routers accept EXTEND cells to routers with private IPs. */ + int ExtendAllowPrivateAddresses; char *User; /**< Name of user to run Tor as. */ char *Group; /**< Name of group to run Tor as. */ - config_line_t *ORPort; /**< Ports to listen on for OR connections. */ - config_line_t *SocksPort; /**< Ports to listen on for SOCKS connections. */ + config_line_t *ORPort_lines; /**< Ports to listen on for OR connections. */ + /** Ports to listen on for SOCKS connections. */ + config_line_t *SocksPort_lines; /** Ports to listen on for transparent pf/netfilter connections. */ - config_line_t *TransPort; - config_line_t *NATDPort; /**< Ports to listen on for transparent natd + config_line_t *TransPort_lines; + config_line_t *NATDPort_lines; /**< Ports to listen on for transparent natd * connections. */ - config_line_t *ControlPort; /**< Port to listen on for control + config_line_t *ControlPort_lines; /**< Ports to listen on for control * connections. */ config_line_t *ControlSocket; /**< List of Unix Domain Sockets to listen on * for control connections. */ + int ControlSocketsGroupWritable; /**< Boolean: Are control sockets g+rw? */ - config_line_t *DirPort; /**< Port to listen on for directory connections. */ - config_line_t *DNSPort; /**< Port to listen on for DNS requests. */ + /** Ports to listen on for directory connections. */ + config_line_t *DirPort_lines; + config_line_t *DNSPort_lines; /**< Ports to listen on for DNS requests. */ + + /** @name port booleans + * + * Derived booleans: True iff there is a non-listener port on an AF_INET or + * AF_INET6 address of the given type configured in one of the _lines + * options above. + * + * @{ + */ + unsigned int ORPort_set : 1; + unsigned int SocksPort_set : 1; + unsigned int TransPort_set : 1; + unsigned int NATDPort_set : 1; + unsigned int ControlPort_set : 1; + unsigned int DirPort_set : 1; + unsigned int DNSPort_set : 1; + /**@}*/ + int AssumeReachable; /**< Whether to publish our descriptor regardless. */ int AuthoritativeDir; /**< Boolean: is this an authoritative directory? */ int V1AuthoritativeDir; /**< Boolean: is this an authoritative directory diff --git a/src/or/policies.c b/src/or/policies.c index 3018803bc4..6e984211ba 100644 --- a/src/or/policies.c +++ b/src/or/policies.c @@ -712,7 +712,11 @@ compare_tor_addr_to_addr_policy(const tor_addr_t *addr, uint16_t port, /* no policy? accept all. */ return ADDR_POLICY_ACCEPTED; } else if (addr == NULL || tor_addr_is_null(addr)) { - tor_assert(port != 0); + if (port == 0) { + log_info(LD_BUG, "Rejecting null address with 0 port (family %d)", + addr ? tor_addr_family(addr) : -1); + return ADDR_POLICY_REJECTED; + } return compare_unknown_tor_addr_to_addr_policy(port, policy); } else if (port == 0) { return compare_known_tor_addr_to_addr_policy_noport(addr, policy); diff --git a/src/or/relay.c b/src/or/relay.c index 3e418ea13f..3d261c2650 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -1265,11 +1265,25 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, case RELAY_COMMAND_SENDME: if (!rh.stream_id) { if (layer_hint) { + if (layer_hint->package_window + CIRCWINDOW_INCREMENT > + CIRCWINDOW_START_MAX) { + log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, + "Bug/attack: unexpected sendme cell from exit relay. " + "Closing circ."); + return -END_CIRC_REASON_TORPROTOCOL; + } layer_hint->package_window += CIRCWINDOW_INCREMENT; log_debug(LD_APP,"circ-level sendme at origin, packagewindow %d.", layer_hint->package_window); circuit_resume_edge_reading(circ, layer_hint); } else { + if (circ->package_window + CIRCWINDOW_INCREMENT > + CIRCWINDOW_START_MAX) { + log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, + "Bug/attack: unexpected sendme cell from client. " + "Closing circ."); + return -END_CIRC_REASON_TORPROTOCOL; + } circ->package_window += CIRCWINDOW_INCREMENT; log_debug(LD_APP, "circ-level sendme at non-origin, packagewindow %d.", diff --git a/src/or/router.c b/src/or/router.c index 352c456f1f..38f1cdd495 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -797,7 +797,7 @@ int check_whether_dirport_reachable(void) { const or_options_t *options = get_options(); - return !options->DirPort || + return !options->DirPort_set || options->AssumeReachable || net_is_disabled() || can_reach_dir_port; @@ -1115,7 +1115,8 @@ int server_mode(const or_options_t *options) { if (options->ClientOnly) return 0; - return (options->ORPort || options->ORListenAddress); + /* XXXX024 I believe we can kill off ORListenAddress here.*/ + return (options->ORPort_set || options->ORListenAddress); } /** Return true iff we are trying to be a non-bridge server. diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 4979b933ad..3c39e362df 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -5160,6 +5160,8 @@ router_differences_are_cosmetic(const routerinfo_t *r1, const routerinfo_t *r2) if (strcasecmp(r1->address, r2->address) || strcasecmp(r1->nickname, r2->nickname) || r1->or_port != r2->or_port || + !tor_addr_eq(&r1->ipv6_addr, &r2->ipv6_addr) || + r1->ipv6_orport != r2->ipv6_orport || r1->dir_port != r2->dir_port || r1->purpose != r2->purpose || crypto_pk_cmp_keys(r1->onion_pkey, r2->onion_pkey) || diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 970353a43c..60a2eae75f 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -962,7 +962,7 @@ router_parse_runningrouters(const char *str) /* Now that we know the signature is okay, and we have a * publication time, cache the list. */ - if (get_options()->DirPort && !authdir_mode_v1(get_options())) + if (get_options()->DirPort_set && !authdir_mode_v1(get_options())) dirserv_set_cached_directory(str, published_on, 1); r = 0; @@ -2201,6 +2201,11 @@ routerstatus_parse_entry_from_string(memarea_t *area, escaped(tok->args[0])); goto err; } + } else { + log_info(LD_BUG, "Found an entry in networkstatus with no " + "microdescriptor digest. (Router %s=%s at %s:%d.)", + rs->nickname, hex_str(rs->identity_digest, DIGEST_LEN), + fmt_addr32(rs->addr), rs->or_port); } } |