[tor-commits] [tor/master] Merge remote-tracking branch 'public/prop298'

nickm at torproject.org nickm at torproject.org
Wed Dec 5 14:43:55 UTC 2018


commit 1eb3719a62074baef97ec1aa5c144096706fb97f
Merge: 1f95e8035 05dee063c
Author: Nick Mathewson <nickm at torproject.org>
Date:   Wed Dec 5 09:43:03 2018 -0500

    Merge remote-tracking branch 'public/prop298'

 changes/ticket28266                  |  10 ++
 src/feature/dirauth/dirvote.c        |  18 +++-
 src/feature/dirauth/dirvote.h        |   8 +-
 src/feature/nodelist/nodefamily.c    |  47 +++++++-
 src/feature/nodelist/nodefamily.h    |   5 +-
 src/feature/nodelist/nodefamily_st.h |   8 +-
 src/feature/relay/router.c           | 203 +++++++++++++++++++++++++----------
 src/feature/relay/router.h           |   4 +
 src/test/test_microdesc.c            |  35 +++++-
 src/test/test_nodelist.c             |  49 +++++++--
 src/test/test_router.c               | 154 ++++++++++++++++++++++++++
 11 files changed, 462 insertions(+), 79 deletions(-)

diff --cc src/feature/relay/router.h
index 217511df9,872eed1f4..7a63c33d3
--- a/src/feature/relay/router.h
+++ b/src/feature/relay/router.h
@@@ -117,10 -117,10 +117,14 @@@ void router_free_all(void)
  /* Used only by router.c and test.c */
  STATIC void get_platform_str(char *platform, size_t len);
  STATIC int router_write_fingerprint(int hashed);
+ STATIC smartlist_t *get_my_declared_family(const or_options_t *options);
++
  #ifdef TOR_UNIT_TESTS
 +extern time_t desc_clean_since;
 +extern const char *desc_dirty_reason;
+ void set_server_identity_key_digest_testing(const uint8_t *digest);
  #endif
++
  #endif
  
  #endif /* !defined(TOR_ROUTER_H) */
diff --cc src/test/test_router.c
index 18740dcb8,b92e96ff3..91cdd2c06
--- a/src/test/test_router.c
+++ b/src/test/test_router.c
@@@ -7,17 -7,16 +7,20 @@@
   * \brief Unittests for code in router.c
   **/
  
+ #define CONFIG_PRIVATE
  #define ROUTER_PRIVATE
 +
  #include "core/or/or.h"
  #include "app/config/config.h"
  #include "core/mainloop/mainloop.h"
  #include "feature/hibernate/hibernate.h"
 +#include "feature/nodelist/networkstatus.h"
 +#include "feature/nodelist/networkstatus_st.h"
+ #include "feature/nodelist/node_st.h"
+ #include "feature/nodelist/nodelist.h"
  #include "feature/nodelist/routerinfo_st.h"
  #include "feature/nodelist/routerlist.h"
 +#include "feature/nodelist/routerstatus_st.h"
  #include "feature/relay/router.h"
  #include "feature/stats/rephist.h"
  #include "lib/crypt_ops/crypto_curve25519.h"
