diff options
Diffstat (limited to 'src')
30 files changed, 306 insertions, 79 deletions
diff --git a/src/app/config/config.c b/src/app/config/config.c index 76df7ec67e..45a23d67d5 100644 --- a/src/app/config/config.c +++ b/src/app/config/config.c @@ -3337,12 +3337,6 @@ options_validate(or_options_t *old_options, or_options_t *options, * Always use the value of UseEntryGuards, not UseEntryGuards_option. */ options->UseEntryGuards = options->UseEntryGuards_option; - if (warn_about_relative_paths(options) && options->RunAsDaemon) { - REJECT("You have specified at least one relative path (see above) " - "with the RunAsDaemon option. RunAsDaemon is not compatible " - "with relative paths."); - } - if (server_mode(options) && (!strcmpstart(uname, "Windows 95") || !strcmpstart(uname, "Windows 98") || @@ -3359,6 +3353,14 @@ options_validate(or_options_t *old_options, or_options_t *options, if (validate_data_directories(options)<0) REJECT("Invalid DataDirectory"); + /* need to check for relative paths after we populate + * options->DataDirectory (just above). */ + if (warn_about_relative_paths(options) && options->RunAsDaemon) { + REJECT("You have specified at least one relative path (see above) " + "with the RunAsDaemon option. RunAsDaemon is not compatible " + "with relative paths."); + } + if (options->Nickname == NULL) { if (server_mode(options)) { options->Nickname = tor_strdup(UNNAMED_ROUTER_NICKNAME); diff --git a/src/app/main/main.c b/src/app/main/main.c index 4dedae9c0c..b8dcb852d2 100644 --- a/src/app/main/main.c +++ b/src/app/main/main.c @@ -34,6 +34,7 @@ #include "core/or/relay.h" #include "core/or/scheduler.h" #include "core/or/status.h" +#include "core/or/versions.h" #include "feature/api/tor_api.h" #include "feature/api/tor_api_internal.h" #include "feature/client/addressmap.h" @@ -767,6 +768,7 @@ tor_free_all(int postfork) dos_free_all(); circuitmux_ewma_free_all(); accounting_free_all(); + protover_summary_cache_free_all(); if (!postfork) { config_free_all(); diff --git a/src/core/mainloop/mainloop.c b/src/core/mainloop/mainloop.c index a24b343756..a9f1429787 100644 --- a/src/core/mainloop/mainloop.c +++ b/src/core/mainloop/mainloop.c @@ -1598,15 +1598,17 @@ rescan_periodic_events(const or_options_t *options) for (int i = 0; periodic_events[i].name; ++i) { periodic_event_item_t *item = &periodic_events[i]; + int enable = !!(item->roles & roles); + /* Handle the event flags. */ if (net_is_disabled() && (item->flags & PERIODIC_EVENT_FLAG_NEED_NET)) { - continue; + enable = 0; } /* Enable the event if needed. It is safe to enable an event that was * already enabled. Same goes for disabling it. */ - if (item->roles & roles) { + if (enable) { log_debug(LD_GENERAL, "Launching periodic event %s", item->name); periodic_event_enable(item); } else { diff --git a/src/core/or/circuitbuild.c b/src/core/or/circuitbuild.c index a69457571e..4f9f09bc8f 100644 --- a/src/core/or/circuitbuild.c +++ b/src/core/or/circuitbuild.c @@ -1658,22 +1658,25 @@ route_len_for_purpose(uint8_t purpose, extend_info_t *exit_ei) STATIC int new_route_len(uint8_t purpose, extend_info_t *exit_ei, smartlist_t *nodes) { - int num_acceptable_routers; int routelen; tor_assert(nodes); routelen = route_len_for_purpose(purpose, exit_ei); - num_acceptable_routers = count_acceptable_nodes(nodes); + int num_acceptable_direct = count_acceptable_nodes(nodes, 1); + int num_acceptable_indirect = count_acceptable_nodes(nodes, 0); - log_debug(LD_CIRC,"Chosen route length %d (%d/%d routers suitable).", - routelen, num_acceptable_routers, smartlist_len(nodes)); + log_debug(LD_CIRC,"Chosen route length %d (%d direct and %d indirect " + "routers suitable).", routelen, num_acceptable_direct, + num_acceptable_indirect); - if (num_acceptable_routers < routelen) { + if (num_acceptable_direct < 1 || num_acceptable_indirect < routelen - 1) { log_info(LD_CIRC, - "Not enough acceptable routers (%d/%d). Discarding this circuit.", - num_acceptable_routers, routelen); + "Not enough acceptable routers (%d/%d direct and %d/%d " + "indirect routers suitable). Discarding this circuit.", + num_acceptable_direct, routelen, + num_acceptable_indirect, routelen); return -1; } @@ -2315,7 +2318,7 @@ circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *exit_ei) * particular router. See bug #25885.) */ MOCK_IMPL(STATIC int, -count_acceptable_nodes, (smartlist_t *nodes)) +count_acceptable_nodes, (smartlist_t *nodes, int direct)) { int num=0; @@ -2329,7 +2332,7 @@ count_acceptable_nodes, (smartlist_t *nodes)) if (! node->is_valid) // log_debug(LD_CIRC,"Nope, the directory says %d is not valid.",i); continue; - if (! node_has_any_descriptor(node)) + if (! node_has_preferred_descriptor(node, direct)) continue; /* The node has a descriptor, so we can just check the ntor key directly */ if (!node_has_curve25519_onion_key(node)) diff --git a/src/core/or/circuitbuild.h b/src/core/or/circuitbuild.h index cee71b297b..93f903f060 100644 --- a/src/core/or/circuitbuild.h +++ b/src/core/or/circuitbuild.h @@ -84,7 +84,8 @@ void circuit_upgrade_circuits_from_guard_wait(void); STATIC circid_t get_unique_circ_id_by_chan(channel_t *chan); STATIC int new_route_len(uint8_t purpose, extend_info_t *exit_ei, smartlist_t *nodes); -MOCK_DECL(STATIC int, count_acceptable_nodes, (smartlist_t *nodes)); +MOCK_DECL(STATIC int, count_acceptable_nodes, (smartlist_t *nodes, + int direct)); STATIC int onion_extend_cpath(origin_circuit_t *circ); diff --git a/src/core/or/versions.c b/src/core/or/versions.c index 06274996a7..6f8eea7a67 100644 --- a/src/core/or/versions.c +++ b/src/core/or/versions.c @@ -377,6 +377,62 @@ sort_version_list(smartlist_t *versions, int remove_duplicates) smartlist_uniq(versions, compare_tor_version_str_ptr_, tor_free_); } +/** If there are more than this many entries, we're probably under + * some kind of weird DoS. */ +static const int MAX_PROTOVER_SUMMARY_MAP_LEN = 1024; + +/** + * Map from protover string to protover_summary_flags_t. + */ +static strmap_t *protover_summary_map = NULL; + +/** + * Helper. Given a non-NULL protover string <b>protocols</b>, set <b>out</b> + * to its summary, and memoize the result in <b>protover_summary_map</b>. + */ +static void +memoize_protover_summary(protover_summary_flags_t *out, + const char *protocols) +{ + if (!protover_summary_map) + protover_summary_map = strmap_new(); + + if (strmap_size(protover_summary_map) >= MAX_PROTOVER_SUMMARY_MAP_LEN) { + protover_summary_cache_free_all(); + } + + const protover_summary_flags_t *cached = + strmap_get(protover_summary_map, protocols); + + if (cached != NULL) { + /* We found a cached entry; no need to parse this one. */ + memcpy(out, cached, sizeof(protover_summary_flags_t)); + tor_assert(out->protocols_known); + return; + } + + memset(out, 0, sizeof(*out)); + out->protocols_known = 1; + out->supports_extend2_cells = + protocol_list_supports_protocol(protocols, PRT_RELAY, 2); + out->supports_ed25519_link_handshake_compat = + protocol_list_supports_protocol(protocols, PRT_LINKAUTH, 3); + out->supports_ed25519_link_handshake_any = + protocol_list_supports_protocol_or_later(protocols, PRT_LINKAUTH, 3); + out->supports_ed25519_hs_intro = + protocol_list_supports_protocol(protocols, PRT_HSINTRO, 4); + out->supports_v3_hsdir = + protocol_list_supports_protocol(protocols, PRT_HSDIR, + PROTOVER_HSDIR_V3); + out->supports_v3_rendezvous_point = + protocol_list_supports_protocol(protocols, PRT_HSREND, + PROTOVER_HS_RENDEZVOUS_POINT_V3); + + protover_summary_flags_t *new_cached = tor_memdup(out, sizeof(*out)); + cached = strmap_set(protover_summary_map, protocols, new_cached); + tor_assert(!cached); +} + /** Summarize the protocols listed in <b>protocols</b> into <b>out</b>, * falling back or correcting them based on <b>version</b> as appropriate. */ @@ -388,21 +444,7 @@ summarize_protover_flags(protover_summary_flags_t *out, tor_assert(out); memset(out, 0, sizeof(*out)); if (protocols) { - out->protocols_known = 1; - out->supports_extend2_cells = - protocol_list_supports_protocol(protocols, PRT_RELAY, 2); - out->supports_ed25519_link_handshake_compat = - protocol_list_supports_protocol(protocols, PRT_LINKAUTH, 3); - out->supports_ed25519_link_handshake_any = - protocol_list_supports_protocol_or_later(protocols, PRT_LINKAUTH, 3); - out->supports_ed25519_hs_intro = - protocol_list_supports_protocol(protocols, PRT_HSINTRO, 4); - out->supports_v3_hsdir = - protocol_list_supports_protocol(protocols, PRT_HSDIR, - PROTOVER_HSDIR_V3); - out->supports_v3_rendezvous_point = - protocol_list_supports_protocol(protocols, PRT_HSREND, - PROTOVER_HS_RENDEZVOUS_POINT_V3); + memoize_protover_summary(out, protocols); } if (version && !strcmpstart(version, "Tor ")) { if (!out->protocols_known) { @@ -420,3 +462,13 @@ summarize_protover_flags(protover_summary_flags_t *out, } } } + +/** + * Free all space held in the protover_summary_map. + */ +void +protover_summary_cache_free_all(void) +{ + strmap_free(protover_summary_map, tor_free_); + protover_summary_map = NULL; +} diff --git a/src/core/or/versions.h b/src/core/or/versions.h index 0c773f3f4c..4fc50a0018 100644 --- a/src/core/or/versions.h +++ b/src/core/or/versions.h @@ -41,4 +41,6 @@ void summarize_protover_flags(protover_summary_flags_t *out, const char *protocols, const char *version); +void protover_summary_cache_free_all(void); + #endif /* !defined(TOR_VERSIONS_H) */ diff --git a/src/feature/dirauth/process_descs.c b/src/feature/dirauth/process_descs.c index c379f25bdd..dca87b3eaf 100644 --- a/src/feature/dirauth/process_descs.c +++ b/src/feature/dirauth/process_descs.c @@ -519,7 +519,8 @@ WRA_MORE_SEVERE(was_router_added_t a, was_router_added_t b) /** As for dirserv_add_descriptor(), but accepts multiple documents, and * returns the most severe error that occurred for any one of them. */ was_router_added_t -dirserv_add_multiple_descriptors(const char *desc, uint8_t purpose, +dirserv_add_multiple_descriptors(const char *desc, size_t desclen, + uint8_t purpose, const char *source, const char **msg) { @@ -536,6 +537,11 @@ dirserv_add_multiple_descriptors(const char *desc, uint8_t purpose, r=ROUTER_ADDED_SUCCESSFULLY; /*Least severe return value. */ + if (!string_is_utf8_no_bom(desc, desclen)) { + *msg = "descriptor(s) or extrainfo(s) not valid UTF-8 or had BOM."; + return ROUTER_AUTHDIR_REJECTS; + } + format_iso_time(time_buf, now); if (tor_snprintf(annotation_buf, sizeof(annotation_buf), "@uploaded-at %s\n" @@ -552,7 +558,7 @@ dirserv_add_multiple_descriptors(const char *desc, uint8_t purpose, s = desc; list = smartlist_new(); - if (!router_parse_list_from_string(&s, NULL, list, SAVED_NOWHERE, 0, 0, + if (!router_parse_list_from_string(&s, s+desclen, list, SAVED_NOWHERE, 0, 0, annotation_buf, NULL)) { SMARTLIST_FOREACH(list, routerinfo_t *, ri, { msg_out = NULL; @@ -568,7 +574,7 @@ dirserv_add_multiple_descriptors(const char *desc, uint8_t purpose, smartlist_clear(list); s = desc; - if (!router_parse_list_from_string(&s, NULL, list, SAVED_NOWHERE, 1, 0, + if (!router_parse_list_from_string(&s, s+desclen, list, SAVED_NOWHERE, 1, 0, NULL, NULL)) { SMARTLIST_FOREACH(list, extrainfo_t *, ei, { msg_out = NULL; diff --git a/src/feature/dirauth/process_descs.h b/src/feature/dirauth/process_descs.h index ad9d5c3d4c..5a0914acd8 100644 --- a/src/feature/dirauth/process_descs.h +++ b/src/feature/dirauth/process_descs.h @@ -17,7 +17,8 @@ void dirserv_free_fingerprint_list(void); int dirserv_add_own_fingerprint(crypto_pk_t *pk); enum was_router_added_t dirserv_add_multiple_descriptors( - const char *desc, uint8_t purpose, + const char *desc, size_t desclen, + uint8_t purpose, const char *source, const char **msg); enum was_router_added_t dirserv_add_descriptor(routerinfo_t *ri, diff --git a/src/feature/dircache/dircache.c b/src/feature/dircache/dircache.c index 872a88018f..4032223db4 100644 --- a/src/feature/dircache/dircache.c +++ b/src/feature/dircache/dircache.c @@ -166,22 +166,16 @@ write_http_response_header_impl(dir_connection_t *conn, ssize_t length, buf_free(buf); } -/** As write_http_response_header_impl, but sets encoding and content-typed - * based on whether the response will be <b>compressed</b> or not. */ +/** As write_http_response_header_impl, but translates method into + * encoding */ static void write_http_response_headers(dir_connection_t *conn, ssize_t length, compress_method_t method, const char *extra_headers, long cache_lifetime) { - const char *methodname = compression_method_get_name(method); - const char *doctype; - if (method == NO_METHOD) - doctype = "text/plain"; - else - doctype = "application/octet-stream"; write_http_response_header_impl(conn, length, - doctype, - methodname, + "text/plain", + compression_method_get_name(method), extra_headers, cache_lifetime); } @@ -1608,8 +1602,8 @@ directory_handle_command_post,(dir_connection_t *conn, const char *headers, const char *msg = "[None]"; uint8_t purpose = authdir_mode_bridge(options) ? ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL; - was_router_added_t r = dirserv_add_multiple_descriptors(body, purpose, - conn->base_.address, &msg); + was_router_added_t r = dirserv_add_multiple_descriptors(body, body_len, + purpose, conn->base_.address, &msg); tor_assert(msg); if (r == ROUTER_ADDED_SUCCESSFULLY) { diff --git a/src/feature/dirclient/dirclient.c b/src/feature/dirclient/dirclient.c index 705bf75e5c..cd88fa5ebf 100644 --- a/src/feature/dirclient/dirclient.c +++ b/src/feature/dirclient/dirclient.c @@ -2221,6 +2221,7 @@ handle_response_fetch_consensus(dir_connection_t *conn, if (!consensus_body) { log_warn(LD_DIR, "Received a consensus diff, but we can't find " "any %s-flavored consensus in our current cache.",flavname); + tor_munmap_file(mapped_consensus); networkstatus_consensus_download_failed(0, flavname); // XXXX if this happens too much, see below return -1; diff --git a/src/feature/hibernate/hibernate.c b/src/feature/hibernate/hibernate.c index 02b05ca3a2..6f8795cecc 100644 --- a/src/feature/hibernate/hibernate.c +++ b/src/feature/hibernate/hibernate.c @@ -50,6 +50,16 @@ hibernating, phase 2: #include <unistd.h> #endif +#ifdef HAVE_SYSTEMD +# if defined(__COVERITY__) && !defined(__INCLUDE_LEVEL__) +/* Systemd's use of gcc's __INCLUDE_LEVEL__ extension macro appears to confuse + * Coverity. Here's a kludge to unconfuse it. + */ +# define __INCLUDE_LEVEL__ 2 +# endif /* defined(__COVERITY__) && !defined(__INCLUDE_LEVEL__) */ +#include <systemd/sd-daemon.h> +#endif /* defined(HAVE_SYSTEMD) */ + /** Are we currently awake, asleep, running out of bandwidth, or shutting * down? */ static hibernate_state_t hibernate_state = HIBERNATE_STATE_INITIAL; @@ -821,6 +831,8 @@ hibernate_soft_limit_reached(void) return get_accounting_bytes() >= soft_limit; } +#define TOR_USEC_PER_SEC (1000000) + /** Called when we get a SIGINT, or when bandwidth soft limit is * reached. Puts us into "loose hibernation": we don't accept new * connections, but we continue handling old ones. */ @@ -856,6 +868,26 @@ hibernate_begin(hibernate_state_t new_state, time_t now) "connections, and will shut down in %d seconds. Interrupt " "again to exit now.", options->ShutdownWaitLength); shutdown_time = time(NULL) + options->ShutdownWaitLength; +#ifdef HAVE_SYSTEMD + /* tell systemd that we may need more than the default 90 seconds to shut + * down so they don't kill us. add some extra time to actually finish + * shutting down, otherwise systemd will kill us immediately after the + * EXTEND_TIMEOUT_USEC expires. this is an *upper* limit; tor will probably + * only take one or two more seconds, but assume that maybe we got swapped + * out and it takes a little while longer. + * + * as of writing, this is a no-op with all-defaults: ShutdownWaitLength is + * 30 seconds, so this will extend the timeout to 60 seconds. + * default systemd DefaultTimeoutStopSec is 90 seconds, so systemd will + * wait (up to) 90 seconds anyways. + * + * 2^31 usec = ~2147 sec = ~35 min. probably nobody will actually set + * ShutdownWaitLength to more than that, but use a longer type so we don't + * need to think about UB on overflow + */ + sd_notifyf(0, "EXTEND_TIMEOUT_USEC=%" PRIu64, + ((uint64_t)(options->ShutdownWaitLength) + 30) * TOR_USEC_PER_SEC); +#endif } else { /* soft limit reached */ hibernate_end_time = interval_end_time; } diff --git a/src/feature/nodelist/networkstatus.c b/src/feature/nodelist/networkstatus.c index ec1a69b9e2..f1def9afb1 100644 --- a/src/feature/nodelist/networkstatus.c +++ b/src/feature/nodelist/networkstatus.c @@ -2403,7 +2403,9 @@ networkstatus_dump_bridge_status_to_file(time_t now) published, thresholds, fingerprint_line ? fingerprint_line : "", status); fname = get_datadir_fname("networkstatus-bridges"); - write_str_to_file(fname,published_thresholds_and_status,0); + if (write_str_to_file(fname,published_thresholds_and_status,0)<0) { + log_warn(LD_DIRSERV, "Unable to write networkstatus-bridges file."); + } tor_free(thresholds); tor_free(published_thresholds_and_status); tor_free(fname); diff --git a/src/lib/cc/.may_include b/src/lib/cc/.may_include index 2b06e8519c..fa1478ce46 100644 --- a/src/lib/cc/.may_include +++ b/src/lib/cc/.may_include @@ -1 +1,2 @@ orconfig.h +lib/cc/*.h
\ No newline at end of file diff --git a/src/lib/cc/ctassert.h b/src/lib/cc/ctassert.h new file mode 100644 index 0000000000..e42976360f --- /dev/null +++ b/src/lib/cc/ctassert.h @@ -0,0 +1,53 @@ +/* Copyright (c) 2018 The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file ctassert.h + * + * \brief Compile-time assertions: CTASSERT(expression). + */ + +#ifndef TOR_CTASSERT_H +#define TOR_CTASSERT_H + +#include "lib/cc/compat_compiler.h" + +/** + * CTASSERT(expression) + * + * Trigger a compiler error if expression is false. + */ +#if __STDC_VERSION__ >= 201112L + +/* If C11 is available, just use _Static_assert. */ +#define CTASSERT(x) _Static_assert((x), #x) + +#else + +/* + * If C11 is not available, expand __COUNTER__, or __INCLUDE_LEVEL__ + * and __LINE__, or just __LINE__, with an intermediate preprocessor + * macro CTASSERT_EXPN, and then use CTASSERT_DECL to paste the + * expansions together into a unique name. + * + * We use this name as a typedef of an array type with a positive + * length if the assertion is true, and a negative length of the + * assertion is false, which is invalid and hence triggers a compiler + * error. + */ +#if defined(__COUNTER__) +#define CTASSERT(x) CTASSERT_EXPN((x), c, __COUNTER__) +#elif defined(__INCLUDE_LEVEL__) +#define CTASSERT(x) CTASSERT_EXPN((x), __INCLUDE_LEVEL__, __LINE__) +#else +/* hope it's unique enough */ +#define CTASSERT(x) CTASSERT_EXPN((x), l, __LINE__) +#endif + +#define CTASSERT_EXPN(x, a, b) CTASSERT_DECL(x, a, b) +#define CTASSERT_DECL(x, a, b) \ + typedef char tor_ctassert_##a##_##b[(x) ? 1 : -1] ATTR_UNUSED + +#endif + +#endif /* !defined(TOR_CTASSERT_H) */ diff --git a/src/lib/cc/include.am b/src/lib/cc/include.am index 2ae90f97dd..52cf8a9f72 100644 --- a/src/lib/cc/include.am +++ b/src/lib/cc/include.am @@ -1,4 +1,5 @@ noinst_HEADERS += \ src/lib/cc/compat_compiler.h \ + src/lib/cc/ctassert.h \ src/lib/cc/torint.h diff --git a/src/lib/encoding/time_fmt.c b/src/lib/encoding/time_fmt.c index a921fc681c..233d0dddff 100644 --- a/src/lib/encoding/time_fmt.c +++ b/src/lib/encoding/time_fmt.c @@ -26,6 +26,10 @@ #include <string.h> #include <time.h> +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif + #ifdef _WIN32 /* For struct timeval */ #include <winsock2.h> diff --git a/src/lib/evloop/timers.c b/src/lib/evloop/timers.c index c4e85c7c93..3603bf1a7d 100644 --- a/src/lib/evloop/timers.c +++ b/src/lib/evloop/timers.c @@ -39,6 +39,10 @@ #include "lib/malloc/malloc.h" #include "lib/time/compat_time.h" +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif + #ifdef _WIN32 // For struct timeval. #include <winsock2.h> diff --git a/src/lib/net/address.c b/src/lib/net/address.c index c97a17037a..a351b9df28 100644 --- a/src/lib/net/address.c +++ b/src/lib/net/address.c @@ -40,6 +40,7 @@ #include "lib/net/address.h" #include "lib/net/socket.h" +#include "lib/cc/ctassert.h" #include "lib/container/smartlist.h" #include "lib/ctime/di_ops.h" #include "lib/log/log.h" @@ -98,6 +99,7 @@ #if AF_UNSPEC != 0 #error We rely on AF_UNSPEC being 0. Let us know about your platform, please! #endif +CTASSERT(AF_UNSPEC == 0); /** Convert the tor_addr_t in <b>a</b>, with port in <b>port</b>, into a * sockaddr object in *<b>sa_out</b> of object size <b>len</b>. If not enough diff --git a/src/lib/string/util_string.c b/src/lib/string/util_string.c index b2b85d151d..e76e73046f 100644 --- a/src/lib/string/util_string.c +++ b/src/lib/string/util_string.c @@ -541,3 +541,16 @@ string_is_utf8(const char *str, size_t len) } return true; } + +/** As string_is_utf8(), but returns false if the string begins with a UTF-8 + * byte order mark (BOM). + */ +int +string_is_utf8_no_bom(const char *str, size_t len) +{ + if (len >= 3 && (!strcmpstart(str, "\uFEFF") || + !strcmpstart(str, "\uFFFE"))) { + return false; + } + return string_is_utf8(str, len); +} diff --git a/src/lib/string/util_string.h b/src/lib/string/util_string.h index 746ece0d33..99467a27c3 100644 --- a/src/lib/string/util_string.h +++ b/src/lib/string/util_string.h @@ -53,5 +53,6 @@ const char *find_str_at_start_of_line(const char *haystack, int string_is_C_identifier(const char *string); int string_is_utf8(const char *str, size_t len); +int string_is_utf8_no_bom(const char *str, size_t len); #endif /* !defined(TOR_UTIL_STRING_H) */ diff --git a/src/lib/thread/.may_include b/src/lib/thread/.may_include index c26a426923..02711348c5 100644 --- a/src/lib/thread/.may_include +++ b/src/lib/thread/.may_include @@ -5,3 +5,4 @@ lib/log/*.h lib/subsys/*.h lib/testsupport/*.h lib/thread/*.h +lib/wallclock/*.h diff --git a/src/lib/thread/compat_pthreads.c b/src/lib/thread/compat_pthreads.c index 934067e4c1..e5c8805ddc 100644 --- a/src/lib/thread/compat_pthreads.c +++ b/src/lib/thread/compat_pthreads.c @@ -12,6 +12,7 @@ #include "orconfig.h" #include "lib/thread/threads.h" +#include "lib/wallclock/timeval.h" #include "lib/log/log.h" #include "lib/log/util_bug.h" diff --git a/src/lib/tls/tortls_openssl.c b/src/lib/tls/tortls_openssl.c index 227225b96e..235620714a 100644 --- a/src/lib/tls/tortls_openssl.c +++ b/src/lib/tls/tortls_openssl.c @@ -639,6 +639,22 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime, SSL_CTX_set_tmp_dh(result->ctx, dh); DH_free(dh); } +/* We check for this function in two ways, since it might be either a symbol + * or a macro. */ +#if defined(SSL_CTX_set1_groups_list) || defined(HAVE_SSL_CTX_SET1_GROUPS_LIST) + { + const char *list; + if (flags & TOR_TLS_CTX_USE_ECDHE_P224) + list = "P-224:P-256"; + else if (flags & TOR_TLS_CTX_USE_ECDHE_P256) + list = "P-256:P-224"; + else + list = "P-256:P-224"; + int r = SSL_CTX_set1_groups_list(result->ctx, list); + if (r < 0) + goto error; + } +#else if (! is_client) { int nid; EC_KEY *ec_key; @@ -654,6 +670,7 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime, SSL_CTX_set_tmp_ecdh(result->ctx, ec_key); EC_KEY_free(ec_key); } +#endif SSL_CTX_set_verify(result->ctx, SSL_VERIFY_PEER, always_accept_verify_cb); /* let us realloc bufs that we're writing from */ diff --git a/src/rust/tor_util/strings.rs b/src/rust/tor_util/strings.rs index d64275e06b..71a908a58c 100644 --- a/src/rust/tor_util/strings.rs +++ b/src/rust/tor_util/strings.rs @@ -105,11 +105,7 @@ macro_rules! cstr { ($($bytes:expr),*) => ( ::std::ffi::CStr::from_bytes_with_nul( concat!($($bytes),*, "\0").as_bytes() - ).unwrap_or( - unsafe{ - ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"\0") - } - ) + ).unwrap_or_default() ) } diff --git a/src/test/test_address.c b/src/test/test_address.c index 69de072cfa..a823fd9cd5 100644 --- a/src/test/test_address.c +++ b/src/test/test_address.c @@ -1186,6 +1186,8 @@ helper_create_mock_node(char id_char) static void helper_free_mock_node(node_t *node) { + if (!node) + return; tor_free(node->ri); tor_free(node); } @@ -1237,11 +1239,9 @@ test_address_tor_node_in_same_network_family(void *ignored) NODE_SET_IPV6(node_a, "2606:4700:4700::1001", 1); tt_int_op(nodes_in_same_family(node_a, node_b), OP_EQ, 1); + done: helper_free_mock_node(node_a); helper_free_mock_node(node_b); - - done: - return; } #define ADDRESS_TEST(name, flags) \ @@ -1279,4 +1279,3 @@ struct testcase_t address_tests[] = { ADDRESS_TEST(tor_node_in_same_network_family, 0), END_OF_TESTCASES }; - diff --git a/src/test/test_circuitbuild.c b/src/test/test_circuitbuild.c index 02eadecd98..dd47ad7689 100644 --- a/src/test/test_circuitbuild.c +++ b/src/test/test_circuitbuild.c @@ -21,11 +21,11 @@ static smartlist_t dummy_nodes; static extend_info_t dummy_ei; static int -mock_count_acceptable_nodes(smartlist_t *nodes) +mock_count_acceptable_nodes(smartlist_t *nodes, int direct) { (void)nodes; - return DEFAULT_ROUTE_LEN + 1; + return direct ? 1 : DEFAULT_ROUTE_LEN + 1; } /* Test route lengths when the caller of new_route_len() doesn't diff --git a/src/test/test_rebind.py b/src/test/test_rebind.py index 7ba3a5796d..c63341a681 100644 --- a/src/test/test_rebind.py +++ b/src/test/test_rebind.py @@ -1,25 +1,42 @@ from __future__ import print_function -import sys -import subprocess -import socket +import errno import os -import time import random +import socket +import subprocess +import sys +import time + +LOG_TIMEOUT = 60.0 +LOG_WAIT = 0.1 +LOG_CHECK_LIMIT = LOG_TIMEOUT / LOG_WAIT + +def fail(msg): + print('FAIL') + sys.exit(msg) def try_connecting_to_socksport(): socks_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) if socks_socket.connect_ex(('127.0.0.1', socks_port)): tor_process.terminate() - print('FAIL') - sys.exit('Cannot connect to SOCKSPort') + fail('Cannot connect to SOCKSPort') socks_socket.close() def wait_for_log(s): - while True: + log_checked = 0 + while log_checked < LOG_CHECK_LIMIT: l = tor_process.stdout.readline() - if s in l.decode('utf8'): + l = l.decode('utf8') + if s in l: return + print('Tor logged: "{}", waiting for "{}"'.format(l.strip(), s)) + # readline() returns a blank string when there is no output + # avoid busy-waiting + if len(s) == 0: + time.sleep(LOG_WAIT) + log_checked += 1 + fail('Could not find "{}" in logs after {} seconds'.format(s, LOG_TIMEOUT)) def pick_random_port(): port = 0 @@ -33,13 +50,16 @@ def pick_random_port(): else: break + if port == 0: + fail('Could not find a random free port between 10000 and 60000') + return port if sys.hexversion < 0x02070000: - sys.exit("ERROR: unsupported Python version (should be >= 2.7)") + fail("ERROR: unsupported Python version (should be >= 2.7)") if sys.hexversion > 0x03000000 and sys.hexversion < 0x03010000: - sys.exit("ERROR: unsupported Python3 version (should be >= 3.1)") + fail("ERROR: unsupported Python3 version (should be >= 3.1)") control_port = pick_random_port() socks_port = pick_random_port() @@ -48,7 +68,7 @@ assert control_port != 0 assert socks_port != 0 if not os.path.exists(sys.argv[1]): - sys.exit('ERROR: cannot find tor at %s' % sys.argv[1]) + fail('ERROR: cannot find tor at %s' % sys.argv[1]) tor_path = sys.argv[1] @@ -60,10 +80,10 @@ tor_process = subprocess.Popen([tor_path, stderr=subprocess.PIPE) if tor_process == None: - sys.exit('ERROR: running tor failed') + fail('ERROR: running tor failed') if len(sys.argv) < 2: - sys.exit('Usage: %s <path-to-tor>' % sys.argv[0]) + fail('Usage: %s <path-to-tor>' % sys.argv[0]) wait_for_log('Opened Control listener on') @@ -72,8 +92,7 @@ try_connecting_to_socksport() control_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) if control_socket.connect_ex(('127.0.0.1', control_port)): tor_process.terminate() - print('FAIL') - sys.exit('Cannot connect to ControlPort') + fail('Cannot connect to ControlPort') control_socket.sendall('AUTHENTICATE \r\n'.encode('utf8')) control_socket.sendall('SETCONF SOCKSPort=0.0.0.0:{}\r\n'.format(socks_port).encode('utf8')) @@ -88,6 +107,14 @@ try_connecting_to_socksport() control_socket.sendall('SIGNAL HALT\r\n'.encode('utf8')) -time.sleep(0.1) +wait_for_log('exiting cleanly') print('OK') -tor_process.terminate() + +try: + tor_process.terminate() +except OSError as e: + if e.errno == errno.ESRCH: # errno 3: No such process + # assume tor has already exited due to SIGNAL HALT + print("Tor has already exited") + else: + raise diff --git a/src/test/test_util.c b/src/test/test_util.c index 1a71da2794..bcface64fd 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -4024,6 +4024,13 @@ test_util_string_is_utf8(void *ptr) tt_int_op(1, OP_EQ, string_is_utf8("ascii\x7f\n", 7)); tt_int_op(1, OP_EQ, string_is_utf8("Risqu\u00e9=1", 9)); + /* Test the utf8_no_bom function */ + tt_int_op(0, OP_EQ, string_is_utf8_no_bom("\uFEFF", 3)); + tt_int_op(0, OP_EQ, string_is_utf8_no_bom("\uFFFE", 3)); + tt_int_op(0, OP_EQ, string_is_utf8_no_bom("\uFEFFlove", 7)); + tt_int_op(1, OP_EQ, string_is_utf8_no_bom("loveandrespect", + strlen("loveandrespect"))); + // Validate exactly 'len' bytes. tt_int_op(0, OP_EQ, string_is_utf8("\0\x80", 2)); tt_int_op(0, OP_EQ, string_is_utf8("Risqu\u00e9=1", 6)); diff --git a/src/win32/orconfig.h b/src/win32/orconfig.h index de3bf09282..cfc3bc9e9e 100644 --- a/src/win32/orconfig.h +++ b/src/win32/orconfig.h @@ -218,7 +218,7 @@ #define USING_TWOS_COMPLEMENT /* Version number of package */ -#define VERSION "0.3.6.0-alpha-dev" +#define VERSION "0.4.0.0-alpha-dev" |