[tor-commits] [tor/maint-0.4.4] Merge branch 'ticket40237_043_01' into ticket40237_044_01
dgoulet at torproject.org
dgoulet at torproject.org
Thu Jan 28 17:15:35 UTC 2021
commit b3652f2104c880bf626cb4e97e6088bca5a1571f
Merge: 5a822b462a 0485c7ddba
Author: David Goulet <dgoulet at torproject.org>
Date: Tue Jan 12 10:54:31 2021 -0500
Merge branch 'ticket40237_043_01' into ticket40237_044_01
changes/ticket40237 | 5 +++
src/core/mainloop/mainloop.c | 3 +-
src/feature/hs/hs_cache.c | 5 ++-
src/feature/hs/hs_client.c | 8 +++--
src/feature/hs/hs_common.c | 12 ++++++--
src/feature/hs/hs_service.c | 9 ++++--
src/feature/hs_common/shared_random_client.c | 26 ++++++++++------
src/feature/nodelist/nodelist.c | 2 +-
src/test/test_hs_cache.c | 19 ++++++------
src/test/test_hs_client.c | 46 +++++++++++++++-------------
src/test/test_hs_common.c | 36 ++++++++++++++--------
src/test/test_hs_service.c | 40 ++++++++++++------------
src/test/test_shared_random.c | 22 ++++++++++---
13 files changed, 144 insertions(+), 89 deletions(-)
diff --cc src/feature/hs/hs_service.c
index a42879a48f,54bc572d11..c29f39c6b4
--- a/src/feature/hs/hs_service.c
+++ b/src/feature/hs/hs_service.c
@@@ -3188,10 -3085,8 +3190,11 @@@ should_service_upload_descriptor(const
}
/* Don't upload desc if we don't have a live consensus */
- if (!networkstatus_get_live_consensus(now)) {
- msg = tor_strdup("No live consensus");
+ if (!networkstatus_get_reasonably_live_consensus(now,
+ usable_consensus_flavor())) {
++ msg = tor_strdup("No reasonably live consensus");
+ log_cant_upload_desc(service, desc, msg,
+ LOG_DESC_UPLOAD_REASON_NO_LIVE_CONSENSUS);
goto cannot;
}
diff --cc src/feature/hs_common/shared_random_client.c
index c2ea5afe32,b4b2f2c9d3..4e8a2942fc
--- a/src/feature/hs_common/shared_random_client.c
+++ b/src/feature/hs_common/shared_random_client.c
@@@ -11,8 -11,8 +11,9 @@@
#include "feature/hs_common/shared_random_client.h"
#include "app/config/config.h"
-#include "feature/dircommon/voting_schedule.h"
+#include "feature/dirauth/authmode.h"
+#include "feature/dirauth/voting_schedule.h"
+ #include "feature/nodelist/microdesc.h"
#include "feature/nodelist/networkstatus.h"
#include "lib/encoding/binascii.h"
@@@ -55,25 -37,17 +56,27 @@@ in
get_voting_interval(void)
{
int interval;
- networkstatus_t *consensus = networkstatus_get_live_consensus(time(NULL));
+ networkstatus_t *consensus =
+ networkstatus_get_reasonably_live_consensus(time(NULL),
+ usable_consensus_flavor());
if (consensus) {
+ /* Ideally we have a live consensus and we can just use that. */
+ interval = (int)(consensus->fresh_until - consensus->valid_after);
+ } else if (authdir_mode(get_options()) || ASSUME_AUTHORITY_SCHEDULING) {
+ /* If we don't have a live consensus and we're an authority,
+ * we should believe our own view of what the schedule ought to be. */
+ interval = dirauth_sched_get_configured_interval();
+ } else if ((consensus = networkstatus_get_latest_consensus())) {
+ /* If we're a client, then maybe a latest consensus is good enough?
+ * It's better than falling back to the non-consensus case. */
interval = (int)(consensus->fresh_until - consensus->valid_after);
} else {
- /* Same for both a testing and real network. We voluntarily ignore the
- * InitialVotingInterval since it complexifies things and it doesn't
- * affect the SR protocol. */
- interval = get_options()->V3AuthVotingInterval;
+ /* We should never be reaching this point, since a client should never
+ * call this code unless they have some kind of a consensus. All we can
+ * do is hope that this network is using the default voting interval. */
+ tor_assert_nonfatal_unreached_once();
+ interval = DEFAULT_NETWORK_VOTING_INTERVAL;
}
tor_assert(interval > 0);
return interval;
@@@ -242,28 -241,18 +247,29 @@@ sr_state_get_start_time_of_current_prot
int voting_interval = get_voting_interval();
time_t beginning_of_curr_round;
- /* This function is not used for voting purposes, so if we have a live
- consensus, use its valid-after as the beginning of the current round.
- If we have no consensus but we're an authority, use our own
- schedule. Otherwise, try using our view of the voting interval
- to figure out when the current round _should_ be starting.
- */
- networkstatus_t *ns = networkstatus_get_live_consensus(approx_time());
+ /* This function is not used for voting purposes, so if we have a reasonably
+ * live consensus, use its valid-after as the beginning of the current
+ * round. If we have no consensus but we're an authority, use our own
+ * schedule. Otherwise, try using our view of the voting interval to figure
+ * out when the current round _should_ be starting. */
+ networkstatus_t *ns =
+ networkstatus_get_reasonably_live_consensus(approx_time(),
+ usable_consensus_flavor());
if (ns) {
beginning_of_curr_round = ns->valid_after;
+ } else if (authdir_mode(get_options()) || ASSUME_AUTHORITY_SCHEDULING) {
+ beginning_of_curr_round = dirauth_sched_get_cur_valid_after_time();
} else {
- beginning_of_curr_round = get_start_time_of_current_round();
+ /* voting_interval comes from get_voting_interval(), so if we're in
+ * this case as a client, we already tried to get the voting interval
+ * from the latest_consensus and gave a bug warning if we couldn't.
+ *
+ * We wouldn't want to look at the latest consensus's valid_after time,
+ * since that would be out of date. */
+ beginning_of_curr_round = voting_sched_get_start_of_interval_after(
+ approx_time() - voting_interval,
+ voting_interval,
+ 0);
}
/* Get current SR protocol round */
diff --cc src/test/test_hs_service.c
index 80383baff8,49c8d29d27..8b94bb6cf1
--- a/src/test/test_hs_service.c
+++ b/src/test/test_hs_service.c
@@@ -89,13 -88,6 +90,14 @@@ mock_networkstatus_get_reasonably_live_
return &mock_ns;
}
+static networkstatus_t *
- mock_networkstatus_get_live_consensus_null(time_t now)
++mock_networkstatus_get_reasonably_live_consensus_null(time_t now, int flavor)
+{
+ (void) now;
++ (void) flavor;
+ return NULL;
+}
+
static or_state_t *dummy_state = NULL;
/* Mock function to get fake or state (used for rev counters) */
@@@ -2199,490 -2170,6 +2201,490 @@@ test_export_client_circuit_id(void *arg
tor_free(cp2);
}
+static smartlist_t *
+mock_node_get_link_specifier_smartlist(const node_t *node, bool direct_conn)
+{
+ (void) node;
+ (void) direct_conn;
+
+ smartlist_t *lspecs = smartlist_new();
+ link_specifier_t *ls_legacy = link_specifier_new();
+ smartlist_add(lspecs, ls_legacy);
+
+ return lspecs;
+}
+
+static node_t *fake_node = NULL;
+
+static const node_t *
+mock_build_state_get_exit_node(cpath_build_state_t *state)
+{
+ (void) state;
+
+ if (!fake_node) {
+ curve25519_secret_key_t seckey;
+ curve25519_secret_key_generate(&seckey, 0);
+
+ fake_node = tor_malloc_zero(sizeof(node_t));
+ fake_node->ri = tor_malloc_zero(sizeof(routerinfo_t));
+ fake_node->ri->onion_curve25519_pkey =
+ tor_malloc_zero(sizeof(curve25519_public_key_t));
+ curve25519_public_key_generate(fake_node->ri->onion_curve25519_pkey,
+ &seckey);
+ }
+
+ return fake_node;
+}
+
+static void
+mock_launch_rendezvous_point_circuit(const hs_service_t *service,
+ const hs_service_intro_point_t *ip,
+ const hs_cell_introduce2_data_t *data)
+{
+ (void) service;
+ (void) ip;
+ (void) data;
+ return;
+}
+
+/**
+ * Test that INTRO2 cells are handled well by onion services in the normal
+ * case and also when onionbalance is enabled.
+ */
+static void
+test_intro2_handling(void *arg)
+{
+ (void)arg;
+
+ MOCK(build_state_get_exit_node, mock_build_state_get_exit_node);
+ MOCK(relay_send_command_from_edge_, mock_relay_send_command_from_edge);
+ MOCK(node_get_link_specifier_smartlist,
+ mock_node_get_link_specifier_smartlist);
+ MOCK(launch_rendezvous_point_circuit, mock_launch_rendezvous_point_circuit);
+
+ memset(relay_payload, 0, sizeof(relay_payload));
+
+ int retval;
+ time_t now = 0101010101;
+ update_approx_time(now);
+
+ /** OK this is the play:
+ *
+ * In Act I, we have a standalone onion service X (without onionbalance
+ * enabled). We test that X can properly handle INTRO2 cells sent by a
+ * client Alice.
+ *
+ * In Act II, we create an onionbalance setup with frontend being Z which
+ * includes instances X and Y. We then setup onionbalance on X and test that
+ * Alice who addresses Z can communicate with X through INTRO2 cells.
+ *
+ * In Act III, we test that Alice can also communicate with X
+ * directly even tho onionbalance is enabled.
+ *
+ * And finally in Act IV, we check various cases where the INTRO2 cell
+ * should not go through because the subcredentials don't line up
+ * (e.g. Alice sends INTRO2 to X using Y's subcredential).
+ */
+
+ /** Let's start with some setup! Create the instances and the frontend
+ service, create Alice, etc: */
+
+ /* Create instance X */
+ hs_service_t x_service;
+ memset(&x_service, 0, sizeof(hs_service_t));
+ /* Disable onionbalance */
+ x_service.config.ob_master_pubkeys = NULL;
+ x_service.state.replay_cache_rend_cookie = replaycache_new(0,0);
+
+ /* Create subcredential for x: */
+ ed25519_keypair_t x_identity_keypair;
+ hs_subcredential_t x_subcred;
+ ed25519_keypair_generate(&x_identity_keypair, 0);
+ hs_helper_get_subcred_from_identity_keypair(&x_identity_keypair,
+ &x_subcred);
+
+ /* Create the x instance's intro point */
+ hs_service_intro_point_t *x_ip = NULL;
+ {
+ curve25519_secret_key_t seckey;
+ curve25519_public_key_t pkey;
+ curve25519_secret_key_generate(&seckey, 0);
+ curve25519_public_key_generate(&pkey, &seckey);
+
+ node_t intro_node;
+ memset(&intro_node, 0, sizeof(intro_node));
+ routerinfo_t ri;
+ memset(&ri, 0, sizeof(routerinfo_t));
+ ri.onion_curve25519_pkey = &pkey;
+ intro_node.ri = &ri;
+
+ x_ip = service_intro_point_new(&intro_node);
+ }
+
+ /* Create z frontend's subcredential */
+ ed25519_keypair_t z_identity_keypair;
+ hs_subcredential_t z_subcred;
+ ed25519_keypair_generate(&z_identity_keypair, 0);
+ hs_helper_get_subcred_from_identity_keypair(&z_identity_keypair,
+ &z_subcred);
+
+ /* Create y instance's subcredential */
+ ed25519_keypair_t y_identity_keypair;
+ hs_subcredential_t y_subcred;
+ ed25519_keypair_generate(&y_identity_keypair, 0);
+ hs_helper_get_subcred_from_identity_keypair(&y_identity_keypair,
+ &y_subcred);
+
+ /* Create Alice's intro point */
+ hs_desc_intro_point_t *alice_ip;
+ ed25519_keypair_t signing_kp;
+ ed25519_keypair_generate(&signing_kp, 0);
+ alice_ip = hs_helper_build_intro_point(&signing_kp, now, "1.2.3.4", 0,
+ &x_ip->auth_key_kp,
+ &x_ip->enc_key_kp);
+
+ /* Create Alice's intro and rend circuits */
+ origin_circuit_t *intro_circ = origin_circuit_new();
+ intro_circ->cpath = tor_malloc_zero(sizeof(crypt_path_t));
+ intro_circ->cpath->prev = intro_circ->cpath;
+ intro_circ->hs_ident = tor_malloc_zero(sizeof(*intro_circ->hs_ident));
+ origin_circuit_t rend_circ;
+ rend_circ.hs_ident = tor_malloc_zero(sizeof(*rend_circ.hs_ident));
+ curve25519_keypair_generate(&rend_circ.hs_ident->rendezvous_client_kp, 0);
+ memset(rend_circ.hs_ident->rendezvous_cookie, 'r', HS_REND_COOKIE_LEN);
+
+ /* ************************************************************ */
+
+ /* Act I:
+ *
+ * Where Alice connects to X without onionbalance in the picture */
+
+ /* Create INTRODUCE1 */
+ tt_assert(fast_mem_is_zero(relay_payload, sizeof(relay_payload)));
+ retval = hs_circ_send_introduce1(intro_circ, &rend_circ,
+ alice_ip, &x_subcred);
+
+ /* Check that the payload was written successfully */
+ tt_int_op(retval, OP_EQ, 0);
+ tt_assert(!fast_mem_is_zero(relay_payload, sizeof(relay_payload)));
+ tt_int_op(relay_payload_len, OP_NE, 0);
+
+ /* Handle the cell */
+ retval = hs_circ_handle_introduce2(&x_service,
+ intro_circ, x_ip,
+ &x_subcred,
+ (uint8_t*)relay_payload,relay_payload_len);
+ tt_int_op(retval, OP_EQ, 0);
+
+ /* ************************************************************ */
+
+ /* Act II:
+ *
+ * We now create an onionbalance setup with Z being the frontend and X and Y
+ * being the backend instances. Make sure that Alice can talk with the
+ * backend instance X even tho she thinks she is talking to the frontend Z.
+ */
+
+ /* Now configure the X instance to do onionbalance with Z as the frontend */
+ x_service.config.ob_master_pubkeys = smartlist_new();
+ smartlist_add(x_service.config.ob_master_pubkeys,
+ &z_identity_keypair.pubkey);
+
+ /* Create descriptors for x and load next descriptor with the x's
+ * subcredential so that it can accept connections for itself. */
+ x_service.desc_current = service_descriptor_new();
+ memset(x_service.desc_current->desc->subcredential.subcred, 'C',SUBCRED_LEN);
+ x_service.desc_next = service_descriptor_new();
+ memcpy(&x_service.desc_next->desc->subcredential, &x_subcred, SUBCRED_LEN);
+
+ /* Refresh OB keys */
+ hs_ob_refresh_keys(&x_service);
+
+ /* Create INTRODUCE1 from Alice to X through Z */
+ memset(relay_payload, 0, sizeof(relay_payload));
+ retval = hs_circ_send_introduce1(intro_circ, &rend_circ,
+ alice_ip, &z_subcred);
+
+ /* Check that the payload was written successfully */
+ tt_int_op(retval, OP_EQ, 0);
+ tt_assert(!fast_mem_is_zero(relay_payload, sizeof(relay_payload)));
+ tt_int_op(relay_payload_len, OP_NE, 0);
+
+ /* Deliver INTRODUCE1 to X even tho it carries Z's subcredential */
+ replaycache_free(x_service.state.replay_cache_rend_cookie);
+ x_service.state.replay_cache_rend_cookie = replaycache_new(0, 0);
+
+ retval = hs_circ_handle_introduce2(&x_service,
+ intro_circ, x_ip,
+ &z_subcred,
+ (uint8_t*)relay_payload, relay_payload_len);
+ tt_int_op(retval, OP_EQ, 0);
+
+ replaycache_free(x_ip->replay_cache);
+ x_ip->replay_cache = replaycache_new(0, 0);
+
+ replaycache_free(x_service.state.replay_cache_rend_cookie);
+ x_service.state.replay_cache_rend_cookie = replaycache_new(0, 0);
+
+ /* ************************************************************ */
+
+ /* Act III:
+ *
+ * Now send a direct INTRODUCE cell from Alice to X using X's subcredential
+ * and check that it succeeds even with onionbalance enabled.
+ */
+
+ /* Refresh OB keys (just to check for memleaks) */
+ hs_ob_refresh_keys(&x_service);
+
+ /* Create INTRODUCE1 from Alice to X using X's subcred. */
+ memset(relay_payload, 0, sizeof(relay_payload));
+ retval = hs_circ_send_introduce1(intro_circ, &rend_circ,
+ alice_ip, &x_subcred);
+
+ /* Check that the payload was written successfully */
+ tt_int_op(retval, OP_EQ, 0);
+ tt_assert(!fast_mem_is_zero(relay_payload, sizeof(relay_payload)));
+ tt_int_op(relay_payload_len, OP_NE, 0);
+
+ /* Send INTRODUCE1 to X with X's subcredential (should succeed) */
+ replaycache_free(x_service.state.replay_cache_rend_cookie);
+ x_service.state.replay_cache_rend_cookie = replaycache_new(0, 0);
+
+ retval = hs_circ_handle_introduce2(&x_service,
+ intro_circ, x_ip,
+ &x_subcred,
+ (uint8_t*)relay_payload, relay_payload_len);
+ tt_int_op(retval, OP_EQ, 0);
+
+ /* ************************************************************ */
+
+ /* Act IV:
+ *
+ * Test cases where the INTRO2 cell should not be able to decode.
+ */
+
+ /* Try sending the exact same INTRODUCE2 cell again and see that the intro
+ * point replay cache triggers: */
+ setup_full_capture_of_logs(LOG_WARN);
+ retval = hs_circ_handle_introduce2(&x_service,
+ intro_circ, x_ip,
+ &x_subcred,
+ (uint8_t*)relay_payload, relay_payload_len);
+ tt_int_op(retval, OP_EQ, -1);
+ expect_log_msg_containing("with the same ENCRYPTED section");
+ teardown_capture_of_logs();
+
+ /* Now cleanup the intro point replay cache but not the service replay cache
+ and see that this one triggers this time. */
+ replaycache_free(x_ip->replay_cache);
+ x_ip->replay_cache = replaycache_new(0, 0);
+ setup_full_capture_of_logs(LOG_INFO);
+ retval = hs_circ_handle_introduce2(&x_service,
+ intro_circ, x_ip,
+ &x_subcred,
+ (uint8_t*)relay_payload, relay_payload_len);
+ tt_int_op(retval, OP_EQ, -1);
+ expect_log_msg_containing("with same REND_COOKIE");
+ teardown_capture_of_logs();
+
+ /* Now just to make sure cleanup both replay caches and make sure that the
+ cell gets through */
+ replaycache_free(x_ip->replay_cache);
+ x_ip->replay_cache = replaycache_new(0, 0);
+ replaycache_free(x_service.state.replay_cache_rend_cookie);
+ x_service.state.replay_cache_rend_cookie = replaycache_new(0, 0);
+ retval = hs_circ_handle_introduce2(&x_service,
+ intro_circ, x_ip,
+ &x_subcred,
+ (uint8_t*)relay_payload, relay_payload_len);
+ tt_int_op(retval, OP_EQ, 0);
+
+ /* As a final thing, create an INTRODUCE1 cell from Alice to X using Y's
+ * subcred (should fail since Y is just another instance and not the frontend
+ * service!) */
+ memset(relay_payload, 0, sizeof(relay_payload));
+ retval = hs_circ_send_introduce1(intro_circ, &rend_circ,
+ alice_ip, &y_subcred);
+ tt_int_op(retval, OP_EQ, 0);
+
+ /* Check that the payload was written successfully */
+ tt_assert(!fast_mem_is_zero(relay_payload, sizeof(relay_payload)));
+ tt_int_op(relay_payload_len, OP_NE, 0);
+
+ retval = hs_circ_handle_introduce2(&x_service,
+ intro_circ, x_ip,
+ &y_subcred,
+ (uint8_t*)relay_payload, relay_payload_len);
+ tt_int_op(retval, OP_EQ, -1);
+
+ done:
+ /* Start cleaning up X */
+ replaycache_free(x_service.state.replay_cache_rend_cookie);
+ smartlist_free(x_service.config.ob_master_pubkeys);
+ tor_free(x_service.state.ob_subcreds);
+ service_descriptor_free(x_service.desc_current);
+ service_descriptor_free(x_service.desc_next);
+ service_intro_point_free(x_ip);
+
+ /* Clean up Alice */
+ hs_desc_intro_point_free(alice_ip);
+ tor_free(rend_circ.hs_ident);
+
+ if (fake_node) {
+ tor_free(fake_node->ri->onion_curve25519_pkey);
+ tor_free(fake_node->ri);
+ tor_free(fake_node);
+ }
+
+ UNMOCK(build_state_get_exit_node);
+ UNMOCK(relay_send_command_from_edge_);
+ UNMOCK(node_get_link_specifier_smartlist);
+ UNMOCK(launch_rendezvous_point_circuit);
+}
+
+static void
+test_cannot_upload_descriptors(void *arg)
+{
+ int ret;
+ time_t now;
+ hs_service_t *service;
+
+ (void) arg;
+
+ hs_init();
+ MOCK(get_or_state,
+ get_or_state_replacement);
- MOCK(networkstatus_get_live_consensus,
- mock_networkstatus_get_live_consensus);
++ MOCK(networkstatus_get_reasonably_live_consensus,
++ mock_networkstatus_get_reasonably_live_consensus);
+
+ dummy_state = or_state_new();
+
+ ret = parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC",
+ &mock_ns.valid_after);
+ tt_int_op(ret, OP_EQ, 0);
+ ret = parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC",
+ &mock_ns.fresh_until);
+ tt_int_op(ret, OP_EQ, 0);
+ dirauth_sched_recalculate_timing(get_options(), mock_ns.valid_after);
+
+ update_approx_time(mock_ns.valid_after + 1);
+ now = mock_ns.valid_after + 1;
+
+ /* Create a service with no descriptor. It's added to the global map. */
+ service = hs_service_new(get_options());
+ tt_assert(service);
+ service->config.version = HS_VERSION_THREE;
+ ed25519_secret_key_generate(&service->keys.identity_sk, 0);
+ ed25519_public_key_generate(&service->keys.identity_pk,
+ &service->keys.identity_sk);
+ /* Register service to global map. */
+ ret = register_service(get_hs_service_map(), service);
+ tt_int_op(ret, OP_EQ, 0);
+ /* But first, build our descriptor. */
+ build_all_descriptors(now);
+
+ /* 1. Testing missing intro points reason. */
+ {
+ digest256map_t *cur = service->desc_current->intro_points.map;
+ digest256map_t *tmp = digest256map_new();
+ service->desc_current->intro_points.map = tmp;
+ service->desc_current->missing_intro_points = 1;
+ setup_full_capture_of_logs(LOG_INFO);
+ run_upload_descriptor_event(now);
+ digest256map_free(tmp, tor_free_);
+ service->desc_current->intro_points.map = cur;
+ expect_log_msg_containing(
+ "Service [scrubbed] can't upload its current descriptor: "
+ "Missing intro points");
+ teardown_capture_of_logs();
+ /* Reset. */
+ service->desc_current->missing_intro_points = 0;
+ }
+
+ /* 2. Testing non established intro points. */
+ {
+ setup_full_capture_of_logs(LOG_INFO);
+ run_upload_descriptor_event(now);
+ expect_log_msg_containing(
+ "Service [scrubbed] can't upload its current descriptor: "
+ "Intro circuits aren't yet all established (0/3).");
+ teardown_capture_of_logs();
+ }
+
+ /* We need to pass the established circuit tests and thus from now on, we
+ * MOCK this to return 3 intro points. */
+ MOCK(count_desc_circuit_established, mock_count_desc_circuit_established);
+ num_intro_points = 3;
+
+ /* 3. Testing non established intro points. */
+ {
+ service->desc_current->next_upload_time = now + 1000;
+ setup_full_capture_of_logs(LOG_INFO);
+ run_upload_descriptor_event(now);
+ expect_log_msg_containing(
+ "Service [scrubbed] can't upload its current descriptor: "
+ "Next upload time is");
+ teardown_capture_of_logs();
+ /* Reset. */
+ service->desc_current->next_upload_time = 0;
+ }
+
+ /* 4. Testing missing live consensus. */
+ {
- MOCK(networkstatus_get_live_consensus,
- mock_networkstatus_get_live_consensus_null);
++ MOCK(networkstatus_get_reasonably_live_consensus,
++ mock_networkstatus_get_reasonably_live_consensus_null);
+ setup_full_capture_of_logs(LOG_INFO);
+ run_upload_descriptor_event(now);
+ expect_log_msg_containing(
+ "Service [scrubbed] can't upload its current descriptor: "
- "No live consensus");
++ "No reasonably live consensus");
+ teardown_capture_of_logs();
+ /* Reset. */
- MOCK(networkstatus_get_live_consensus,
- mock_networkstatus_get_live_consensus);
++ MOCK(networkstatus_get_reasonably_live_consensus,
++ mock_networkstatus_get_reasonably_live_consensus);
+ }
+
+ /* 5. Test missing minimum directory information. */
+ {
+ MOCK(router_have_minimum_dir_info,
+ mock_router_have_minimum_dir_info_false);
+ setup_full_capture_of_logs(LOG_INFO);
+ run_upload_descriptor_event(now);
+ expect_log_msg_containing(
+ "Service [scrubbed] can't upload its current descriptor: "
+ "Not enough directory information");
+ teardown_capture_of_logs();
+
+ /* Running it again shouldn't trigger anything due to rate limitation. */
+ setup_full_capture_of_logs(LOG_INFO);
+ run_upload_descriptor_event(now);
+ expect_no_log_entry();
+ teardown_capture_of_logs();
+ UNMOCK(router_have_minimum_dir_info);
+ }
+
+ /* Increase time and redo test (5) in order to test the rate limiting. */
+ update_approx_time(mock_ns.valid_after + 61);
+ {
+ MOCK(router_have_minimum_dir_info,
+ mock_router_have_minimum_dir_info_false);
+ setup_full_capture_of_logs(LOG_INFO);
+ run_upload_descriptor_event(now);
+ expect_log_msg_containing(
+ "Service [scrubbed] can't upload its current descriptor: "
+ "Not enough directory information");
+ teardown_capture_of_logs();
+ UNMOCK(router_have_minimum_dir_info);
+ }
+
+ done:
+ hs_free_all();
+ UNMOCK(count_desc_circuit_established);
- UNMOCK(networkstatus_get_live_consensus);
++ UNMOCK(networkstatus_get_reasonably_live_consensus);
+ UNMOCK(get_or_state);
+}
+
struct testcase_t hs_service_tests[] = {
{ "e2e_rend_circuit_setup", test_e2e_rend_circuit_setup, TT_FORK,
NULL, NULL },
More information about the tor-commits
mailing list