@@@ -236,104 -236,161 +240,254 @@@ test_router_check_descriptor_bandwidth_
    UNMOCK(we_are_hibernating);
  }
  
 +static networkstatus_t *mock_ns = NULL;
 +static networkstatus_t *
 +mock_networkstatus_get_live_consensus(time_t now)
 +{
 +  (void)now;
 +  return mock_ns;
 +}
 +
 +static routerstatus_t *mock_rs = NULL;
 +static const routerstatus_t *
 +mock_networkstatus_vote_find_entry(networkstatus_t *ns, const char *digest)
 +{
 +  (void)ns;
 +  (void)digest;
 +  return mock_rs;
 +}
 +
 +static void
 +test_router_mark_if_too_old(void *arg)
 +{
 +  (void)arg;
 +  time_t now = approx_time();
 +  MOCK(networkstatus_get_live_consensus,
 +       mock_networkstatus_get_live_consensus);
 +  MOCK(networkstatus_vote_find_entry, mock_networkstatus_vote_find_entry);
 +
 +  routerstatus_t rs;
 +  networkstatus_t ns;
 +  memset(&rs, 0, sizeof(rs));
 +  memset(&ns, 0, sizeof(ns));
 +  mock_ns = &ns;
 +  mock_ns->valid_after = now-3600;
 +  mock_rs = &rs;
 +  mock_rs->published_on = now - 10;
 +
 +  // no reason to mark this time.
 +  desc_clean_since = now-10;
 +  desc_dirty_reason = NULL;
 +  mark_my_descriptor_dirty_if_too_old(now);
 +  tt_i64_op(desc_clean_since, OP_EQ, now-10);
 +
 +  // Doesn't appear in consensus?  Still don't mark it.
 +  mock_ns = NULL;
 +  mark_my_descriptor_dirty_if_too_old(now);
 +  tt_i64_op(desc_clean_since, OP_EQ, now-10);
 +  mock_ns = &ns;
 +
 +  // No new descriptor in a long time?  Mark it.
 +  desc_clean_since = now - 3600 * 96;
 +  mark_my_descriptor_dirty_if_too_old(now);
 +  tt_i64_op(desc_clean_since, OP_EQ, 0);
 +  tt_str_op(desc_dirty_reason, OP_EQ, "time for new descriptor");
 +
 +  // Version in consensus published a long time ago?  We won't mark it
 +  // if it's been clean for only a short time.
 +  desc_clean_since = now - 10;
 +  desc_dirty_reason = NULL;
 +  mock_rs->published_on = now - 3600 * 96;
 +  mark_my_descriptor_dirty_if_too_old(now);
 +  tt_i64_op(desc_clean_since, OP_EQ, now - 10);
 +
 +  // ... but if it's been clean a while, we mark.
 +  desc_clean_since = now - 2 * 3600;
 +  mark_my_descriptor_dirty_if_too_old(now);
 +  tt_i64_op(desc_clean_since, OP_EQ, 0);
 +  tt_str_op(desc_dirty_reason, OP_EQ,
 +            "version listed in consensus is quite old");
 +
 +  // same deal if we're marked stale.
 +  desc_clean_since = now - 2 * 3600;
 +  desc_dirty_reason = NULL;
 +  mock_rs->published_on = now - 10;
 +  mock_rs->is_staledesc = 1;
 +  mark_my_descriptor_dirty_if_too_old(now);
 +  tt_i64_op(desc_clean_since, OP_EQ, 0);
 +  tt_str_op(desc_dirty_reason, OP_EQ,
 +            "listed as stale in consensus");
 +
 +  // same deal if we're absent from the consensus.
 +  desc_clean_since = now - 2 * 3600;
 +  desc_dirty_reason = NULL;
 +  mock_rs = NULL;
 +  mark_my_descriptor_dirty_if_too_old(now);
 +  tt_i64_op(desc_clean_since, OP_EQ, 0);
 +  tt_str_op(desc_dirty_reason, OP_EQ,
 +            "not listed in consensus");
 +
 + done:
 +  UNMOCK(networkstatus_get_live_consensus);
 +  UNMOCK(networkstatus_vote_find_entry);
 +}
 +
