diff options
Diffstat (limited to 'src')
56 files changed, 1283 insertions, 305 deletions
diff --git a/src/app/config/config.c b/src/app/config/config.c index 5c8a3792ee..6c17bb0d8c 100644 --- a/src/app/config/config.c +++ b/src/app/config/config.c @@ -548,7 +548,7 @@ static const config_var_t option_vars_[] = { V(LogTimeGranularity, MSEC_INTERVAL, "1 second"), V(TruncateLogFile, BOOL, "0"), V_IMMUTABLE(SyslogIdentityTag, STRING, NULL), - V_IMMUTABLE(AndroidIdentityTag,STRING, NULL), + OBSOLETE("AndroidIdentityTag"), V(LongLivedPorts, CSV, "21,22,706,1863,5050,5190,5222,5223,6523,6667,6697,8300"), VAR("MapAddress", LINELIST, AddressMap, NULL), @@ -580,6 +580,7 @@ static const config_var_t option_vars_[] = { V(OutboundBindAddress, LINELIST, NULL), V(OutboundBindAddressOR, LINELIST, NULL), V(OutboundBindAddressExit, LINELIST, NULL), + V(OutboundBindAddressPT, LINELIST, NULL), OBSOLETE("PathBiasDisableRate"), V(PathBiasCircThreshold, INT, "-1"), @@ -609,7 +610,7 @@ static const config_var_t option_vars_[] = { V(TestingAuthKeySlop, INTERVAL, "3 hours"), V(TestingSigningKeySlop, INTERVAL, "1 day"), - V(OptimisticData, AUTOBOOL, "auto"), + OBSOLETE("OptimisticData"), OBSOLETE("PortForwarding"), OBSOLETE("PortForwardingHelper"), OBSOLETE("PreferTunneledDirConns"), @@ -2104,6 +2105,16 @@ options_act,(const or_options_t *old_options)) "in a non-anonymous mode. It will provide NO ANONYMITY."); } + /* 31851: OutboundBindAddressExit is relay-only */ + if (parse_outbound_addresses(options, 0, &msg) < 0) { + // LCOV_EXCL_START + log_warn(LD_BUG, "Failed parsing previously validated outbound " + "bind addresses: %s", msg); + tor_free(msg); + return -1; + // LCOV_EXCL_STOP + } + if (options->Bridges) { mark_bridge_list(); for (cl = options->Bridges; cl; cl = cl->next) { @@ -2265,16 +2276,6 @@ options_act,(const or_options_t *old_options)) tor_free(http_authenticator); } - /* 31851: OutboundBindAddressExit is relay-only */ - if (parse_outbound_addresses(options, 0, &msg) < 0) { - // LCOV_EXCL_START - log_warn(LD_BUG, "Failed parsing previously validated outbound " - "bind addresses: %s", msg); - tor_free(msg); - return -1; - // LCOV_EXCL_STOP - } - config_maybe_load_geoip_files_(options, old_options); if (geoip_is_loaded(AF_INET) && options->GeoIPExcludeUnknown) { @@ -4934,15 +4935,19 @@ options_init_logs(const or_options_t *old_options, const or_options_t *options, goto cleanup; } + /* We added this workaround in 0.4.5.x; we can remove it in 0.4.6 or + * later */ if (!strcasecmp(smartlist_get(elts, 0), "android")) { -#ifdef HAVE_ANDROID_LOG_H +#ifdef HAVE_SYSLOG_H + log_warn(LD_CONFIG, "The android logging API is no longer supported;" + " adding a syslog instead. The 'android' logging " + " type will no longer work in the future."); if (!validate_only) { - add_android_log(severity, options->AndroidIdentityTag); + add_syslog_log(severity, options->SyslogIdentityTag); } #else - log_warn(LD_CONFIG, "Android logging is not supported" - " on this system. Sorry."); -#endif /* defined(HAVE_ANDROID_LOG_H) */ + log_warn(LD_CONFIG, "The android logging API is no longer supported."); +#endif goto cleanup; } } @@ -7180,7 +7185,8 @@ parse_outbound_address_lines(const config_line_t *lines, outbound_addr_t type, "configured: %s", family==AF_INET?" IPv4":(family==AF_INET6?" IPv6":""), type==OUTBOUND_ADDR_OR?" OR": - (type==OUTBOUND_ADDR_EXIT?" exit":""), lines->value); + (type==OUTBOUND_ADDR_EXIT?" exit": + (type==OUTBOUND_ADDR_PT?" PT":"")), lines->value); return -1; } lines = lines->next; @@ -7203,7 +7209,7 @@ parse_outbound_addresses(or_options_t *options, int validate_only, char **msg) } if (parse_outbound_address_lines(options->OutboundBindAddress, - OUTBOUND_ADDR_EXIT_AND_OR, options, + OUTBOUND_ADDR_ANY, options, validate_only, msg) < 0) { goto err; } @@ -7220,6 +7226,12 @@ parse_outbound_addresses(or_options_t *options, int validate_only, char **msg) goto err; } + if (parse_outbound_address_lines(options->OutboundBindAddressPT, + OUTBOUND_ADDR_PT, options, validate_only, + msg) < 0) { + goto err; + } + return 0; err: return -1; diff --git a/src/app/config/or_options_st.h b/src/app/config/or_options_st.h index 3b84e5e1f2..3ccd2c9761 100644 --- a/src/app/config/or_options_st.h +++ b/src/app/config/or_options_st.h @@ -24,10 +24,29 @@ struct config_suite_t; struct routerset_t; /** Enumeration of outbound address configuration types: - * Exit-only, OR-only, or both */ -typedef enum {OUTBOUND_ADDR_EXIT, OUTBOUND_ADDR_OR, - OUTBOUND_ADDR_EXIT_AND_OR, - OUTBOUND_ADDR_MAX} outbound_addr_t; + * Exit-only, OR-only, PT-only, or any of them */ +typedef enum { + /** Outbound IP address for Exit connections. Controlled by the + * `OutboundBindAddressExit` configuration entry in torrc. */ + OUTBOUND_ADDR_EXIT, + + /** Outbound IP address for OR connections. Controlled by the + * `OutboundBindAddressOR` configuration entry in torrc. */ + OUTBOUND_ADDR_OR, + + /** Outbound IP address for PT connections. Controlled by the + * `OutboundBindAddressPT` configuration entry in torrc. */ + OUTBOUND_ADDR_PT, + + /** Outbound IP address for any outgoing connections. Controlled by the + * OutboundBindAddress configuration entry in torrc. This value is used as + * fallback if the more specific OUTBOUND_ADDR_EXIT, OUTBOUND_ADDR_OR, and + * OUTBOUND_ADDR_PT are unset. */ + OUTBOUND_ADDR_ANY, + + /** Max value for this enum. Must be the last element in this enum. */ + OUTBOUND_ADDR_MAX +} outbound_addr_t; /** Which protocol to use for TCPProxy. */ typedef enum { @@ -58,7 +77,6 @@ struct or_options_t { int TruncateLogFile; /**< Boolean: Should we truncate the log file before we start writing? */ char *SyslogIdentityTag; /**< Identity tag to add for syslog logging. */ - char *AndroidIdentityTag; /**< Identity tag to add for Android logging. */ char *DebugLogFile; /**< Where to send verbose log messages. */ char *DataDirectory_option; /**< Where to store long-term data, as @@ -131,6 +149,8 @@ struct or_options_t { struct config_line_t *OutboundBindAddressOR; /** Local address to bind outbound exit sockets */ struct config_line_t *OutboundBindAddressExit; + /** Local address to bind outbound PT sockets */ + struct config_line_t *OutboundBindAddressPT; /** Addresses derived from the various OutboundBindAddress lines. * [][0] is IPv4, [][1] is IPv6 */ @@ -848,10 +868,6 @@ struct or_options_t { * once. */ int MaxClientCircuitsPending; - /** If 1, we always send optimistic data when it's supported. If 0, we - * never use it. If -1, we do what the consensus says. */ - int OptimisticData; - /** If 1, we accept and launch no external network connections, except on * control ports. */ int DisableNetwork; diff --git a/src/app/config/or_state_st.h b/src/app/config/or_state_st.h index 31b7f8a983..6769ef7b87 100644 --- a/src/app/config/or_state_st.h +++ b/src/app/config/or_state_st.h @@ -38,17 +38,11 @@ struct or_state_t { uint64_t AccountingBytesAtSoftLimit; uint64_t AccountingExpectedUsage; - /** A list of Entry Guard-related configuration lines. (pre-prop271) */ - struct config_line_t *EntryGuards; - - /** A list of guard-related configuration lines. (post-prop271) */ + /** A list of guard-related configuration lines. */ struct config_line_t *Guard; struct config_line_t *TransportProxies; - /** Cached revision counters for active hidden services on this host */ - struct config_line_t *HidServRevCounter; - /** These fields hold information on the history of bandwidth usage for * servers. The "Ends" fields hold the time when we last updated the * bandwidth usage. The "Interval" fields hold the granularity, in seconds, diff --git a/src/app/config/resolve_addr.c b/src/app/config/resolve_addr.c index b37707d2da..b811a68b8c 100644 --- a/src/app/config/resolve_addr.c +++ b/src/app/config/resolve_addr.c @@ -652,12 +652,12 @@ static const size_t fn_address_table_auth_len = * method_out is set to RESOLVED_ADDR_RESOLVED and hostname_out is set * to the resolved hostname. On failure to resolve, an error is returned. * - * If no given Address, fallback to the local hostname (see section 2). + * If no given Address, fallback to the network interface (see section 2). * * 2. Look at the network interface. * * Attempt to find the first public usable address from the list of - * network interface returned by the OS. + * network interfaces returned by the OS. * * On failure, we attempt to look at the local hostname (3). * diff --git a/src/app/config/statefile.c b/src/app/config/statefile.c index b25167d2ec..22b15fcf24 100644 --- a/src/app/config/statefile.c +++ b/src/app/config/statefile.c @@ -58,16 +58,38 @@ /** A list of state-file "abbreviations," for compatibility. */ static config_abbrev_t state_abbrevs_[] = { - { "AccountingBytesReadInterval", "AccountingBytesReadInInterval", 0, 0 }, - { "HelperNode", "EntryGuard", 0, 0 }, - { "HelperNodeDownSince", "EntryGuardDownSince", 0, 0 }, - { "HelperNodeUnlistedSince", "EntryGuardUnlistedSince", 0, 0 }, - { "EntryNode", "EntryGuard", 0, 0 }, - { "EntryNodeDownSince", "EntryGuardDownSince", 0, 0 }, - { "EntryNodeUnlistedSince", "EntryGuardUnlistedSince", 0, 0 }, { NULL, NULL, 0, 0}, }; +/** A list of obsolete keys that we do not and should not preserve. + * + * We could just let these live in ExtraLines indefinitely, but they're + * never going to be used again, and every version that used them + * has been obsolete for a long time. + * */ +static const char *obsolete_state_keys[] = { + /* These were renamed in 0.1.1.11-alpha */ + "AccountingBytesReadInterval", + "HelperNode", + "HelperNodeDownSince", + "HelperNodeUnlistedSince", + "EntryNode", + "HelperNodeDownSince", + "EntryNodeUnlistedSince", + /* These were replaced by "Guard" in 0.3.0.1-alpha. */ + "EntryGuard", + "EntryGuardDownSince", + "EntryGuardUnlistedSince", + "EntryGuardAddedBy", + "EntryGuardPathBias", + "EntryGuardPathUseBias", + /* This was replaced by OPE-based revision numbers in 0.3.5.1-alpha, + * and was never actually used in a released version. */ + "HidServRevCounter", + + NULL, +}; + /** dummy instance of or_state_t, used for type-checking its * members with CONF_CHECK_VAR_TYPE. */ DUMMY_TYPECHECK_INSTANCE(or_state_t); @@ -91,19 +113,9 @@ static const config_var_t state_vars_[] = { V(AccountingSoftLimitHitAt, ISOTIME, NULL), V(AccountingBytesAtSoftLimit, MEMUNIT, NULL), - VAR("EntryGuard", LINELIST_S, EntryGuards, NULL), - VAR("EntryGuardDownSince", LINELIST_S, EntryGuards, NULL), - VAR("EntryGuardUnlistedSince", LINELIST_S, EntryGuards, NULL), - VAR("EntryGuardAddedBy", LINELIST_S, EntryGuards, NULL), - VAR("EntryGuardPathBias", LINELIST_S, EntryGuards, NULL), - VAR("EntryGuardPathUseBias", LINELIST_S, EntryGuards, NULL), - V(EntryGuards, LINELIST_V, NULL), - VAR("TransportProxy", LINELIST_S, TransportProxies, NULL), V(TransportProxies, LINELIST_V, NULL), - V(HidServRevCounter, LINELIST, NULL), - V(BWHistoryReadEnds, ISOTIME, NULL), V(BWHistoryReadInterval, POSINT, "900"), V(BWHistoryReadValues, CSV, ""), @@ -475,6 +487,7 @@ or_state_load(void) } else { log_info(LD_GENERAL, "Initialized state"); } + or_state_remove_obsolete_lines(&new_state->ExtraLines); if (or_state_set(new_state) == -1) { or_state_save_broken(fname); } @@ -494,6 +507,36 @@ or_state_load(void) return r; } +/** Remove from `extra_lines` every element whose key appears in + * `obsolete_state_keys`. */ +STATIC void +or_state_remove_obsolete_lines(config_line_t **extra_lines) +{ + /* make a strmap for the obsolete state names, so we can have O(1) + lookup. */ + strmap_t *bad_keys = strmap_new(); + for (unsigned i = 0; obsolete_state_keys[i] != NULL; ++i) { + strmap_set_lc(bad_keys, obsolete_state_keys[i], (void*)"rmv"); + } + + config_line_t **line = extra_lines; + while (*line) { + if (strmap_get_lc(bad_keys, (*line)->key) != NULL) { + /* This key is obsolete; remove it. */ + config_line_t *victim = *line; + *line = (*line)->next; + + victim->next = NULL; // prevent double-free. + config_free_lines(victim); + } else { + /* This is just an unrecognized key; keep it. */ + line = &(*line)->next; + } + } + + strmap_free(bad_keys, NULL); +} + /** Did the last time we tried to write the state file fail? If so, we * should consider disabling such features as preemptive circuit generation * to compute circuit-build-time. */ diff --git a/src/app/config/statefile.h b/src/app/config/statefile.h index 98d9d2dda1..89b10560f3 100644 --- a/src/app/config/statefile.h +++ b/src/app/config/statefile.h @@ -33,6 +33,7 @@ STATIC void or_state_free_(or_state_t *state); STATIC or_state_t *or_state_new(void); struct config_mgr_t; STATIC const struct config_mgr_t *get_state_mgr(void); +STATIC void or_state_remove_obsolete_lines(struct config_line_t **extra_lines); #endif /* defined(STATEFILE_PRIVATE) */ #endif /* !defined(TOR_STATEFILE_H) */ diff --git a/src/app/main/main.c b/src/app/main/main.c index 31a4f141ad..ff530c0ad0 100644 --- a/src/app/main/main.c +++ b/src/app/main/main.c @@ -298,7 +298,7 @@ process_signal(int sig) } #ifdef _WIN32 -/** Activate SIGINT on reciving a control signal in console */ +/** Activate SIGINT on receiving a control signal in console. */ static BOOL WINAPI process_win32_console_ctrl(DWORD ctrl_type) { diff --git a/src/app/main/subsysmgr.c b/src/app/main/subsysmgr.c index de601d28cd..349803cd46 100644 --- a/src/app/main/subsysmgr.c +++ b/src/app/main/subsysmgr.c @@ -300,7 +300,7 @@ subsystems_thread_cleanup(void) void subsystems_dump_list(void) { - for (unsigned i = 0; i < n_tor_subsystems - 1; ++i) { + for (unsigned i = 0; i < n_tor_subsystems; ++i) { const subsys_fns_t *sys = tor_subsystems[i]; printf("% 4d\t%16s\t%s\n", sys->level, sys->name, sys->location?sys->location:""); diff --git a/src/core/mainloop/connection.c b/src/core/mainloop/connection.c index 82886ccd0b..c043b1ccec 100644 --- a/src/core/mainloop/connection.c +++ b/src/core/mainloop/connection.c @@ -2331,9 +2331,9 @@ conn_get_outbound_address(sa_family_t family, ext_addr = &options->OutboundBindAddresses[OUTBOUND_ADDR_EXIT] [fam_index]; } else if (!tor_addr_is_null( - &options->OutboundBindAddresses[OUTBOUND_ADDR_EXIT_AND_OR] + &options->OutboundBindAddresses[OUTBOUND_ADDR_ANY] [fam_index])) { - ext_addr = &options->OutboundBindAddresses[OUTBOUND_ADDR_EXIT_AND_OR] + ext_addr = &options->OutboundBindAddresses[OUTBOUND_ADDR_ANY] [fam_index]; } } else { // All non-exit connections @@ -2342,9 +2342,9 @@ conn_get_outbound_address(sa_family_t family, ext_addr = &options->OutboundBindAddresses[OUTBOUND_ADDR_OR] [fam_index]; } else if (!tor_addr_is_null( - &options->OutboundBindAddresses[OUTBOUND_ADDR_EXIT_AND_OR] + &options->OutboundBindAddresses[OUTBOUND_ADDR_ANY] [fam_index])) { - ext_addr = &options->OutboundBindAddresses[OUTBOUND_ADDR_EXIT_AND_OR] + ext_addr = &options->OutboundBindAddresses[OUTBOUND_ADDR_ANY] [fam_index]; } } @@ -3224,7 +3224,14 @@ retry_all_listeners(smartlist_t *new_conns, int close_all_noncontrol) &skip, &addr_in_use); } - tor_assert(new_conn); + /* There are many reasons why we can't open a new listener port so in case + * we hit those, bail early so tor can stop. */ + if (!new_conn) { + log_warn(LD_NET, "Unable to create listener port: %s:%d", + fmt_addr(&r->new_port->addr), r->new_port->port); + retval = -1; + break; + } smartlist_add(new_conns, new_conn); diff --git a/src/core/or/channel.c b/src/core/or/channel.c index d082174dc8..c163f53488 100644 --- a/src/core/or/channel.c +++ b/src/core/or/channel.c @@ -2395,12 +2395,16 @@ channel_is_better(channel_t *a, channel_t *b) * *msg_out to a message describing the channel's state and our next action, * and set *launch_out to a boolean indicated whether the caller should try to * launch a new channel with channel_connect(). + * + * If `for_origin_circ` is set, mark the channel as interesting for origin + * circuits, and therefore interesting for our bootstrapping reports. */ MOCK_IMPL(channel_t *, channel_get_for_extend,(const char *rsa_id_digest, const ed25519_public_key_t *ed_id, const tor_addr_t *target_ipv4_addr, const tor_addr_t *target_ipv6_addr, + bool for_origin_circ, const char **msg_out, int *launch_out)) { @@ -2440,8 +2444,15 @@ channel_get_for_extend,(const char *rsa_id_digest, if (!CHANNEL_IS_OPEN(chan)) { /* If the address matches, don't launch a new connection for this * circuit. */ - if (matches_target) + if (matches_target) { ++n_inprogress_goodaddr; + if (for_origin_circ) { + /* We were looking for a connection for an origin circuit; this one + * matches, so we'll note that we decided to use it for an origin + * circuit. */ + channel_mark_as_used_for_origin_circuit(chan); + } + } continue; } diff --git a/src/core/or/channel.h b/src/core/or/channel.h index 606b0730b8..206d0fdc97 100644 --- a/src/core/or/channel.h +++ b/src/core/or/channel.h @@ -526,6 +526,7 @@ void channel_mark_for_close(channel_t *chan); int channel_write_packed_cell(channel_t *chan, packed_cell_t *cell); void channel_listener_mark_for_close(channel_listener_t *chan_l); +void channel_mark_as_used_for_origin_circuit(channel_t *chan); /* Channel callback registrations */ @@ -661,6 +662,7 @@ MOCK_DECL(channel_t *, channel_get_for_extend,( const struct ed25519_public_key_t *ed_id, const tor_addr_t *target_ipv4_addr, const tor_addr_t *target_ipv6_addr, + bool for_origin_circ, const char **msg_out, int *launch_out)); diff --git a/src/core/or/channeltls.c b/src/core/or/channeltls.c index a0debf8d22..32723fed1e 100644 --- a/src/core/or/channeltls.c +++ b/src/core/or/channeltls.c @@ -360,6 +360,31 @@ channel_tls_handle_incoming(or_connection_t *orconn) return chan; } +/** + * Set the `potentially_used_for_bootstrapping` flag on the or_connection_t + * corresponding to the provided channel. + * + * This flag indicates that if the connection fails, it might be interesting + * to the bootstrapping subsystem. (The bootstrapping system only cares about + * channels that we have tried to use for our own circuits. Other channels + * may have been launched in response to EXTEND cells from somebody else, and + * if they fail, it won't necessarily indicate a bootstrapping problem.) + **/ +void +channel_mark_as_used_for_origin_circuit(channel_t *chan) +{ + if (BUG(!chan)) + return; + if (chan->magic != TLS_CHAN_MAGIC) + return; + channel_tls_t *tlschan = channel_tls_from_base(chan); + if (BUG(!tlschan)) + return; + + if (tlschan->conn) + tlschan->conn->potentially_used_for_bootstrapping = 1; +} + /********* * Casts * ********/ diff --git a/src/core/or/circuitbuild.c b/src/core/or/circuitbuild.c index ab4ce9f784..a3a7a8cf58 100644 --- a/src/core/or/circuitbuild.c +++ b/src/core/or/circuitbuild.c @@ -574,6 +574,7 @@ circuit_handle_first_hop(origin_circuit_t *circ) &firsthop->extend_info->ed_identity, orport4 ? &orport4->addr : NULL, orport6 ? &orport6->addr : NULL, + true, &msg, &should_launch); @@ -590,6 +591,11 @@ circuit_handle_first_hop(origin_circuit_t *circ) log_info(LD_CIRC,"connect to firsthop failed. Closing."); return -END_CIRC_REASON_CONNECTFAILED; } + /* We didn't find a channel, but we're launching one for an origin + * circuit. (If we decided not to launch a channel, then we found at + * least one once good in-progress channel use for this circuit, and + * marked it in channel_get_for_extend().) */ + channel_mark_as_used_for_origin_circuit(n_chan); circuit_chan_publish(circ, n_chan); } @@ -602,6 +608,8 @@ circuit_handle_first_hop(origin_circuit_t *circ) } else { /* it's already open. use it. */ tor_assert(!circ->base_.n_hop); circ->base_.n_chan = n_chan; + /* We found a channel, and we're using it for an origin circuit. */ + channel_mark_as_used_for_origin_circuit(n_chan); circuit_chan_publish(circ, n_chan); log_debug(LD_CIRC,"Conn open for %s. Delivering first onion skin.", safe_str_client(extend_info_describe(firsthop->extend_info))); @@ -770,27 +778,15 @@ circuit_deliver_create_cell,(circuit_t *circ, return -1; } -/** Return true iff we should send a create_fast cell to start building a given - * circuit */ -static inline int +/** Return true iff we should send a create_fast cell to start building a + * given circuit */ +static inline bool should_use_create_fast_for_circuit(origin_circuit_t *circ) { - const or_options_t *options = get_options(); tor_assert(circ->cpath); tor_assert(circ->cpath->extend_info); - if (!circuit_has_usable_onion_key(circ)) { - /* We don't have ntor, and we don't have or can't use TAP, - * so our hand is forced: only a create_fast will work. */ - return 1; - } - if (public_server_mode(options)) { - /* We're a server, and we have a usable onion key. We can choose. - * Prefer to blend our circuit into the other circuits we are - * creating on behalf of others. */ - return 0; - } - return networkstatus_get_param(NULL, "usecreatefast", 0, 0, 1); + return ! circuit_has_usable_onion_key(circ); } /** diff --git a/src/core/or/circuitpadding.c b/src/core/or/circuitpadding.c index 889ffb03f1..e6daba5469 100644 --- a/src/core/or/circuitpadding.c +++ b/src/core/or/circuitpadding.c @@ -1226,6 +1226,7 @@ circpad_send_padding_cell_for_callback(circpad_machine_runtime_t *mi) circuit_t *circ = mi->on_circ; int machine_idx = mi->machine_index; mi->padding_scheduled_at_usec = 0; + mi->is_padding_timer_scheduled = 0; circpad_statenum_t state = mi->current_state; /* Make sure circuit didn't close on us */ diff --git a/src/core/or/circuituse.c b/src/core/or/circuituse.c index df23c63cff..9b506e67a1 100644 --- a/src/core/or/circuituse.c +++ b/src/core/or/circuituse.c @@ -2632,22 +2632,6 @@ cpath_is_on_circuit(origin_circuit_t *circ, crypt_path_t *crypt_path) return 0; } -/** Return true iff client-side optimistic data is supported. */ -static int -optimistic_data_enabled(void) -{ - const or_options_t *options = get_options(); - if (options->OptimisticData < 0) { - /* Note: this default was 0 before #18815 was merged. We can't take the - * parameter out of the consensus until versions before that are all - * obsolete. */ - const int32_t enabled = - networkstatus_get_param(NULL, "UseOptimisticData", /*default*/ 1, 0, 1); - return (int)enabled; - } - return options->OptimisticData; -} - /** Attach the AP stream <b>apconn</b> to circ's linked list of * p_streams. Also set apconn's cpath_layer to <b>cpath</b>, or to the last * hop in circ's cpath if <b>cpath</b> is NULL. @@ -2700,11 +2684,10 @@ link_apconn_to_circ(entry_connection_t *apconn, origin_circuit_t *circ, exitnode = node_get_by_id(cpath->extend_info->identity_digest); /* See if we can use optimistic data on this circuit */ - if (optimistic_data_enabled() && - (circ->base_.purpose == CIRCUIT_PURPOSE_C_GENERAL || - circ->base_.purpose == CIRCUIT_PURPOSE_C_HSDIR_GET || - circ->base_.purpose == CIRCUIT_PURPOSE_S_HSDIR_POST || - circ->base_.purpose == CIRCUIT_PURPOSE_C_REND_JOINED)) + if (circ->base_.purpose == CIRCUIT_PURPOSE_C_GENERAL || + circ->base_.purpose == CIRCUIT_PURPOSE_C_HSDIR_GET || + circ->base_.purpose == CIRCUIT_PURPOSE_S_HSDIR_POST || + circ->base_.purpose == CIRCUIT_PURPOSE_C_REND_JOINED) apconn->may_use_optimistic_data = 1; else apconn->may_use_optimistic_data = 0; diff --git a/src/core/or/or_connection_st.h b/src/core/or/or_connection_st.h index 8e012a6b85..253fe67020 100644 --- a/src/core/or/or_connection_st.h +++ b/src/core/or/or_connection_st.h @@ -74,6 +74,11 @@ struct or_connection_t { unsigned int is_outgoing:1; unsigned int proxy_type:3; /**< One of PROXY_NONE...PROXY_HAPROXY */ unsigned int wide_circ_ids:1; + /** True iff a failure on this connection indicates a posssible + * bootstrapping problem. We set this as true if we notice that this + * connection could handle a pending origin circuit, or if we launch it to + * handle an origin circuit. */ + unsigned int potentially_used_for_bootstrapping:1; /** True iff this connection has had its bootstrap failure logged with * control_event_bootstrap_problem. */ unsigned int have_noted_bootstrap_problem:1; diff --git a/src/feature/client/transports.c b/src/feature/client/transports.c index 2eb05d6a67..0e4361a210 100644 --- a/src/feature/client/transports.c +++ b/src/feature/client/transports.c @@ -1447,6 +1447,37 @@ create_managed_proxy_environment(const managed_proxy_t *mp) */ smartlist_add_asprintf(envs, "TOR_PT_EXIT_ON_STDIN_CLOSE=1"); + /* Specify which IPv4 and IPv6 addresses the PT should make its outgoing + * connections from. See: https://bugs.torproject.org/5304 for more + * information about this. */ + { + /* Set TOR_PT_OUTBOUND_BIND_ADDRESS_V4. */ + const tor_addr_t *ipv4_addr = managed_proxy_outbound_address(options, + AF_INET); + + /* managed_proxy_outbound_address() only returns a non-NULL value if + * tor_addr_is_null() was false, which means we don't have to check that + * here. */ + if (ipv4_addr) { + char *ipv4_addr_str = tor_addr_to_str_dup(ipv4_addr); + smartlist_add_asprintf(envs, + "TOR_PT_OUTBOUND_BIND_ADDRESS_V4=%s", + ipv4_addr_str); + tor_free(ipv4_addr_str); + } + + /* Set TOR_PT_OUTBOUND_BIND_ADDRESS_V6. */ + const tor_addr_t *ipv6_addr = managed_proxy_outbound_address(options, + AF_INET6); + if (ipv6_addr) { + char *ipv6_addr_str = tor_addr_to_str_dup(ipv6_addr); + smartlist_add_asprintf(envs, + "TOR_PT_OUTBOUND_BIND_ADDRESS_V6=[%s]", + ipv6_addr_str); + tor_free(ipv6_addr_str); + } + } + SMARTLIST_FOREACH_BEGIN(envs, const char *, env_var) { set_environment_variable_in_smartlist(merged_env_vars, env_var, tor_free_, 1); @@ -1919,3 +1950,46 @@ managed_proxy_severity_parse(const char *severity) return -1; } + +/** Return the outbound address from the given <b>family</b>. Returns NULL if + * the user haven't specified a specific outbound address in either + * OutboundBindAddress or OutboundBindAddressPT. */ +STATIC const tor_addr_t * +managed_proxy_outbound_address(const or_options_t *options, sa_family_t family) +{ + tor_assert(options); + + const tor_addr_t *address = NULL; + int family_index; + + switch (family) { + case AF_INET: + family_index = 0; + break; + case AF_INET6: + family_index = 1; + break; + default: + /* LCOV_EXCL_START */ + tor_assert_unreached(); + return NULL; + /* LCOV_EXCL_STOP */ + } + + /* We start by checking if the user specified an address in + * OutboundBindAddressPT. */ + address = &options->OutboundBindAddresses[OUTBOUND_ADDR_PT][family_index]; + + if (! tor_addr_is_null(address)) + return address; + + /* We fallback to check if the user specified an address in + * OutboundBindAddress. */ + address = &options->OutboundBindAddresses[OUTBOUND_ADDR_ANY][family_index]; + + if (! tor_addr_is_null(address)) + return address; + + /* The user have not specified a preference for outgoing connections. */ + return NULL; +} diff --git a/src/feature/client/transports.h b/src/feature/client/transports.h index 1ed942c175..3aff1cb248 100644 --- a/src/feature/client/transports.h +++ b/src/feature/client/transports.h @@ -149,6 +149,8 @@ STATIC void managed_proxy_stderr_callback(process_t *, const char *, size_t); STATIC bool managed_proxy_exit_callback(process_t *, process_exit_code_t); STATIC int managed_proxy_severity_parse(const char *); +STATIC const tor_addr_t *managed_proxy_outbound_address(const or_options_t *, + sa_family_t); #endif /* defined(PT_PRIVATE) */ diff --git a/src/feature/control/control_bootstrap.c b/src/feature/control/control_bootstrap.c index d4f2adde81..d6dfdad94e 100644 --- a/src/feature/control/control_bootstrap.c +++ b/src/feature/control/control_bootstrap.c @@ -348,6 +348,18 @@ control_event_bootstrap_prob_or, (const char *warn, int reason, { int dowarn = 0; + if (! or_conn->potentially_used_for_bootstrapping) { + /* We never decided that this channel was a good match for one of our + * origin_circuit_t objects. That means that we probably launched it + * for somebody else, most likely in response to an EXTEND cell. + * + * Since EXTEND cells can contain arbitrarily broken descriptions of + * relays, a failure on this connection here won't necessarily indicate a + * bootstrapping problem. + */ + return; + } + if (or_conn->have_noted_bootstrap_problem) return; diff --git a/src/feature/dirauth/dirvote.c b/src/feature/dirauth/dirvote.c index 8676df76ab..f56d3ef0a0 100644 --- a/src/feature/dirauth/dirvote.c +++ b/src/feature/dirauth/dirvote.c @@ -4,6 +4,7 @@ /* See LICENSE for licensing information */ #define DIRVOTE_PRIVATE + #include "core/or/or.h" #include "app/config/config.h" #include "app/config/resolve_addr.h" @@ -4177,8 +4178,8 @@ dirvote_dirreq_get_status_vote(const char *url, smartlist_t *items, /** Get the best estimate of a router's bandwidth for dirauth purposes, * preferring measured to advertised values if available. */ -static uint32_t -dirserv_get_bandwidth_for_router_kb(const routerinfo_t *ri) +MOCK_IMPL(uint32_t,dirserv_get_bandwidth_for_router_kb, + (const routerinfo_t *ri)) { uint32_t bw_kb = 0; /* @@ -4207,33 +4208,73 @@ dirserv_get_bandwidth_for_router_kb(const routerinfo_t *ri) return bw_kb; } -/** Helper for sorting: compares two routerinfos first by address, and then by - * descending order of "usefulness". (An authority is more useful than a - * non-authority; a running router is more useful than a non-running router; - * and a router with more bandwidth is more useful than one with less.) +/** + * Helper: compare the address of family `family` in `a` with the address in + * `b`. The family must be one of `AF_INET` and `AF_INET6`. **/ static int -compare_routerinfo_by_ip_and_bw_(const void **a, const void **b) +compare_routerinfo_addrs_by_family(const routerinfo_t *a, + const routerinfo_t *b, + int family) +{ + const tor_addr_t *addr1 = (family==AF_INET) ? &a->ipv4_addr : &a->ipv6_addr; + const tor_addr_t *addr2 = (family==AF_INET) ? &b->ipv4_addr : &b->ipv6_addr; + const int maskbits = (family==AF_INET) ? 32 : 64; + return tor_addr_compare_masked(addr1, addr2, maskbits, CMP_EXACT); +} + +/** Helper for sorting: compares two ipv4 routerinfos first by ipv4 address, + * and then by descending order of "usefulness" + * (see compare_routerinfo_usefulness) + **/ +STATIC int +compare_routerinfo_by_ipv4(const void **a, const void **b) +{ + const routerinfo_t *first = *(const routerinfo_t **)a; + const routerinfo_t *second = *(const routerinfo_t **)b; + int comparison = compare_routerinfo_addrs_by_family(first, second, AF_INET); + if (comparison == 0) { + // If addresses are equal, use other comparison criteria + return compare_routerinfo_usefulness(first, second); + } else { + return comparison; + } +} + +/** Helper for sorting: compares two ipv6 routerinfos first by ipv6 address, + * and then by descending order of "usefulness" + * (see compare_routerinfo_usefulness) + **/ +STATIC int +compare_routerinfo_by_ipv6(const void **a, const void **b) +{ + const routerinfo_t *first = *(const routerinfo_t **)a; + const routerinfo_t *second = *(const routerinfo_t **)b; + int comparison = compare_routerinfo_addrs_by_family(first, second, AF_INET6); + // If addresses are equal, use other comparison criteria + if (comparison == 0) + return compare_routerinfo_usefulness(first, second); + else + return comparison; +} + +/** +* Compare routerinfos by descending order of "usefulness" : +* An authority is more useful than a non-authority; a running router is +* more useful than a non-running router; and a router with more bandwidth +* is more useful than one with less. +**/ +STATIC int +compare_routerinfo_usefulness(const routerinfo_t *first, + const routerinfo_t *second) { - routerinfo_t *first = *(routerinfo_t **)a, *second = *(routerinfo_t **)b; int first_is_auth, second_is_auth; - uint32_t bw_kb_first, bw_kb_second; const node_t *node_first, *node_second; int first_is_running, second_is_running; - uint32_t first_ipv4h = tor_addr_to_ipv4h(&first->ipv4_addr); - uint32_t second_ipv4h = tor_addr_to_ipv4h(&second->ipv4_addr); - - /* we return -1 if first should appear before second... that is, - * if first is a better router. */ - if (first_ipv4h < second_ipv4h) - return -1; - else if (first_ipv4h > second_ipv4h) - return 1; - + uint32_t bw_kb_first, bw_kb_second; /* Potentially, this next bit could cause k n lg n memeq calls. But in * reality, we will almost never get here, since addresses will usually be * different. */ - first_is_auth = router_digest_is_trusted_dir(first->cache_info.identity_digest); second_is_auth = @@ -4248,7 +4289,6 @@ compare_routerinfo_by_ip_and_bw_(const void **a, const void **b) node_second = node_get_by_id(second->cache_info.identity_digest); first_is_running = node_first && node_first->is_running; second_is_running = node_second && node_second->is_running; - if (first_is_running && !second_is_running) return -1; else if (!first_is_running && second_is_running) @@ -4269,40 +4309,89 @@ compare_routerinfo_by_ip_and_bw_(const void **a, const void **b) DIGEST_LEN); } -/** Given a list of routerinfo_t in <b>routers</b>, return a new digestmap_t - * whose keys are the identity digests of those routers that we're going to - * exclude for Sybil-like appearance. */ -static digestmap_t * -get_possible_sybil_list(const smartlist_t *routers) +/** Given a list of routerinfo_t in <b>routers</b> that all use the same + * IP version, specified in <b>family</b>, return a new digestmap_t whose keys + * are the identity digests of those routers that we're going to exclude for + * Sybil-like appearance. + */ +STATIC digestmap_t * +get_sybil_list_by_ip_version(const smartlist_t *routers, sa_family_t family) { const dirauth_options_t *options = dirauth_get_options(); - digestmap_t *omit_as_sybil; + digestmap_t *omit_as_sybil = digestmap_new(); smartlist_t *routers_by_ip = smartlist_new(); - tor_addr_t last_addr = TOR_ADDR_NULL; - int addr_count; + int addr_count = 0; + routerinfo_t *last_ri = NULL; /* Allow at most this number of Tor servers on a single IP address, ... */ int max_with_same_addr = options->AuthDirMaxServersPerAddr; if (max_with_same_addr <= 0) max_with_same_addr = INT_MAX; smartlist_add_all(routers_by_ip, routers); - smartlist_sort(routers_by_ip, compare_routerinfo_by_ip_and_bw_); - omit_as_sybil = digestmap_new(); + if (family == AF_INET6) + smartlist_sort(routers_by_ip, compare_routerinfo_by_ipv6); + else + smartlist_sort(routers_by_ip, compare_routerinfo_by_ipv4); - addr_count = 0; SMARTLIST_FOREACH_BEGIN(routers_by_ip, routerinfo_t *, ri) { - if (!tor_addr_eq(&last_addr, &ri->ipv4_addr)) { - tor_addr_copy(&last_addr, &ri->ipv4_addr); + bool addrs_equal; + if (last_ri) + addrs_equal = !compare_routerinfo_addrs_by_family(last_ri, ri, family); + else + addrs_equal = false; + + if (! addrs_equal) { + last_ri = ri; addr_count = 1; } else if (++addr_count > max_with_same_addr) { digestmap_set(omit_as_sybil, ri->cache_info.identity_digest, ri); } } SMARTLIST_FOREACH_END(ri); - smartlist_free(routers_by_ip); return omit_as_sybil; } +/** Given a list of routerinfo_t in <b>routers</b>, return a new digestmap_t + * whose keys are the identity digests of those routers that we're going to + * exclude for Sybil-like appearance. */ +STATIC digestmap_t * +get_all_possible_sybil(const smartlist_t *routers) +{ + smartlist_t *routers_ipv6, *routers_ipv4; + routers_ipv6 = smartlist_new(); + routers_ipv4 = smartlist_new(); + digestmap_t *omit_as_sybil_ipv4; + digestmap_t *omit_as_sybil_ipv6; + digestmap_t *omit_as_sybil = digestmap_new(); + // Sort the routers in two lists depending on their IP version + SMARTLIST_FOREACH_BEGIN(routers, routerinfo_t *, ri) { + // If the router has an IPv6 address + if (tor_addr_family(&(ri->ipv6_addr)) == AF_INET6) { + smartlist_add(routers_ipv6, ri); + } + // If the router has an IPv4 address + if (tor_addr_family(&(ri->ipv4_addr)) == AF_INET) { + smartlist_add(routers_ipv4, ri); + } + } SMARTLIST_FOREACH_END(ri); + omit_as_sybil_ipv4 = get_sybil_list_by_ip_version(routers_ipv4, AF_INET); + omit_as_sybil_ipv6 = get_sybil_list_by_ip_version(routers_ipv6, AF_INET6); + + // Add all possible sybils to the common digestmap + DIGESTMAP_FOREACH (omit_as_sybil_ipv4, sybil_id, routerinfo_t *, ri) { + digestmap_set(omit_as_sybil, ri->cache_info.identity_digest, ri); + } DIGESTMAP_FOREACH_END; + DIGESTMAP_FOREACH (omit_as_sybil_ipv6, sybil_id, routerinfo_t *, ri) { + digestmap_set(omit_as_sybil, ri->cache_info.identity_digest, ri); + } DIGESTMAP_FOREACH_END; + // Clean the temp variables + smartlist_free(routers_ipv4); + smartlist_free(routers_ipv6); + digestmap_free(omit_as_sybil_ipv4, NULL); + digestmap_free(omit_as_sybil_ipv6, NULL); + // Return the digestmap: it now contains all the possible sybils + return omit_as_sybil; +} /** Given a platform string as in a routerinfo_t (possibly null), return a * newly allocated version string for a networkstatus document, or NULL if the * platform doesn't give a Tor version. */ @@ -4477,7 +4566,6 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH; networkstatus_voter_info_t *voter = NULL; vote_timing_t timing; - digestmap_t *omit_as_sybil = NULL; const int vote_on_reachability = running_long_enough_to_decide_unreachable(); smartlist_t *microdescriptors = NULL; smartlist_t *bw_file_headers = NULL; @@ -4547,19 +4635,16 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, routers_make_ed_keys_unique(routers); /* After this point, don't use rl->routers; use 'routers' instead. */ routers_sort_by_identity(routers); - omit_as_sybil = get_possible_sybil_list(routers); - - DIGESTMAP_FOREACH(omit_as_sybil, sybil_id, void *, ignore) { - (void) ignore; + /* Get a digestmap of possible sybil routers, IPv4 or IPv6 */ + digestmap_t *omit_as_sybil = get_all_possible_sybil(routers); + DIGESTMAP_FOREACH (omit_as_sybil, sybil_id, void *, ignore) { + (void)ignore; rep_hist_make_router_pessimal(sybil_id, now); - } DIGESTMAP_FOREACH_END; - + } DIGESTMAP_FOREACH_END /* Count how many have measured bandwidths so we know how to assign flags; * this must come before dirserv_compute_performance_thresholds() */ dirserv_count_measured_bws(routers); - dirserv_compute_performance_thresholds(omit_as_sybil); - routerstatuses = smartlist_new(); microdescriptors = smartlist_new(); @@ -4587,7 +4672,6 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, ri->cache_info.signing_key_cert->signing_key.pubkey, ED25519_PUBKEY_LEN); } - if (digestmap_get(omit_as_sybil, ri->cache_info.identity_digest)) clear_status_flags_on_sybil(rs); diff --git a/src/feature/dirauth/dirvote.h b/src/feature/dirauth/dirvote.h index 9cc87489b4..a4f1b8bfe9 100644 --- a/src/feature/dirauth/dirvote.h +++ b/src/feature/dirauth/dirvote.h @@ -183,6 +183,8 @@ dirvote_add_signatures(const char *detached_signatures_body, /* Item access */ MOCK_DECL(const char*, dirvote_get_pending_consensus, (consensus_flavor_t flav)); +MOCK_DECL(uint32_t,dirserv_get_bandwidth_for_router_kb, + (const routerinfo_t *ri)); MOCK_DECL(const char*, dirvote_get_pending_detached_signatures, (void)); const cached_dir_t *dirvote_get_vote(const char *fp, int flags); @@ -234,6 +236,22 @@ int networkstatus_add_detached_signatures(networkstatus_t *target, const char *source, int severity, const char **msg_out); +STATIC int +compare_routerinfo_usefulness(const routerinfo_t *first, + const routerinfo_t *second); +STATIC +int compare_routerinfo_by_ipv4(const void **a, const void **b); + +STATIC +int compare_routerinfo_by_ipv6(const void **a, const void **b); + +STATIC +digestmap_t * get_sybil_list_by_ip_version( + const smartlist_t *routers, sa_family_t family); + +STATIC +digestmap_t * get_all_possible_sybil(const smartlist_t *routers); + STATIC char *networkstatus_get_detached_signatures(smartlist_t *consensuses); STATIC microdesc_t *dirvote_create_microdescriptor(const routerinfo_t *ri, diff --git a/src/feature/dircache/dircache_stub.c b/src/feature/dircache/dircache_stub.c index 87811597d1..725c44bd4d 100644 --- a/src/feature/dircache/dircache_stub.c +++ b/src/feature/dircache/dircache_stub.c @@ -14,6 +14,7 @@ #include "feature/dircache/dirserv.h" #include "feature/dircommon/dir_connection_st.h" +DISABLE_GCC_WARNING("-Wmissing-noreturn") int directory_handle_command(dir_connection_t *conn) { @@ -29,6 +30,7 @@ connection_dirserv_flushed_some(dir_connection_t *conn) tor_assert_nonfatal_unreached_once(); return -1; } +ENABLE_GCC_WARNING("-Wmissing-noreturn") void dir_conn_clear_spool(dir_connection_t *conn) diff --git a/src/feature/dirclient/dirclient.c b/src/feature/dirclient/dirclient.c index f088ef8283..74e68ac6be 100644 --- a/src/feature/dirclient/dirclient.c +++ b/src/feature/dirclient/dirclient.c @@ -1987,7 +1987,7 @@ dirclient_dump_total_dls(void) { const or_options_t *options = get_options(); for (int bootstrapped = 0; bootstrapped < 2; ++bootstrapped) { - bool first_time = true; + smartlist_t *lines = smartlist_new(); for (int i=0; i < DIR_PURPOSE_MAX_; ++i) { uint64_t n = total_dl[i][bootstrapped]; if (n == 0) @@ -1995,15 +1995,19 @@ dirclient_dump_total_dls(void) if (options->SafeLogging_ != SAFELOG_SCRUB_NONE && purpose_needs_anonymity(i, ROUTER_PURPOSE_GENERAL, NULL)) continue; - if (first_time) { - log_notice(LD_NET, - "While %sbootstrapping, fetched this many bytes: ", - bootstrapped?"not ":""); - first_time = false; - } - log_notice(LD_NET, " %"PRIu64" (%s)", - n, dir_conn_purpose_to_string(i)); + smartlist_add_asprintf(lines, "%"PRIu64" (%s)", + n, dir_conn_purpose_to_string(i)); + } + + if (smartlist_len(lines) > 0) { + char *log_line = smartlist_join_strings(lines, "; ", 0, NULL); + log_notice(LD_NET, "While %sbootstrapping, fetched this many bytes: %s", + bootstrapped?"not ":"", log_line); + tor_free(log_line); + + SMARTLIST_FOREACH(lines, char *, s, tor_free(s)); } + smartlist_free(lines); } } @@ -2505,9 +2509,12 @@ handle_response_fetch_desc(dir_connection_t *conn, } if (status_code != 200) { int dir_okay = status_code == 404 || - (status_code == 400 && !strcmp(reason, "Servers unavailable.")); + (status_code == 400 && !strcmp(reason, "Servers unavailable.")) || + status_code == 301; /* 404 means that it didn't have them; no big deal. - * Older (pre-0.1.1.8) servers said 400 Servers unavailable instead. */ + * Older (pre-0.1.1.8) servers said 400 Servers unavailable instead. + * 301 is considered as an error since Tor does not follow redirects, + * which means we failed to reach the server we wanted. */ log_fn(dir_okay ? LOG_INFO : LOG_WARN, LD_DIR, "Received http status code %d (%s) from server %s " "while fetching \"/tor/server/%s\". I'll try again soon.", diff --git a/src/feature/hs/hs_circuitmap.c b/src/feature/hs/hs_circuitmap.c index 466a02de39..e46b008a5c 100644 --- a/src/feature/hs/hs_circuitmap.c +++ b/src/feature/hs/hs_circuitmap.c @@ -275,7 +275,7 @@ hs_circuitmap_get_or_circuit(hs_token_type_t type, /** Public function: Return v2 and v3 introduction circuit to this relay. * Always return a newly allocated list for which it is the caller's - * responsability to free it. */ + * responsibility to free it. */ smartlist_t * hs_circuitmap_get_all_intro_circ_relay_side(void) { diff --git a/src/feature/hs/hs_service.c b/src/feature/hs/hs_service.c index 3e264b4686..f2a8898b2c 100644 --- a/src/feature/hs/hs_service.c +++ b/src/feature/hs/hs_service.c @@ -1587,7 +1587,7 @@ setup_desc_intro_point(const ed25519_keypair_t *signing_kp, memcpy(&desc_ip->onion_key, &ip->onion_key, sizeof(desc_ip->onion_key)); /* Key and certificate material. */ - desc_ip->auth_key_cert = tor_cert_create(signing_kp, + desc_ip->auth_key_cert = tor_cert_create_ed25519(signing_kp, CERT_TYPE_AUTH_HS_IP_KEY, &ip->auth_key_kp.pubkey, nearest_hour, @@ -1638,7 +1638,7 @@ setup_desc_intro_point(const ed25519_keypair_t *signing_kp, ed25519_public_key_from_curve25519_public_key(&ed25519_pubkey, &ip->enc_key_kp.pubkey, 0); - desc_ip->enc_key_cert = tor_cert_create(signing_kp, + desc_ip->enc_key_cert = tor_cert_create_ed25519(signing_kp, CERT_TYPE_CROSS_HS_IP_KEYS, &ed25519_pubkey, nearest_hour, HS_DESC_CERT_LIFETIME, @@ -1712,12 +1712,13 @@ build_desc_signing_key_cert(hs_service_descriptor_t *desc, time_t now) /* Fresh certificate for the signing key. */ plaintext->signing_key_cert = - tor_cert_create(&desc->blinded_kp, CERT_TYPE_SIGNING_HS_DESC, + tor_cert_create_ed25519(&desc->blinded_kp, CERT_TYPE_SIGNING_HS_DESC, &desc->signing_kp.pubkey, now, HS_DESC_CERT_LIFETIME, CERT_FLAG_INCLUDE_SIGNING_KEY); /* If the cert creation fails, the descriptor encoding will fail and thus * ultimately won't be uploaded. We'll get a stack trace to help us learn - * where the call came from and the tor_cert_create() will log the error. */ + * where the call came from and the tor_cert_create_ed25519() will log the + * error. */ tor_assert_nonfatal(plaintext->signing_key_cert); } diff --git a/src/feature/hs_common/shared_random_client.c b/src/feature/hs_common/shared_random_client.c index 3f46321be4..c2ea5afe32 100644 --- a/src/feature/hs_common/shared_random_client.c +++ b/src/feature/hs_common/shared_random_client.c @@ -274,10 +274,6 @@ sr_state_get_start_time_of_current_protocol_run(void) protocol run */ time_t time_elapsed_since_start_of_run = curr_round_slot * voting_interval; - log_debug(LD_GENERAL, "Current SRV proto run: Start of current round: %u. " - "Time elapsed: %u (%d)", (unsigned) beginning_of_curr_round, - (unsigned) time_elapsed_since_start_of_run, voting_interval); - return beginning_of_curr_round - time_elapsed_since_start_of_run; } diff --git a/src/feature/keymgt/loadkey.c b/src/feature/keymgt/loadkey.c index 7958bd964f..9b8f2f018a 100644 --- a/src/feature/keymgt/loadkey.c +++ b/src/feature/keymgt/loadkey.c @@ -661,7 +661,7 @@ ed_key_init_from_file(const char *fname, uint32_t flags, uint32_t cert_flags = 0; if (flags & INIT_ED_KEY_INCLUDE_SIGNING_KEY_IN_CERT) cert_flags |= CERT_FLAG_INCLUDE_SIGNING_KEY; - cert = tor_cert_create(signing_key, cert_type, + cert = tor_cert_create_ed25519(signing_key, cert_type, &keypair->pubkey, now, lifetime, cert_flags); @@ -739,7 +739,7 @@ ed_key_new(const ed25519_keypair_t *signing_key, uint32_t cert_flags = 0; if (flags & INIT_ED_KEY_INCLUDE_SIGNING_KEY_IN_CERT) cert_flags |= CERT_FLAG_INCLUDE_SIGNING_KEY; - tor_cert_t *cert = tor_cert_create(signing_key, cert_type, + tor_cert_t *cert = tor_cert_create_ed25519(signing_key, cert_type, &keypair->pubkey, now, lifetime, cert_flags); diff --git a/src/feature/nodelist/dirlist.c b/src/feature/nodelist/dirlist.c index cd2921e653..f6e4662a0f 100644 --- a/src/feature/nodelist/dirlist.c +++ b/src/feature/nodelist/dirlist.c @@ -236,8 +236,8 @@ mark_all_dirservers_up(smartlist_t *server_list) /** Return true iff <b>digest</b> is the digest of the identity key of a * trusted directory matching at least one bit of <b>type</b>. If <b>type</b> * is zero (NO_DIRINFO), or ALL_DIRINFO, any authority is okay. */ -int -router_digest_is_trusted_dir_type(const char *digest, dirinfo_type_t type) +MOCK_IMPL(int, router_digest_is_trusted_dir_type, + (const char *digest, dirinfo_type_t type)) { if (!trusted_dir_servers) return 0; diff --git a/src/feature/nodelist/dirlist.h b/src/feature/nodelist/dirlist.h index c9310ff357..ae3debf4e5 100644 --- a/src/feature/nodelist/dirlist.h +++ b/src/feature/nodelist/dirlist.h @@ -25,13 +25,14 @@ int router_digest_is_fallback_dir(const char *digest); MOCK_DECL(dir_server_t *, trusteddirserver_get_by_v3_auth_digest, (const char *d)); +MOCK_DECL(int, router_digest_is_trusted_dir_type, + (const char *digest, dirinfo_type_t type)); + bool router_addr_is_trusted_dir_type(const tor_addr_t *addr, dirinfo_type_t type); #define router_addr_is_trusted_dir(d) \ router_addr_is_trusted_dir_type((d), NO_DIRINFO) -int router_digest_is_trusted_dir_type(const char *digest, - dirinfo_type_t type); #define router_digest_is_trusted_dir(d) \ router_digest_is_trusted_dir_type((d), NO_DIRINFO) diff --git a/src/feature/nodelist/networkstatus.c b/src/feature/nodelist/networkstatus.c index 9210518de0..ece3c9e059 100644 --- a/src/feature/nodelist/networkstatus.c +++ b/src/feature/nodelist/networkstatus.c @@ -2444,7 +2444,12 @@ networkstatus_getinfo_by_purpose(const char *purpose_string, time_t now) return answer; } -/* DOCDOC get_net_param_from_list */ +/** + * Search through a smartlist of "key=int32" strings for a value beginning + * with "param_name=". If one is found, clip it to be between min_val and + * max_val inclusive and return it. If one is not found, return + * default_val. + ***/ static int32_t get_net_param_from_list(smartlist_t *net_params, const char *param_name, int32_t default_val, int32_t min_val, int32_t max_val) diff --git a/src/feature/nodelist/nodelist.c b/src/feature/nodelist/nodelist.c index 7edc1fc51c..c9928d2f9b 100644 --- a/src/feature/nodelist/nodelist.c +++ b/src/feature/nodelist/nodelist.c @@ -1947,7 +1947,7 @@ node_get_curve25519_onion_key(const node_t *node) /* Return a newly allocacted RSA onion public key taken from the given node. * * Return NULL if node is NULL or no RSA onion public key can be found. It is - * the caller responsability to free the returned object. */ + * the caller responsibility to free the returned object. */ crypto_pk_t * node_get_rsa_onion_key(const node_t *node) { diff --git a/src/feature/nodelist/torcert.c b/src/feature/nodelist/torcert.c index 89cc9c88fb..dc36626122 100644 --- a/src/feature/nodelist/torcert.c +++ b/src/feature/nodelist/torcert.c @@ -37,11 +37,11 @@ #include "core/or/or_handshake_certs_st.h" -/** Helper for tor_cert_create(): signs any 32 bytes, not just an ed25519 - * key. +/** As tor_cert_create(), but accept an arbitrary signed_key_type as the + * subject key -- not just an ed25519 key. */ -static tor_cert_t * -tor_cert_sign_impl(const ed25519_keypair_t *signing_key, +tor_cert_t * +tor_cert_create_raw(const ed25519_keypair_t *signing_key, uint8_t cert_type, uint8_t signed_key_type, const uint8_t signed_key_info[32], @@ -128,13 +128,13 @@ tor_cert_sign_impl(const ed25519_keypair_t *signing_key, * the public part of <b>signing_key</b> in the certificate. */ tor_cert_t * -tor_cert_create(const ed25519_keypair_t *signing_key, +tor_cert_create_ed25519(const ed25519_keypair_t *signing_key, uint8_t cert_type, const ed25519_public_key_t *signed_key, time_t now, time_t lifetime, uint32_t flags) { - return tor_cert_sign_impl(signing_key, cert_type, + return tor_cert_create_raw(signing_key, cert_type, SIGNED_KEY_TYPE_ED25519, signed_key->pubkey, now, lifetime, flags); } diff --git a/src/feature/nodelist/torcert.h b/src/feature/nodelist/torcert.h index f8fba2b794..3314ee2550 100644 --- a/src/feature/nodelist/torcert.h +++ b/src/feature/nodelist/torcert.h @@ -11,7 +11,9 @@ #include "lib/crypt_ops/crypto_ed25519.h" -#define SIGNED_KEY_TYPE_ED25519 0x01 +#define SIGNED_KEY_TYPE_ED25519 0x01 +#define SIGNED_KEY_TYPE_SHA256_OF_RSA 0x02 +#define SIGNED_KEY_TYPE_SHA256_OF_X509 0x03 #define CERT_TYPE_ID_SIGNING 0x04 #define CERT_TYPE_SIGNING_LINK 0x05 @@ -56,11 +58,17 @@ typedef struct tor_cert_st { struct tor_tls_t; -tor_cert_t *tor_cert_create(const ed25519_keypair_t *signing_key, +tor_cert_t *tor_cert_create_ed25519(const ed25519_keypair_t *signing_key, uint8_t cert_type, const ed25519_public_key_t *signed_key, time_t now, time_t lifetime, uint32_t flags); +tor_cert_t * tor_cert_create_raw(const ed25519_keypair_t *signing_key, + uint8_t cert_type, + uint8_t signed_key_type, + const uint8_t signed_key_info[32], + time_t now, time_t lifetime, + uint32_t flags); tor_cert_t *tor_cert_parse(const uint8_t *cert, size_t certlen); diff --git a/src/feature/relay/circuitbuild_relay.c b/src/feature/relay/circuitbuild_relay.c index 64f3c341ae..289a5be557 100644 --- a/src/feature/relay/circuitbuild_relay.c +++ b/src/feature/relay/circuitbuild_relay.c @@ -475,6 +475,7 @@ circuit_extend(struct cell_t *cell, struct circuit_t *circ) &ec.ed_pubkey, ipv4_valid ? &ec.orport_ipv4.addr : NULL, ipv6_valid ? &ec.orport_ipv6.addr : NULL, + false, &msg, &should_launch); diff --git a/src/feature/relay/router.c b/src/feature/relay/router.c index 11847a2616..5ca21964b6 100644 --- a/src/feature/relay/router.c +++ b/src/feature/relay/router.c @@ -2607,6 +2607,10 @@ check_descriptor_bandwidth_changed(time_t now) } } +// This function can be "noreturn" if relay mode is disabled and +// ALL_BUGS_ARE_FATAL is set. +DISABLE_GCC_WARNING("-Wmissing-noreturn") + /** Note at log level severity that our best guess of address has changed from * <b>prev</b> to <b>cur</b>. */ void @@ -2636,6 +2640,7 @@ log_addr_has_changed(int severity, "Guessed our IP address as %s (source: %s).", addrbuf_cur, source); } +ENABLE_GCC_WARNING("-Wmissing-noreturn") /** Check whether our own address has changed versus the one we have in our * current descriptor. @@ -3570,7 +3575,7 @@ router_set_rsa_onion_pkey(const crypto_pk_t *pk, char **onion_pkey_out, } /* From an ASN-1 encoded onion pkey, return a newly allocated RSA key object. - * It is the caller responsability to free the returned object. + * It is the caller's responsibility to free the returned object. * * Return NULL if the pkey is NULL, malformed or if the length is 0. */ crypto_pk_t * diff --git a/src/feature/relay/routerkeys.c b/src/feature/relay/routerkeys.c index 744a73d936..116f0b4e3d 100644 --- a/src/feature/relay/routerkeys.c +++ b/src/feature/relay/routerkeys.c @@ -387,12 +387,10 @@ generate_ed_link_cert(const or_options_t *options, time_t now, return 0; } - ed25519_public_key_t dummy_key; - memcpy(dummy_key.pubkey, digests->d[DIGEST_SHA256], DIGEST256_LEN); - - link_cert = tor_cert_create(get_master_signing_keypair(), + link_cert = tor_cert_create_raw(get_master_signing_keypair(), CERT_TYPE_SIGNING_LINK, - &dummy_key, + SIGNED_KEY_TYPE_SHA256_OF_X509, + (const uint8_t*)digests->d[DIGEST_SHA256], now, options->TestingLinkCertLifetime, 0); @@ -466,7 +464,7 @@ init_mock_ed_keys(const crypto_pk_t *rsa_identity_key) MAKEKEY(master_signing_key); MAKEKEY(current_auth_key); #define MAKECERT(cert, signing, signed_, type, flags) \ - cert = tor_cert_create(signing, \ + cert = tor_cert_create_ed25519(signing, \ type, \ &signed_->pubkey, \ time(NULL), 86400, \ @@ -699,8 +697,8 @@ make_ntor_onion_key_crosscert(const curve25519_keypair_t *onion_key, onion_key) < 0) goto end; - cert = tor_cert_create(&ed_onion_key, CERT_TYPE_ONION_ID, master_id_key, - now, lifetime, 0); + cert = tor_cert_create_ed25519(&ed_onion_key, CERT_TYPE_ONION_ID, + master_id_key, now, lifetime, 0); end: memwipe(&ed_onion_key, 0, sizeof(ed_onion_key)); diff --git a/src/lib/fs/path.c b/src/lib/fs/path.c index 1a15969419..2eef4bded7 100644 --- a/src/lib/fs/path.c +++ b/src/lib/fs/path.c @@ -598,6 +598,12 @@ tor_glob(const char *pattern) return NULL; } + // #40141: workaround for bug in glibc < 2.19 where patterns ending in path + // separator match files and folders instead of folders only + size_t pattern_len = strlen(pattern); + bool dir_only = has_glob(pattern) && + pattern_len > 0 && pattern[pattern_len-1] == *PATH_SEPARATOR; + result = smartlist_new(); size_t i; for (i = 0; i < matches.gl_pathc; i++) { @@ -606,7 +612,12 @@ tor_glob(const char *pattern) if (len > 0 && match[len-1] == *PATH_SEPARATOR) { match[len-1] = '\0'; } - smartlist_add(result, match); + + if (!dir_only || (dir_only && is_dir(file_status(match)))) { + smartlist_add(result, match); + } else { + tor_free(match); + } } globfree(&matches); #else diff --git a/src/lib/log/log.c b/src/lib/log/log.c index cd848fdd73..12e4dbaaa2 100644 --- a/src/lib/log/log.c +++ b/src/lib/log/log.c @@ -51,10 +51,6 @@ #include "lib/fdio/fdio.h" #include "lib/cc/ctassert.h" -#ifdef HAVE_ANDROID_LOG_H -#include <android/log.h> -#endif // HAVE_ANDROID_LOG_H. - /** @{ */ /** The string we stick at the end of a log message when it is too long, * and its length. */ @@ -78,8 +74,6 @@ typedef struct logfile_t { int needs_close; /**< Boolean: true if the stream gets closed on shutdown. */ int is_temporary; /**< Boolean: close after initializing logging subsystem.*/ int is_syslog; /**< Boolean: send messages to syslog. */ - int is_android; /**< Boolean: send messages to Android's log subsystem. */ - char *android_tag; /**< Identity Tag used in Android's log subsystem. */ log_callback callback; /**< If not NULL, send messages to this function. */ log_severity_list_t *severities; /**< Which severity of messages should we * log for each log domain? */ @@ -126,33 +120,6 @@ should_log_function_name(log_domain_mask_t domain, int severity) } } -#ifdef HAVE_ANDROID_LOG_H -/** Helper function to convert Tor's log severity into the matching - * Android log priority. - */ -static int -severity_to_android_log_priority(int severity) -{ - switch (severity) { - case LOG_DEBUG: - return ANDROID_LOG_VERBOSE; - case LOG_INFO: - return ANDROID_LOG_DEBUG; - case LOG_NOTICE: - return ANDROID_LOG_INFO; - case LOG_WARN: - return ANDROID_LOG_WARN; - case LOG_ERR: - return ANDROID_LOG_ERROR; - default: - // LCOV_EXCL_START - raw_assert(0); - return 0; - // LCOV_EXCL_STOP - } -} -#endif /* defined(HAVE_ANDROID_LOG_H) */ - /** A mutex to guard changes to logfiles and logging. */ static tor_mutex_t log_mutex; /** True iff we have initialized log_mutex */ @@ -475,13 +442,13 @@ pending_log_message_free_(pending_log_message_t *msg) } /** Helper function: returns true iff the log file, given in <b>lf</b>, is - * handled externally via the system log API, the Android logging API, or is an + * handled externally via the system log API, or is an * external callback function. */ static inline int logfile_is_external(const logfile_t *lf) { raw_assert(lf); - return lf->is_syslog || lf->is_android || lf->callback; + return lf->is_syslog || lf->callback; } /** Return true iff <b>lf</b> would like to receive a message with the @@ -537,11 +504,6 @@ logfile_deliver(logfile_t *lf, const char *buf, size_t msg_len, syslog(severity, "%s", msg_after_prefix); #endif /* defined(MAXLINE) */ #endif /* defined(HAVE_SYSLOG_H) */ - } else if (lf->is_android) { -#ifdef HAVE_ANDROID_LOG_H - int priority = severity_to_android_log_priority(severity); - __android_log_write(priority, lf->android_tag, msg_after_prefix); -#endif // HAVE_ANDROID_LOG_H. } else if (lf->callback) { if (domain & LD_NOCB) { if (!*callbacks_deferred && pending_cb_messages) { @@ -677,7 +639,7 @@ tor_log_update_sigsafe_err_fds(void) n_fds = 1; for (lf = logfiles; lf; lf = lf->next) { - /* Don't try callback to the control port, syslogs, android logs, or any + /* Don't try callback to the control port, syslogs, or any * other non-file descriptor log: We can't call arbitrary functions from a * signal handler. */ @@ -775,7 +737,6 @@ log_free_(logfile_t *victim) return; tor_free(victim->severities); tor_free(victim->filename); - tor_free(victim->android_tag); tor_free(victim); } @@ -1247,39 +1208,6 @@ add_syslog_log(const log_severity_list_t *severity, } #endif /* defined(HAVE_SYSLOG_H) */ -#ifdef HAVE_ANDROID_LOG_H -/** - * Add a log handler to send messages to the Android platform log facility. - */ -int -add_android_log(const log_severity_list_t *severity, - const char *android_tag) -{ - logfile_t *lf = NULL; - - lf = tor_malloc_zero(sizeof(logfile_t)); - lf->fd = -1; - lf->severities = tor_memdup(severity, sizeof(log_severity_list_t)); - lf->filename = tor_strdup("<android>"); - lf->is_android = 1; - - if (android_tag == NULL) - lf->android_tag = tor_strdup("Tor"); - else { - char buf[256]; - tor_snprintf(buf, sizeof(buf), "Tor-%s", android_tag); - lf->android_tag = tor_strdup(buf); - } - - LOCK_LOGS(); - lf->next = logfiles; - logfiles = lf; - log_global_min_severity_ = get_min_log_level(); - UNLOCK_LOGS(); - return 0; -} -#endif /* defined(HAVE_ANDROID_LOG_H) */ - /** If <b>level</b> is a valid log severity, return the corresponding * numeric value. Otherwise, return -1. */ int @@ -1457,8 +1385,7 @@ parse_log_severity_config(const char **cfg_ptr, if (!strcasecmpstart(cfg, "file") || !strcasecmpstart(cfg, "stderr") || !strcasecmpstart(cfg, "stdout") || - !strcasecmpstart(cfg, "syslog") || - !strcasecmpstart(cfg, "android")) { + !strcasecmpstart(cfg, "syslog")) { goto done; } if (got_an_unqualified_range > 1) diff --git a/src/lib/log/log.h b/src/lib/log/log.h index aafbf9be2f..fb8a5a28a6 100644 --- a/src/lib/log/log.h +++ b/src/lib/log/log.h @@ -175,10 +175,6 @@ MOCK_DECL(int, add_file_log,(const log_severity_list_t *severity, int add_syslog_log(const log_severity_list_t *severity, const char* syslog_identity_tag); #endif // HAVE_SYSLOG_H. -#ifdef HAVE_ANDROID_LOG_H -int add_android_log(const log_severity_list_t *severity, - const char *android_identity_tag); -#endif // HAVE_ANDROID_LOG_H. int add_callback_log(const log_severity_list_t *severity, log_callback cb); typedef void (*pending_callback_callback)(void); void logs_set_pending_callback_callback(pending_callback_callback cb); diff --git a/src/lib/net/address.c b/src/lib/net/address.c index 5a32533610..ea6c29db9f 100644 --- a/src/lib/net/address.c +++ b/src/lib/net/address.c @@ -1731,8 +1731,8 @@ get_interface_address6,(int severity, sa_family_t family, tor_addr_t *addr)) /* Get a list of public or internal IPs in arbitrary order */ addrs = get_interface_address6_list(severity, family, 1); - /* Find the first non-internal address, or the last internal address - * Ideally, we want the default route, see #12377 for details */ + /* Find the first non-internal address, or the last internal address. + * Ideally, we want the default route; see #12377 for details. */ SMARTLIST_FOREACH_BEGIN(addrs, tor_addr_t *, a) { tor_addr_copy(addr, a); const bool is_internal = tor_addr_is_internal(a, 0); diff --git a/src/test/conf_examples/large_1/expected b/src/test/conf_examples/large_1/expected index 99a12ffc84..fcd19db3df 100644 --- a/src/test/conf_examples/large_1/expected +++ b/src/test/conf_examples/large_1/expected @@ -3,7 +3,6 @@ AccountingRule sum AccountingStart day 05:15 Address 128.66.8.8 AllowNonRFC953Hostnames 1 -AndroidIdentityTag droidy AutomapHostsOnResolve 1 AutomapHostsSuffixes .onions AvoidDiskWrites 1 @@ -111,7 +110,6 @@ NumDirectoryGuards 4 NumEntryGuards 5 NumPrimaryGuards 8 OfflineMasterKey 1 -OptimisticData 1 ORPort 2222 OutboundBindAddress 10.0.0.7 OutboundBindAddressExit 10.0.0.8 diff --git a/src/test/conf_examples/large_1/expected_no_dirauth b/src/test/conf_examples/large_1/expected_no_dirauth index 26a33bdc7c..4a19bc546c 100644 --- a/src/test/conf_examples/large_1/expected_no_dirauth +++ b/src/test/conf_examples/large_1/expected_no_dirauth @@ -3,7 +3,6 @@ AccountingRule sum AccountingStart day 05:15 Address 128.66.8.8 AllowNonRFC953Hostnames 1 -AndroidIdentityTag droidy AutomapHostsOnResolve 1 AutomapHostsSuffixes .onions AvoidDiskWrites 1 @@ -110,7 +109,6 @@ NumDirectoryGuards 4 NumEntryGuards 5 NumPrimaryGuards 8 OfflineMasterKey 1 -OptimisticData 1 ORPort 2222 OutboundBindAddress 10.0.0.7 OutboundBindAddressExit 10.0.0.8 diff --git a/src/test/conf_examples/large_1/torrc b/src/test/conf_examples/large_1/torrc index 20ddf00e16..3f5b1e179f 100644 --- a/src/test/conf_examples/large_1/torrc +++ b/src/test/conf_examples/large_1/torrc @@ -3,7 +3,6 @@ AccountingRule sum AccountingStart day 05:15 Address 128.66.8.8 AllowNonRFC953Hostnames 1 -AndroidIdentityTag droidy AutomapHostsOnResolve 1 AutomapHostsSuffixes .onions AvoidDiskWrites 1 diff --git a/src/test/hs_test_helpers.c b/src/test/hs_test_helpers.c index 5116fc7169..e9aafa4760 100644 --- a/src/test/hs_test_helpers.c +++ b/src/test/hs_test_helpers.c @@ -75,7 +75,8 @@ hs_helper_build_intro_point(const ed25519_keypair_t *signing_kp, time_t now, ret = ed25519_keypair_generate(&auth_kp, 0); tt_int_op(ret, OP_EQ, 0); } - ip->auth_key_cert = tor_cert_create(signing_kp, CERT_TYPE_AUTH_HS_IP_KEY, + ip->auth_key_cert = tor_cert_create_ed25519(signing_kp, + CERT_TYPE_AUTH_HS_IP_KEY, &auth_kp.pubkey, now, HS_DESC_CERT_LIFETIME, CERT_FLAG_INCLUDE_SIGNING_KEY); @@ -110,7 +111,8 @@ hs_helper_build_intro_point(const ed25519_keypair_t *signing_kp, time_t now, } ed25519_keypair_from_curve25519_keypair(&ed25519_kp, &signbit, &curve25519_kp); - cross_cert = tor_cert_create(signing_kp, CERT_TYPE_CROSS_HS_IP_KEYS, + cross_cert = tor_cert_create_ed25519(signing_kp, + CERT_TYPE_CROSS_HS_IP_KEYS, &ed25519_kp.pubkey, time(NULL), HS_DESC_CERT_LIFETIME, CERT_FLAG_INCLUDE_SIGNING_KEY); @@ -155,7 +157,7 @@ hs_helper_build_hs_desc_impl(unsigned int no_ip, sizeof(ed25519_public_key_t)); desc->plaintext_data.signing_key_cert = - tor_cert_create(&blinded_kp, CERT_TYPE_SIGNING_HS_DESC, + tor_cert_create_ed25519(&blinded_kp, CERT_TYPE_SIGNING_HS_DESC, &signing_kp->pubkey, now, 3600, CERT_FLAG_INCLUDE_SIGNING_KEY); tt_assert(desc->plaintext_data.signing_key_cert); diff --git a/src/test/include.am b/src/test/include.am index fe55991f82..cb3a498f74 100644 --- a/src/test/include.am +++ b/src/test/include.am @@ -171,6 +171,7 @@ src_test_test_SOURCES += \ src/test/test_crypto_rng.c \ src/test/test_data.c \ src/test/test_dir.c \ + src/test/test_dirvote.c \ src/test/test_dir_common.c \ src/test/test_dir_handle_get.c \ src/test/test_dispatch.c \ @@ -234,6 +235,7 @@ src_test_test_SOURCES += \ src/test/test_sendme.c \ src/test/test_shared_random.c \ src/test/test_socks.c \ + src/test/test_statefile.c \ src/test/test_stats.c \ src/test/test_status.c \ src/test/test_storagedir.c \ diff --git a/src/test/test.c b/src/test/test.c index 2961669c46..77aa6db975 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -709,6 +709,7 @@ struct testgroup_t testgroups[] = { { "dir/", dir_tests }, { "dir/auth/process_descs/", process_descs_tests }, { "dir/md/", microdesc_tests }, + { "dirauth/dirvote/", dirvote_tests}, { "dir/voting/flags/", voting_flags_tests }, { "dir/voting/schedule/", voting_schedule_tests }, { "dir_handle_get/", dir_handle_get_tests }, @@ -769,6 +770,7 @@ struct testgroup_t testgroups[] = { { "sendme/", sendme_tests }, { "shared-random/", sr_tests }, { "socks/", socks_tests }, + { "statefile/", statefile_tests }, { "stats/", stats_tests }, { "status/" , status_tests }, { "storagedir/", storagedir_tests }, diff --git a/src/test/test.h b/src/test/test.h index 18987719d0..bd3a4102f5 100644 --- a/src/test/test.h +++ b/src/test/test.h @@ -122,6 +122,7 @@ extern struct testcase_t crypto_rng_tests[]; extern struct testcase_t crypto_tests[]; extern struct testcase_t dir_handle_get_tests[]; extern struct testcase_t dir_tests[]; +extern struct testcase_t dirvote_tests[]; extern struct testcase_t dispatch_tests[]; extern struct testcase_t dns_tests[]; extern struct testcase_t dos_tests[]; @@ -186,6 +187,7 @@ extern struct testcase_t scheduler_tests[]; extern struct testcase_t sendme_tests[]; extern struct testcase_t socks_tests[]; extern struct testcase_t sr_tests[]; +extern struct testcase_t statefile_tests[]; extern struct testcase_t stats_tests[]; extern struct testcase_t status_tests[]; extern struct testcase_t storagedir_tests[]; diff --git a/src/test/test_channel.c b/src/test/test_channel.c index 042eb27d9d..c86327ceb4 100644 --- a/src/test/test_channel.c +++ b/src/test/test_channel.c @@ -1382,7 +1382,7 @@ test_channel_for_extend(void *arg) /* The expected result is chan2 because it is older than chan1. */ ret_chan = channel_get_for_extend(digest, &ed_id, &ipv4_addr, &ipv6_addr, - &msg, &launch); + false, &msg, &launch); tt_assert(ret_chan); tt_ptr_op(ret_chan, OP_EQ, chan2); tt_int_op(launch, OP_EQ, 0); @@ -1391,7 +1391,7 @@ test_channel_for_extend(void *arg) /* Switch that around from previous test. */ chan2->timestamp_created = chan1->timestamp_created + 1; ret_chan = channel_get_for_extend(digest, &ed_id, &ipv4_addr, &ipv6_addr, - &msg, &launch); + false, &msg, &launch); tt_assert(ret_chan); tt_ptr_op(ret_chan, OP_EQ, chan1); tt_int_op(launch, OP_EQ, 0); @@ -1401,7 +1401,7 @@ test_channel_for_extend(void *arg) * channel 2 should be picked due to how channel_is_better() works. */ chan2->timestamp_created = chan1->timestamp_created; ret_chan = channel_get_for_extend(digest, &ed_id, &ipv4_addr, &ipv6_addr, - &msg, &launch); + false, &msg, &launch); tt_assert(ret_chan); tt_ptr_op(ret_chan, OP_EQ, chan1); tt_int_op(launch, OP_EQ, 0); @@ -1413,7 +1413,7 @@ test_channel_for_extend(void *arg) /* Condemned the older channel. */ chan1->state = CHANNEL_STATE_CLOSING; ret_chan = channel_get_for_extend(digest, &ed_id, &ipv4_addr, &ipv6_addr, - &msg, &launch); + false, &msg, &launch); tt_assert(ret_chan); tt_ptr_op(ret_chan, OP_EQ, chan2); tt_int_op(launch, OP_EQ, 0); @@ -1423,7 +1423,7 @@ test_channel_for_extend(void *arg) /* Make the older channel a client one. */ channel_mark_client(chan1); ret_chan = channel_get_for_extend(digest, &ed_id, &ipv4_addr, &ipv6_addr, - &msg, &launch); + false, &msg, &launch); tt_assert(ret_chan); tt_ptr_op(ret_chan, OP_EQ, chan2); tt_int_op(launch, OP_EQ, 0); @@ -1435,7 +1435,7 @@ test_channel_for_extend(void *arg) memset(&dumb_ed_id, 0, sizeof(dumb_ed_id)); ret_chan = channel_get_for_extend(digest, &dumb_ed_id, &ipv4_addr, &ipv6_addr, - &msg, &launch); + false, &msg, &launch); tt_assert(!ret_chan); tt_str_op(msg, OP_EQ, "Not connected. Connecting."); tt_int_op(launch, OP_EQ, 1); @@ -1445,7 +1445,7 @@ test_channel_for_extend(void *arg) chan1->state = CHANNEL_STATE_OPENING; chan2->state = CHANNEL_STATE_OPENING; ret_chan = channel_get_for_extend(digest, &ed_id, &ipv4_addr, &ipv6_addr, - &msg, &launch); + false, &msg, &launch); tt_assert(!ret_chan); tt_str_op(msg, OP_EQ, "Connection in progress; waiting."); tt_int_op(launch, OP_EQ, 0); @@ -1455,7 +1455,7 @@ test_channel_for_extend(void *arg) /* Mark channel 1 as bad for circuits. */ channel_mark_bad_for_new_circs(chan1); ret_chan = channel_get_for_extend(digest, &ed_id, &ipv4_addr, &ipv6_addr, - &msg, &launch); + false, &msg, &launch); tt_assert(ret_chan); tt_ptr_op(ret_chan, OP_EQ, chan2); tt_int_op(launch, OP_EQ, 0); @@ -1466,7 +1466,7 @@ test_channel_for_extend(void *arg) channel_mark_bad_for_new_circs(chan1); channel_mark_bad_for_new_circs(chan2); ret_chan = channel_get_for_extend(digest, &ed_id, &ipv4_addr, &ipv6_addr, - &msg, &launch); + false, &msg, &launch); tt_assert(!ret_chan); tt_str_op(msg, OP_EQ, "Connections all too old, or too non-canonical. " " Launching a new one."); @@ -1478,7 +1478,7 @@ test_channel_for_extend(void *arg) test_chan_should_be_canonical = 0; test_chan_should_match_target = 0; ret_chan = channel_get_for_extend(digest, &ed_id, &ipv4_addr, &ipv6_addr, - &msg, &launch); + false, &msg, &launch); tt_assert(!ret_chan); tt_str_op(msg, OP_EQ, "Connections all too old, or too non-canonical. " " Launching a new one."); diff --git a/src/test/test_circuitbuild.c b/src/test/test_circuitbuild.c index 74824a1bc1..299908ce82 100644 --- a/src/test/test_circuitbuild.c +++ b/src/test/test_circuitbuild.c @@ -1214,6 +1214,7 @@ mock_channel_get_for_extend(const char *rsa_id_digest, const ed25519_public_key_t *ed_id, const tor_addr_t *target_ipv4_addr, const tor_addr_t *target_ipv6_addr, + bool for_origin_circ, const char **msg_out, int *launch_out) { @@ -1221,6 +1222,7 @@ mock_channel_get_for_extend(const char *rsa_id_digest, (void)ed_id; (void)target_ipv4_addr; (void)target_ipv6_addr; + (void)for_origin_circ; /* channel_get_for_extend() requires non-NULL arguments */ tt_ptr_op(msg_out, OP_NE, NULL); diff --git a/src/test/test_connection.c b/src/test/test_connection.c index 954aeb82e3..178a37adf6 100644 --- a/src/test/test_connection.c +++ b/src/test/test_connection.c @@ -617,7 +617,8 @@ test_conn_download_status(void *arg) connection_t *ap_conn = NULL; const struct testcase_t *tc = arg; - consensus_flavor_t usable_flavor = (consensus_flavor_t)tc->setup_data; + consensus_flavor_t usable_flavor = + networkstatus_parse_flavor_name((const char*) tc->setup_data); /* The "other flavor" trick only works if there are two flavors */ tor_assert(N_CONSENSUS_FLAVORS == 2); @@ -1093,17 +1094,17 @@ struct testcase_t connection_tests[] = { CONNECTION_TESTCASE(get_rend, TT_FORK, test_conn_get_rend_st), CONNECTION_TESTCASE(get_rsrc, TT_FORK, test_conn_get_rsrc_st), - CONNECTION_TESTCASE_ARG(download_status, TT_FORK, - test_conn_download_status_st, FLAV_MICRODESC), - CONNECTION_TESTCASE_ARG(download_status, TT_FORK, - test_conn_download_status_st, FLAV_NS), + CONNECTION_TESTCASE_ARG(download_status, TT_FORK, + test_conn_download_status_st, "microdesc"), + CONNECTION_TESTCASE_ARG(download_status, TT_FORK, + test_conn_download_status_st, "ns"), CONNECTION_TESTCASE_ARG(https_proxy_connect, TT_FORK, test_conn_proxy_connect_st, &PROXY_CONNECT_ARG), CONNECTION_TESTCASE_ARG(haproxy_proxy_connect, TT_FORK, test_conn_proxy_connect_st, &PROXY_HAPROXY_ARG), -//CONNECTION_TESTCASE(func_suffix, TT_FORK, setup_func_pair), + //CONNECTION_TESTCASE(func_suffix, TT_FORK, setup_func_pair), { "failed_orconn_tracker", test_failed_orconn_tracker, TT_FORK, NULL, NULL }, { "describe", test_conn_describe, TT_FORK, NULL, NULL }, END_OF_TESTCASES diff --git a/src/test/test_dir.c b/src/test/test_dir.c index ab0315aa2d..88fbd5ca7d 100644 --- a/src/test/test_dir.c +++ b/src/test/test_dir.c @@ -943,7 +943,7 @@ test_dir_formats_rsa_ed25519(void *arg) ed25519_secret_key_from_seed(&kp2.seckey, (const uint8_t*)"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); ed25519_public_key_generate(&kp2.pubkey, &kp2.seckey); - r2->cache_info.signing_key_cert = tor_cert_create(&kp1, + r2->cache_info.signing_key_cert = tor_cert_create_ed25519(&kp1, CERT_TYPE_ID_SIGNING, &kp2.pubkey, now, 86400, @@ -7290,7 +7290,7 @@ test_dir_dirserv_router_get_status(void *arg) ed25519_secret_key_from_seed(&kp2.seckey, (const uint8_t*)"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); ed25519_public_key_generate(&kp2.pubkey, &kp2.seckey); - ri->cache_info.signing_key_cert = tor_cert_create(&kp1, + ri->cache_info.signing_key_cert = tor_cert_create_ed25519(&kp1, CERT_TYPE_ID_SIGNING, &kp2.pubkey, now, 86400, diff --git a/src/test/test_dirvote.c b/src/test/test_dirvote.c new file mode 100644 index 0000000000..bc2d1150d6 --- /dev/null +++ b/src/test/test_dirvote.c @@ -0,0 +1,671 @@ +/* Copyright (c) 2020, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file test_dirvote.c + * \brief Unit tests for dirvote related functions + */ +#define DIRVOTE_PRIVATE + +#include "core/or/or.h" +#include "feature/dirauth/dirvote.h" +#include "feature/nodelist/dirlist.h" +#include "feature/nodelist/node_st.h" +#include "feature/nodelist/nodelist.h" +#include "feature/nodelist/routerinfo_st.h" +#include "feature/nodelist/signed_descriptor_st.h" + +#include "test/test.h" + +/** + * This struct holds the various informations that are needed for router + * comparison. Each router in the test function has one, and they are all + * put in a global digestmap, router_properties + */ +typedef struct router_values_t { + int is_running; + int is_auth; + int bw_kb; + char digest[DIGEST_LEN]; +} router_values_t; +/** + * This typedef makes declaring digests easier and less verbose + */ +typedef char sha1_digest_t[DIGEST_LEN]; + +// Use of global variable is justified because the functions that have to be +// mocked take as arguments objects we have no control over +static digestmap_t *router_properties = NULL; +// Use of global variable is justified by its use in nodelist.c +// and is necessary to avoid memory leaks when mocking the +// function node_get_by_id +static node_t *running_node; +static node_t *non_running_node; + +/* Allocate memory to the global variables that represent a running + * and non-running node + */ +#define ALLOCATE_MOCK_NODES() \ + running_node = tor_malloc(sizeof(node_t)); \ + running_node->is_running = 1; \ + non_running_node = tor_malloc(sizeof(node_t)); \ + non_running_node->is_running = 0; + +/* Free the memory allocated to the mock nodes */ +#define FREE_MOCK_NODES() \ + tor_free(running_node); \ + tor_free(non_running_node); + +static int +mock_router_digest_is_trusted(const char *digest, dirinfo_type_t type) +{ + (void)type; + router_values_t *mock_status; + mock_status = digestmap_get(router_properties, digest); + if (!mock_status) { + return -1; + } + return mock_status->is_auth; +} + +static const node_t * +mock_node_get_by_id(const char *identity_digest) +{ + router_values_t *status; + status = digestmap_get(router_properties, identity_digest); + if (!status) { + return NULL; + } + if (status->is_running) + return running_node; + else + return non_running_node; +} + +static uint32_t +mock_dirserv_get_bw(const routerinfo_t *ri) +{ + const char *digest = ri->cache_info.identity_digest; + router_values_t *status; + status = digestmap_get(router_properties, digest); + if (!status) { + return -1; + } + return status->bw_kb; +} + +/** Generate a pointer to a router_values_t struct with the arguments as + * field values, and return it + * The returned pointer has to be freed by the caller. + */ +static router_values_t * +router_values_new(int running, int auth, int bw, char *digest) +{ + router_values_t *status = tor_malloc(sizeof(router_values_t)); + memcpy(status->digest, digest, sizeof(status->digest)); + status->is_running = running; + status->bw_kb = bw; + status->is_auth = auth; + return status; +} + +/** Given a router_values_t struct, generate a pointer to a routerinfo struct. + * In the cache_info member, put the identity digest, and depending on + * the family argument, fill the IPv4 or IPv6 address. Return the pointer. + * The returned pointer has to be freed by the caller. + */ +static routerinfo_t * +routerinfo_new(router_values_t *status, int family, int addr) +{ + routerinfo_t *ri = tor_malloc(sizeof(routerinfo_t)); + signed_descriptor_t cache_info; + memcpy(cache_info.identity_digest, status->digest, + sizeof(cache_info.identity_digest)); + ri->cache_info = cache_info; + tor_addr_t ipv6, ipv4; + ipv6.family = family; + ipv4.family = family; + // Set the address of the other IP version to 0 + if (family == AF_INET) { + ipv4.addr.in_addr.s_addr = addr; + for (size_t i = 0; i < 16; i++) { + ipv6.addr.in6_addr.s6_addr[i] = 0; + } + } else { + for (size_t i = 0; i < 16; i++) { + ipv6.addr.in6_addr.s6_addr[i] = addr; + } + ipv4.addr.in_addr.s_addr = 0; + } + ri->ipv6_addr = ipv6; + ri->ipv4_addr = ipv4; + return ri; +} + +static void +test_dirvote_compare_routerinfo_usefulness(void *arg) +{ + (void)arg; + MOCK(router_digest_is_trusted_dir_type, mock_router_digest_is_trusted); + MOCK(node_get_by_id, mock_node_get_by_id); + MOCK(dirserv_get_bandwidth_for_router_kb, mock_dirserv_get_bw); + ALLOCATE_MOCK_NODES(); + router_properties = digestmap_new(); + + // The router one is the "least useful" router, every router is compared to + // it + sha1_digest_t digest_one = "aaaa"; + router_values_t *status_one = router_values_new(0, 0, 0, digest_one); + digestmap_set(router_properties, status_one->digest, status_one); + sha1_digest_t digest_two = "bbbb"; + router_values_t *status_two = router_values_new(0, 1, 0, digest_two); + digestmap_set(router_properties, status_two->digest, status_two); + sha1_digest_t digest_three = "cccc"; + router_values_t *status_three = router_values_new(1, 0, 0, digest_three); + digestmap_set(router_properties, status_three->digest, status_three); + sha1_digest_t digest_four = "dddd"; + router_values_t *status_four = router_values_new(0, 0, 128, digest_four); + digestmap_set(router_properties, status_four->digest, status_four); + sha1_digest_t digest_five = "9999"; + router_values_t *status_five = router_values_new(0, 0, 0, digest_five); + digestmap_set(router_properties, status_five->digest, status_five); + + // A router that has auth status is more useful than a non-auth one + routerinfo_t *first = routerinfo_new(status_one, AF_INET, 0xf); + routerinfo_t *second = routerinfo_new(status_two, AF_INET, 0xf); + int a = compare_routerinfo_usefulness(first, second); + tt_assert(a == 1); + tor_free(second); + + // A running router is more useful than a non running one + routerinfo_t *third = routerinfo_new(status_three, AF_INET, 0xf); + a = compare_routerinfo_usefulness(first, third); + tt_assert(a == 1); + tor_free(third); + + // A higher bandwidth is more useful + routerinfo_t *fourth = routerinfo_new(status_four, AF_INET, 0xf); + a = compare_routerinfo_usefulness(first, fourth); + tt_assert(a == 1); + tor_free(fourth); + + // In case of tie, the digests are compared + routerinfo_t *fifth = routerinfo_new(status_five, AF_INET, 0xf); + a = compare_routerinfo_usefulness(first, fifth); + tt_assert(a > 0); + tor_free(fifth); + +done: + UNMOCK(router_digest_is_trusted_dir_type); + UNMOCK(node_get_by_id); + UNMOCK(dirserv_get_bandwidth_for_router_kb); + FREE_MOCK_NODES(); + digestmap_free(router_properties, NULL); + tor_free(status_one); + tor_free(status_two); + tor_free(status_three); + tor_free(status_four); + tor_free(status_five); + tor_free(first); +} + +static void +test_dirvote_compare_routerinfo_by_ipv4(void *arg) +{ + (void)arg; + MOCK(router_digest_is_trusted_dir_type, mock_router_digest_is_trusted); + MOCK(node_get_by_id, mock_node_get_by_id); + MOCK(dirserv_get_bandwidth_for_router_kb, mock_dirserv_get_bw); + + ALLOCATE_MOCK_NODES(); + router_properties = digestmap_new(); + sha1_digest_t digest_one = "aaaa"; + router_values_t *status_one = router_values_new(0, 0, 0, digest_one); + digestmap_set(router_properties, status_one->digest, status_one); + sha1_digest_t digest_two = "bbbb"; + router_values_t *status_two = router_values_new(0, 1, 0, digest_two); + digestmap_set(router_properties, status_two->digest, status_two); + + // Both routers have an IPv4 address + routerinfo_t *first = routerinfo_new(status_one, AF_INET, 1); + routerinfo_t *second = routerinfo_new(status_two, AF_INET, 0xf); + + // The first argument's address precedes the seconds' one + int a = compare_routerinfo_by_ipv4((const void **)&first, + (const void **)&second); + tt_assert(a < 0); + // The second argument's address precedes the first' one + a = compare_routerinfo_by_ipv4((const void **)&second, + (const void **)&first); + tt_assert(a > 0); + tor_addr_copy(&(second->ipv4_addr), &(first->ipv6_addr)); + // The addresses are equal, they are compared by usefulness, + // and first is less useful than second + a = compare_routerinfo_by_ipv4((const void **)&first, + (const void **)&second); + tt_assert(a == 1); +done: + UNMOCK(router_digest_is_trusted_dir_type); + UNMOCK(node_get_by_id); + UNMOCK(dirserv_get_bandwidth_for_router_kb); + FREE_MOCK_NODES(); + digestmap_free(router_properties, NULL); + tor_free(status_one); + tor_free(status_two); + tor_free(first); + tor_free(second); +} + +static void +test_dirvote_compare_routerinfo_by_ipv6(void *arg) +{ + (void)arg; + MOCK(router_digest_is_trusted_dir_type, mock_router_digest_is_trusted); + MOCK(node_get_by_id, mock_node_get_by_id); + MOCK(dirserv_get_bandwidth_for_router_kb, mock_dirserv_get_bw); + + ALLOCATE_MOCK_NODES(); + router_properties = digestmap_new(); + char digest_one[DIGEST_LEN] = "aaaa"; + router_values_t *status_one = router_values_new(0, 0, 0, digest_one); + digestmap_set(router_properties, status_one->digest, status_one); + char digest_two[DIGEST_LEN] = "bbbb"; + router_values_t *status_two = router_values_new(0, 1, 0, digest_two); + digestmap_set(router_properties, status_two->digest, status_two); + + // Both routers have an IPv6 address + routerinfo_t *first = routerinfo_new(status_one, AF_INET6, 1); + routerinfo_t *second = routerinfo_new(status_two, AF_INET6, 0xf); + + // The first argument's address precedes the seconds' one + int a = compare_routerinfo_by_ipv6((const void **)&first, + (const void **)&second); + tt_assert(a < 0); + // The second argument's address precedes the first' one + a = compare_routerinfo_by_ipv6((const void **)&second, + (const void **)&first); + tt_assert(a > 0); + tor_addr_copy(&(first->ipv6_addr), &(second->ipv6_addr)); + // The addresses are equal, they are compared by usefulness, + // and first is less useful than second + a = compare_routerinfo_by_ipv6((const void **)&first, + (const void **)&second); + tt_assert(a == 1); +done: + UNMOCK(router_digest_is_trusted_dir_type); + UNMOCK(node_get_by_id); + UNMOCK(dirserv_get_bandwidth_for_router_kb); + FREE_MOCK_NODES(); + digestmap_free(router_properties, NULL); + tor_free(status_one); + tor_free(status_two); + tor_free(first); + tor_free(second); +} + +/** Create routers values and routerinfos that always have the same + * characteristics, and add them to the global digestmap. This macro is here to + * avoid duplicated code fragments. + * The created name##_val pointer should be freed by the caller (and cannot + * be freed in the macro as it causes a heap-after-free error) + */ +#define CREATE_ROUTER(digest, name, addr, ip_version) \ + sha1_digest_t name##_digest = digest; \ + name##_val = router_values_new(1, 1, 1, name##_digest); \ + digestmap_set(router_properties, name##_digest, name##_val); \ + name##_ri = routerinfo_new(name##_val, ip_version, addr); + +#define ROUTER_FREE(name) \ + tor_free(name##_val); \ + tor_free(name##_ri); + +/** Test to see if the returned routers are exactly the ones that should be + * flagged as sybils : we test for inclusion then for number of elements + */ +#define TEST_SYBIL(true_sybil, possible_sybil) \ + DIGESTMAP_FOREACH (true_sybil, sybil_id, void *, ignore) { \ + (void)ignore; \ + tt_assert(digestmap_get(possible_sybil, sybil_id)); \ + } \ + DIGESTMAP_FOREACH_END; \ + tt_assert(digestmap_size(true_sybil) == digestmap_size(possible_sybil)); + +static void +test_dirvote_get_sybil_by_ip_version_ipv4(void *arg) +{ + // It is assumed that global_dirauth_options.AuthDirMaxServersPerAddr == 2 + (void)arg; + router_values_t *aaaa_val=NULL, *bbbb_val=NULL, *cccc_val=NULL, + *dddd_val=NULL, *eeee_val=NULL, *ffff_val=NULL, *gggg_val=NULL, + *hhhh_val=NULL; + routerinfo_t *aaaa_ri=NULL, *bbbb_ri=NULL, *cccc_ri=NULL, + *dddd_ri=NULL, *eeee_ri=NULL, *ffff_ri=NULL, *gggg_ri=NULL, + *hhhh_ri=NULL; + + MOCK(router_digest_is_trusted_dir_type, mock_router_digest_is_trusted); + MOCK(node_get_by_id, mock_node_get_by_id); + MOCK(dirserv_get_bandwidth_for_router_kb, mock_dirserv_get_bw); + ALLOCATE_MOCK_NODES(); + router_properties = digestmap_new(); + smartlist_t *routers_ipv4; + routers_ipv4 = smartlist_new(); + digestmap_t *true_sybil_routers = NULL; + true_sybil_routers = digestmap_new(); + digestmap_t *omit_as_sybil; + + CREATE_ROUTER("aaaa", aaaa, 123, AF_INET); + smartlist_add(routers_ipv4, aaaa_ri); + CREATE_ROUTER("bbbb", bbbb, 123, AF_INET); + smartlist_add(routers_ipv4, bbbb_ri); + omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv4, AF_INET); + tt_assert(digestmap_isempty(omit_as_sybil) == 1); + digestmap_free(omit_as_sybil, NULL); + + CREATE_ROUTER("cccc", cccc, 123, AF_INET); + smartlist_add(routers_ipv4, cccc_ri); + digestmap_set(true_sybil_routers, cccc_digest, cccc_digest); + omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv4, AF_INET); + TEST_SYBIL(true_sybil_routers, omit_as_sybil); + digestmap_free(omit_as_sybil, NULL); + + CREATE_ROUTER("dddd", dddd, 123, AF_INET); + smartlist_add(routers_ipv4, dddd_ri); + digestmap_set(true_sybil_routers, dddd_digest, dddd_digest); + omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv4, AF_INET); + TEST_SYBIL(true_sybil_routers, omit_as_sybil); + digestmap_free(omit_as_sybil, NULL); + + CREATE_ROUTER("eeee", eeee, 456, AF_INET); + smartlist_add(routers_ipv4, eeee_ri); + omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv4, AF_INET); + TEST_SYBIL(true_sybil_routers, omit_as_sybil); + digestmap_free(omit_as_sybil, NULL); + + CREATE_ROUTER("ffff", ffff, 456, AF_INET); + smartlist_add(routers_ipv4, ffff_ri); + omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv4, AF_INET); + TEST_SYBIL(true_sybil_routers, omit_as_sybil); + digestmap_free(omit_as_sybil, NULL); + + CREATE_ROUTER("gggg", gggg, 456, AF_INET); + smartlist_add(routers_ipv4, gggg_ri); + digestmap_set(true_sybil_routers, gggg_digest, gggg_digest); + omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv4, AF_INET); + TEST_SYBIL(true_sybil_routers, omit_as_sybil); + digestmap_free(omit_as_sybil, NULL); + + CREATE_ROUTER("hhhh", hhhh, 456, AF_INET); + smartlist_add(routers_ipv4, hhhh_ri); + digestmap_set(true_sybil_routers, hhhh_digest, hhhh_digest); + omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv4, AF_INET); + TEST_SYBIL(true_sybil_routers, omit_as_sybil); + +done: + UNMOCK(router_digest_is_trusted_dir_type); + UNMOCK(node_get_by_id); + UNMOCK(dirserv_get_bandwidth_for_router_kb); + FREE_MOCK_NODES(); + digestmap_free(router_properties, NULL); + smartlist_free(routers_ipv4); + digestmap_free(omit_as_sybil, NULL); + digestmap_free(true_sybil_routers, NULL); + ROUTER_FREE(aaaa); + ROUTER_FREE(bbbb); + ROUTER_FREE(cccc); + ROUTER_FREE(dddd); + ROUTER_FREE(eeee); + ROUTER_FREE(ffff); + ROUTER_FREE(gggg); + ROUTER_FREE(hhhh); +} + +static void +test_dirvote_get_sybil_by_ip_version_ipv6(void *arg) +{ + router_values_t *aaaa_val=NULL, *bbbb_val=NULL, *cccc_val=NULL, + *dddd_val=NULL, *eeee_val=NULL, *ffff_val=NULL, *gggg_val=NULL, + *hhhh_val=NULL; + routerinfo_t *aaaa_ri=NULL, *bbbb_ri=NULL, *cccc_ri=NULL, + *dddd_ri=NULL, *eeee_ri=NULL, *ffff_ri=NULL, *gggg_ri=NULL, + *hhhh_ri=NULL; + + // It is assumed that global_dirauth_options.AuthDirMaxServersPerAddr == 2 + (void)arg; + MOCK(router_digest_is_trusted_dir_type, mock_router_digest_is_trusted); + MOCK(node_get_by_id, mock_node_get_by_id); + MOCK(dirserv_get_bandwidth_for_router_kb, mock_dirserv_get_bw); + ALLOCATE_MOCK_NODES(); + router_properties = digestmap_new(); + smartlist_t *routers_ipv6; + routers_ipv6 = smartlist_new(); + digestmap_t *true_sybil_routers = NULL; + true_sybil_routers = digestmap_new(); + digestmap_t *omit_as_sybil; + + CREATE_ROUTER("aaaa", aaaa, 123, AF_INET6); + smartlist_add(routers_ipv6, aaaa_ri); + CREATE_ROUTER("bbbb", bbbb, 123, AF_INET6); + smartlist_add(routers_ipv6, bbbb_ri); + omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv6, AF_INET6); + TEST_SYBIL(true_sybil_routers, omit_as_sybil); + digestmap_free(omit_as_sybil, NULL); + + CREATE_ROUTER("cccc", cccc, 123, AF_INET6); + smartlist_add(routers_ipv6, cccc_ri); + digestmap_set(true_sybil_routers, cccc_digest, cccc_digest); + omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv6, AF_INET6); + TEST_SYBIL(true_sybil_routers, omit_as_sybil); + digestmap_free(omit_as_sybil, NULL); + + CREATE_ROUTER("dddd", dddd, 123, AF_INET6); + smartlist_add(routers_ipv6, dddd_ri); + digestmap_set(true_sybil_routers, dddd_digest, dddd_digest); + omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv6, AF_INET6); + TEST_SYBIL(true_sybil_routers, omit_as_sybil); + digestmap_free(omit_as_sybil, NULL); + + CREATE_ROUTER("eeee", eeee, 456, AF_INET6); + smartlist_add(routers_ipv6, eeee_ri); + omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv6, AF_INET6); + TEST_SYBIL(true_sybil_routers, omit_as_sybil); + digestmap_free(omit_as_sybil, NULL); + + CREATE_ROUTER("ffff", ffff, 456, AF_INET6); + smartlist_add(routers_ipv6, ffff_ri); + omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv6, AF_INET6); + TEST_SYBIL(true_sybil_routers, omit_as_sybil); + digestmap_free(omit_as_sybil, NULL); + + CREATE_ROUTER("gggg", gggg, 456, AF_INET6); + smartlist_add(routers_ipv6, gggg_ri); + digestmap_set(true_sybil_routers, gggg_digest, gggg_digest); + omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv6, AF_INET6); + TEST_SYBIL(true_sybil_routers, omit_as_sybil); + digestmap_free(omit_as_sybil, NULL); + + CREATE_ROUTER("hhhh", hhhh, 456, AF_INET6); + smartlist_add(routers_ipv6, hhhh_ri); + digestmap_set(true_sybil_routers, hhhh_digest, hhhh_digest); + omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv6, AF_INET6); + TEST_SYBIL(true_sybil_routers, omit_as_sybil); +done: + UNMOCK(router_digest_is_trusted_dir_type); + UNMOCK(node_get_by_id); + UNMOCK(dirserv_get_bandwidth_for_router_kb); + FREE_MOCK_NODES(); + digestmap_free(router_properties, NULL); + digestmap_free(true_sybil_routers, NULL); + smartlist_free(routers_ipv6); + digestmap_free(omit_as_sybil, NULL); + ROUTER_FREE(aaaa); + ROUTER_FREE(bbbb); + ROUTER_FREE(cccc); + ROUTER_FREE(dddd); + ROUTER_FREE(eeee); + ROUTER_FREE(ffff); + ROUTER_FREE(gggg); + ROUTER_FREE(hhhh); +} + +static void +test_dirvote_get_all_possible_sybil(void *arg) +{ + router_values_t *aaaa_val=NULL, *bbbb_val=NULL, *cccc_val=NULL, + *dddd_val=NULL, *eeee_val=NULL, *ffff_val=NULL, *gggg_val=NULL, + *hhhh_val=NULL, *iiii_val=NULL, *jjjj_val=NULL, *kkkk_val=NULL, + *llll_val=NULL, *mmmm_val=NULL, *nnnn_val=NULL, *oooo_val=NULL, + *pppp_val=NULL; + routerinfo_t *aaaa_ri=NULL, *bbbb_ri=NULL, *cccc_ri=NULL, + *dddd_ri=NULL, *eeee_ri=NULL, *ffff_ri=NULL, *gggg_ri=NULL, + *hhhh_ri=NULL, *iiii_ri=NULL, *jjjj_ri=NULL, *kkkk_ri=NULL, + *llll_ri=NULL, *mmmm_ri=NULL, *nnnn_ri=NULL, *oooo_ri=NULL, + *pppp_ri=NULL; + + // It is assumed that global_dirauth_options.AuthDirMaxServersPerAddr == 2 + (void)arg; + MOCK(router_digest_is_trusted_dir_type, mock_router_digest_is_trusted); + MOCK(node_get_by_id, mock_node_get_by_id); + MOCK(dirserv_get_bandwidth_for_router_kb, mock_dirserv_get_bw); + ALLOCATE_MOCK_NODES(); + router_properties = digestmap_new(); + smartlist_t *routers; + routers = smartlist_new(); + digestmap_t *true_sybil_routers = NULL; + true_sybil_routers = digestmap_new(); + digestmap_t *omit_as_sybil; + + CREATE_ROUTER("aaaa", aaaa, 123, AF_INET); + smartlist_add(routers, aaaa_ri); + CREATE_ROUTER("bbbb", bbbb, 123, AF_INET); + smartlist_add(routers, bbbb_ri); + omit_as_sybil = get_all_possible_sybil(routers); + TEST_SYBIL(true_sybil_routers, omit_as_sybil); + digestmap_free(omit_as_sybil, NULL); + + CREATE_ROUTER("cccc", cccc, 123, AF_INET); + smartlist_add(routers, cccc_ri); + digestmap_set(true_sybil_routers, cccc_digest, cccc_digest); + omit_as_sybil = get_all_possible_sybil(routers); + TEST_SYBIL(true_sybil_routers, omit_as_sybil); + digestmap_free(omit_as_sybil, NULL); + + CREATE_ROUTER("dddd", dddd, 123, AF_INET); + smartlist_add(routers, dddd_ri); + digestmap_set(true_sybil_routers, dddd_digest, dddd_digest); + omit_as_sybil = get_all_possible_sybil(routers); + TEST_SYBIL(true_sybil_routers, omit_as_sybil); + digestmap_free(omit_as_sybil, NULL); + + CREATE_ROUTER("eeee", eeee, 456, AF_INET); + smartlist_add(routers, eeee_ri); + omit_as_sybil = get_all_possible_sybil(routers); + TEST_SYBIL(true_sybil_routers, omit_as_sybil); + digestmap_free(omit_as_sybil, NULL); + + CREATE_ROUTER("ffff", ffff, 456, AF_INET); + smartlist_add(routers, ffff_ri); + omit_as_sybil = get_all_possible_sybil(routers); + TEST_SYBIL(true_sybil_routers, omit_as_sybil); + digestmap_free(omit_as_sybil, NULL); + + CREATE_ROUTER("gggg", gggg, 456, AF_INET); + smartlist_add(routers, gggg_ri); + digestmap_set(true_sybil_routers, gggg_digest, gggg_digest); + omit_as_sybil = get_all_possible_sybil(routers); + TEST_SYBIL(true_sybil_routers, omit_as_sybil); + digestmap_free(omit_as_sybil, NULL); + + CREATE_ROUTER("hhhh", hhhh, 456, AF_INET); + smartlist_add(routers, hhhh_ri); + digestmap_set(true_sybil_routers, hhhh_digest, hhhh_digest); + omit_as_sybil = get_all_possible_sybil(routers); + TEST_SYBIL(true_sybil_routers, omit_as_sybil); + digestmap_free(omit_as_sybil, NULL); + + CREATE_ROUTER("iiii", iiii, 123, AF_INET6); + smartlist_add(routers, iiii_ri); + CREATE_ROUTER("jjjj", jjjj, 123, AF_INET6); + smartlist_add(routers, jjjj_ri); + omit_as_sybil = get_all_possible_sybil(routers); + TEST_SYBIL(true_sybil_routers, omit_as_sybil); + digestmap_free(omit_as_sybil, NULL); + + CREATE_ROUTER("kkkk", kkkk, 123, AF_INET6); + smartlist_add(routers, kkkk_ri); + digestmap_set(true_sybil_routers, kkkk_digest, kkkk_digest); + omit_as_sybil = get_all_possible_sybil(routers); + TEST_SYBIL(true_sybil_routers, omit_as_sybil); + digestmap_free(omit_as_sybil,NULL); + + CREATE_ROUTER("llll", llll, 123, AF_INET6); + smartlist_add(routers, llll_ri); + digestmap_set(true_sybil_routers, llll_digest, llll_digest); + omit_as_sybil = get_all_possible_sybil(routers); + TEST_SYBIL(true_sybil_routers, omit_as_sybil); + digestmap_free(omit_as_sybil,NULL); + + CREATE_ROUTER("mmmm", mmmm, 456, AF_INET6); + smartlist_add(routers, mmmm_ri); + omit_as_sybil = get_all_possible_sybil(routers); + TEST_SYBIL(true_sybil_routers, omit_as_sybil); + digestmap_free(omit_as_sybil, NULL); + + CREATE_ROUTER("nnnn", nnnn, 456, AF_INET6); + smartlist_add(routers, nnnn_ri); + omit_as_sybil = get_all_possible_sybil(routers); + TEST_SYBIL(true_sybil_routers, omit_as_sybil); + digestmap_free(omit_as_sybil, NULL); + + CREATE_ROUTER("oooo", oooo, 456, AF_INET6); + smartlist_add(routers, oooo_ri); + digestmap_set(true_sybil_routers, oooo_digest, oooo_digest); + omit_as_sybil = get_all_possible_sybil(routers); + TEST_SYBIL(true_sybil_routers, omit_as_sybil); + digestmap_free(omit_as_sybil, NULL); + + CREATE_ROUTER("pppp", pppp, 456, AF_INET6); + smartlist_add(routers, pppp_ri); + digestmap_set(true_sybil_routers, pppp_digest, pppp_digest); + omit_as_sybil = get_all_possible_sybil(routers); + TEST_SYBIL(true_sybil_routers, omit_as_sybil); + +done: + UNMOCK(router_digest_is_trusted_dir_type); + UNMOCK(node_get_by_id); + UNMOCK(dirserv_get_bandwidth_for_router_kb); + FREE_MOCK_NODES(); + digestmap_free(router_properties, NULL); + smartlist_free(routers); + digestmap_free(omit_as_sybil, NULL); + digestmap_free(true_sybil_routers, NULL); + ROUTER_FREE(aaaa); + ROUTER_FREE(bbbb); + ROUTER_FREE(cccc); + ROUTER_FREE(dddd); + ROUTER_FREE(eeee); + ROUTER_FREE(ffff); + ROUTER_FREE(gggg); + ROUTER_FREE(hhhh); + ROUTER_FREE(iiii); + ROUTER_FREE(jjjj); + ROUTER_FREE(kkkk); + ROUTER_FREE(llll); + ROUTER_FREE(mmmm); + ROUTER_FREE(nnnn); + ROUTER_FREE(oooo); + ROUTER_FREE(pppp); +} + +#define NODE(name, flags) \ + { \ + #name, test_dirvote_##name, (flags), NULL, NULL \ + } + +struct testcase_t dirvote_tests[] = { + NODE(compare_routerinfo_usefulness, TT_FORK), + NODE(compare_routerinfo_by_ipv6, TT_FORK), + NODE(compare_routerinfo_by_ipv4, TT_FORK), + NODE(get_sybil_by_ip_version_ipv4, TT_FORK), + NODE(get_sybil_by_ip_version_ipv6, TT_FORK), + NODE(get_all_possible_sybil, TT_FORK), + END_OF_TESTCASES}; diff --git a/src/test/test_hs_descriptor.c b/src/test/test_hs_descriptor.c index 782b78306c..b6e13c79a8 100644 --- a/src/test/test_hs_descriptor.c +++ b/src/test/test_hs_descriptor.c @@ -56,7 +56,7 @@ test_cert_encoding(void *arg) ret = ed25519_public_key_generate(&signed_key, &secret_key); tt_int_op(ret, == , 0); - cert = tor_cert_create(&kp, CERT_TYPE_SIGNING_AUTH, &signed_key, + cert = tor_cert_create_ed25519(&kp, CERT_TYPE_SIGNING_AUTH, &signed_key, now, 3600 * 2, CERT_FLAG_INCLUDE_SIGNING_KEY); tt_assert(cert); @@ -706,7 +706,7 @@ test_validate_cert(void *arg) tt_int_op(ret, OP_EQ, 0); /* Cert of type CERT_TYPE_AUTH_HS_IP_KEY. */ - cert = tor_cert_create(&kp, CERT_TYPE_AUTH_HS_IP_KEY, + cert = tor_cert_create_ed25519(&kp, CERT_TYPE_AUTH_HS_IP_KEY, &kp.pubkey, now, 3600, CERT_FLAG_INCLUDE_SIGNING_KEY); tt_assert(cert); @@ -726,8 +726,9 @@ test_validate_cert(void *arg) tor_cert_free(cert); /* Try a cert without including the signing key. */ - cert = tor_cert_create(&kp, CERT_TYPE_AUTH_HS_IP_KEY, &kp.pubkey, now, - 3600, 0); + cert = tor_cert_create_ed25519(&kp, CERT_TYPE_AUTH_HS_IP_KEY, + &kp.pubkey, now, 3600, 0); + tt_assert(cert); /* Test with a bad type. */ ret = cert_is_valid(cert, CERT_TYPE_AUTH_HS_IP_KEY, "unicorn"); diff --git a/src/test/test_link_handshake.c b/src/test/test_link_handshake.c index 1566b349ed..06af299056 100644 --- a/src/test/test_link_handshake.c +++ b/src/test/test_link_handshake.c @@ -710,7 +710,7 @@ CERTS_FAIL(missing_signing_key, /* ed25519 */ * signing key. */ const ed25519_keypair_t *mk = get_master_identity_keypair(); const ed25519_keypair_t *sk = get_master_signing_keypair(); - tor_cert_t *bad_cert = tor_cert_create(mk, CERT_TYPE_ID_SIGNING, + tor_cert_t *bad_cert = tor_cert_create_ed25519(mk, CERT_TYPE_ID_SIGNING, &sk->pubkey, time(NULL), 86400, 0 /* don't include signer */); certs_cell_cert_setlen_body(cert, bad_cert->encoded_len); diff --git a/src/test/test_routerkeys.c b/src/test/test_routerkeys.c index 8d653e44a2..e5314046b9 100644 --- a/src/test/test_routerkeys.c +++ b/src/test/test_routerkeys.c @@ -151,7 +151,7 @@ test_routerkeys_ed_certs(void *args) for (int i = 0; i <= 1; ++i) { uint32_t flags = i ? CERT_FLAG_INCLUDE_SIGNING_KEY : 0; - cert[i] = tor_cert_create(&kp1, 5, &kp2.pubkey, now, 10000, flags); + cert[i] = tor_cert_create_ed25519(&kp1, 5, &kp2.pubkey, now, 10000, flags); tt_assert(cert[i]); tt_uint_op(cert[i]->sig_bad, OP_EQ, 0); diff --git a/src/test/test_statefile.c b/src/test/test_statefile.c new file mode 100644 index 0000000000..dc9ecfee3e --- /dev/null +++ b/src/test/test_statefile.c @@ -0,0 +1,56 @@ +/* Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2020, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "orconfig.h" + +#define STATEFILE_PRIVATE + +#include "core/or/or.h" +#include "lib/encoding/confline.h" +#include "app/config/statefile.h" + +#include "test/test.h" + +static void +test_statefile_remove_obsolete(void *arg) +{ + (void)arg; + config_line_t *inp = NULL; + /* try empty config */ + or_state_remove_obsolete_lines(&inp); + tt_assert(!inp); + + /* try removing every line */ + config_line_append(&inp, "EntryGuard", "doesn't matter"); + config_line_append(&inp, "HidServRevCounter", "ignore"); + config_line_append(&inp, "hidservrevcounter", "foobar"); // note case + or_state_remove_obsolete_lines(&inp); + tt_assert(!inp); + + /* Now try removing a subset of lines. */ + config_line_append(&inp, "EntryGuard", "doesn't matter"); + config_line_append(&inp, "Guard", "in use"); + config_line_append(&inp, "HidServRevCounter", "ignore"); + config_line_append(&inp, "TorVersion", "this test doesn't care"); + or_state_remove_obsolete_lines(&inp); + tt_assert(inp); + tt_str_op(inp->key, OP_EQ, "Guard"); + tt_str_op(inp->value, OP_EQ, "in use"); + tt_assert(inp->next); + tt_str_op(inp->next->key, OP_EQ, "TorVersion"); + tt_str_op(inp->next->value, OP_EQ, "this test doesn't care"); + tt_assert(! inp->next->next); + + done: + config_free_lines(inp); +} + +#define T(name) \ + { #name, test_statefile_##name, 0, NULL, NULL } + +struct testcase_t statefile_tests[] = { + T(remove_obsolete), + END_OF_TESTCASES +}; |