+ static node_t fake_node;
+ static const node_t *
+ mock_node_get_by_nickname(const char *name, unsigned flags)
+ {
+   (void)flags;
+   if (!strcasecmp(name, "crumpet"))
+     return &fake_node;
+   else
+     return NULL;
+ }
+ 
+ static void
+ test_router_get_my_family(void *arg)
+ {
+   (void)arg;
+   or_options_t *options = options_new();
+   smartlist_t *sl = NULL;
+   char *join = NULL;
+   // Overwrite the result of router_get_my_identity_digest().  This
+   // happens to be okay, but only for testing.
+   set_server_identity_key_digest_testing(
+                                    (const uint8_t*)"holeinthebottomofthe");
+ 
+   setup_capture_of_logs(LOG_WARN);
+ 
+   // No family listed -- so there's no list.
+   sl = get_my_declared_family(options);
+   tt_ptr_op(sl, OP_EQ, NULL);
+   expect_no_log_entry();
+ 
+ #define CLEAR() do {                                    \
+     if (sl) {                                           \
+       SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));  \
+       smartlist_free(sl);                               \
+     }                                                   \
+     tor_free(join);                                     \
+     mock_clean_saved_logs();                            \
+   } while (0)
+ 
+   // Add a single nice friendly hex member.  This should be enough
+   // to have our own ID added.
+   tt_ptr_op(options->MyFamily, OP_EQ, NULL);
+   config_line_append(&options->MyFamily, "MyFamily",
+                      "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
+ 
+   sl = get_my_declared_family(options);
+   tt_ptr_op(sl, OP_NE, NULL);
+   tt_int_op(smartlist_len(sl), OP_EQ, 2);
+   join = smartlist_join_strings(sl, " ", 0, NULL);
+   tt_str_op(join, OP_EQ,
+             "$686F6C65696E746865626F74746F6D6F66746865 "
+             "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
+   expect_no_log_entry();
+   CLEAR();
+ 
+   // Add a hex member with a ~.  The ~ part should get removed.
+   config_line_append(&options->MyFamily, "MyFamily",
+                      "$0123456789abcdef0123456789abcdef01234567~Muffin");
+   sl = get_my_declared_family(options);
+   tt_ptr_op(sl, OP_NE, NULL);
+   tt_int_op(smartlist_len(sl), OP_EQ, 3);
+   join = smartlist_join_strings(sl, " ", 0, NULL);
+   tt_str_op(join, OP_EQ,
+             "$0123456789ABCDEF0123456789ABCDEF01234567 "
+             "$686F6C65696E746865626F74746F6D6F66746865 "
+             "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
+   expect_no_log_entry();
+   CLEAR();
+ 
+   // Nickname lookup will fail, so a nickname will appear verbatim.
+   config_line_append(&options->MyFamily, "MyFamily",
+                      "BAGEL");
+   sl = get_my_declared_family(options);
+   tt_ptr_op(sl, OP_NE, NULL);
+   tt_int_op(smartlist_len(sl), OP_EQ, 4);
+   join = smartlist_join_strings(sl, " ", 0, NULL);
+   tt_str_op(join, OP_EQ,
+             "$0123456789ABCDEF0123456789ABCDEF01234567 "
+             "$686F6C65696E746865626F74746F6D6F66746865 "
+             "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA "
+             "bagel");
+   expect_single_log_msg_containing(
+            "There is a router named \"BAGEL\" in my declared family, but "
+            "I have no descriptor for it.");
+   CLEAR();
+ 
+   // A bogus digest should fail entirely.
+   config_line_append(&options->MyFamily, "MyFamily",
+                      "$painauchocolat");
+   sl = get_my_declared_family(options);
+   tt_ptr_op(sl, OP_NE, NULL);
+   tt_int_op(smartlist_len(sl), OP_EQ, 4);
+   join = smartlist_join_strings(sl, " ", 0, NULL);
+   tt_str_op(join, OP_EQ,
+             "$0123456789ABCDEF0123456789ABCDEF01234567 "
+             "$686F6C65696E746865626F74746F6D6F66746865 "
+             "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA "
+             "bagel");
+   // "BAGEL" is still there, but it won't make a warning, because we already
+   // warned about it.
+   expect_single_log_msg_containing(
+            "There is a router named \"$painauchocolat\" in my declared "
+            "family, but that isn't a legal digest or nickname. Skipping it.");
+   CLEAR();
+ 
+   // Let's introduce a node we can look up by nickname
+   memset(&fake_node, 0, sizeof(fake_node));
+   memcpy(fake_node.identity, "whydoyouasknonononon", DIGEST_LEN);
+   MOCK(node_get_by_nickname, mock_node_get_by_nickname);
+ 
+   config_line_append(&options->MyFamily, "MyFamily",
+                      "CRUmpeT");
+   sl = get_my_declared_family(options);
+   tt_ptr_op(sl, OP_NE, NULL);
+   tt_int_op(smartlist_len(sl), OP_EQ, 5);
+   join = smartlist_join_strings(sl, " ", 0, NULL);
+   tt_str_op(join, OP_EQ,
+             "$0123456789ABCDEF0123456789ABCDEF01234567 "
+             "$686F6C65696E746865626F74746F6D6F66746865 "
+             "$776879646F796F7561736B6E6F6E6F6E6F6E6F6E "
+             "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA "
+             "bagel");
+   // "BAGEL" is still there, but it won't make a warning, because we already
+   // warned about it.  Some with "$painauchocolat".
+   expect_single_log_msg_containing(
+            "There is a router named \"CRUmpeT\" in my declared "
+            "family, but it wasn't listed by digest. Please consider saying "
+            "$776879646F796F7561736B6E6F6E6F6E6F6E6F6E instead, if that's "
+            "what you meant.");
+   CLEAR();
+   UNMOCK(node_get_by_nickname);
+ 
+   // Try a singleton list containing only us: It should give us NULL.
+   config_free_lines(options->MyFamily);
+   config_line_append(&options->MyFamily, "MyFamily",
+                      "$686F6C65696E746865626F74746F6D6F66746865");
+   sl = get_my_declared_family(options);
+   tt_ptr_op(sl, OP_EQ, NULL);
+   expect_no_log_entry();
+ 
+  done:
+   or_options_free(options);
+   teardown_capture_of_logs();
+   CLEAR();
+   UNMOCK(node_get_by_nickname);
+ 
+ #undef CLEAR
+ }
+ 
  #define ROUTER_TEST(name, flags)                          \
    { #name, test_router_ ## name, flags, NULL, NULL }
  
  struct testcase_t router_tests[] = {
    ROUTER_TEST(check_descriptor_bandwidth_changed, TT_FORK),
    ROUTER_TEST(dump_router_to_string_no_bridge_distribution_method, TT_FORK),
 +  ROUTER_TEST(mark_if_too_old, TT_FORK),
+   ROUTER_TEST(get_my_family, TT_FORK),
    END_OF_TESTCASES
  };



More information about the tor-commits mailing list