[tor-commits] [tor/master] test_dir: Unit tests for RSA-only router and extrainfo descriptor creation

asn at torproject.org asn at torproject.org
Tue Mar 26 13:37:54 UTC 2019


commit 53b49d1a35d2e7abf1cc7aff15553c23dde0f352
Author: teor <teor at torproject.org>
Date:   Mon Feb 18 15:24:26 2019 +1000

    test_dir: Unit tests for RSA-only router and extrainfo descriptor creation
    
    Tests 29017 and 29018.
---
 src/feature/nodelist/torcert.c |   4 +-
 src/feature/nodelist/torcert.h |   2 +-
 src/feature/relay/router.c     |  18 +++---
 src/feature/relay/router.h     |  12 +++-
 src/test/test_dir.c            | 134 ++++++++++++++++++++++++++++++++++++++---
 5 files changed, 146 insertions(+), 24 deletions(-)

diff --git a/src/feature/nodelist/torcert.c b/src/feature/nodelist/torcert.c
index b0197e9f1..56f1a8ac9 100644
--- a/src/feature/nodelist/torcert.c
+++ b/src/feature/nodelist/torcert.c
@@ -290,8 +290,8 @@ tor_cert_describe_signature_status(const tor_cert_t *cert)
 }
 
 /** Return a new copy of <b>cert</b> */
-tor_cert_t *
-tor_cert_dup(const tor_cert_t *cert)
+MOCK_IMPL(tor_cert_t *,
+tor_cert_dup,(const tor_cert_t *cert))
 {
   tor_cert_t *newcert = tor_memdup(cert, sizeof(tor_cert_t));
   if (cert->encoded)
diff --git a/src/feature/nodelist/torcert.h b/src/feature/nodelist/torcert.h
index 492275b51..03d5bdca9 100644
--- a/src/feature/nodelist/torcert.h
+++ b/src/feature/nodelist/torcert.h
@@ -71,7 +71,7 @@ int tor_cert_checksig(tor_cert_t *cert,
                       const ed25519_public_key_t *pubkey, time_t now);
 const char *tor_cert_describe_signature_status(const tor_cert_t *cert);
 
-tor_cert_t *tor_cert_dup(const tor_cert_t *cert);
+MOCK_DECL(tor_cert_t *,tor_cert_dup,(const tor_cert_t *cert));
 int tor_cert_eq(const tor_cert_t *cert1, const tor_cert_t *cert2);
 int tor_cert_opt_eq(const tor_cert_t *cert1, const tor_cert_t *cert2);
 
diff --git a/src/feature/relay/router.c b/src/feature/relay/router.c
index 7e2161ef3..18c837529 100644
--- a/src/feature/relay/router.c
+++ b/src/feature/relay/router.c
@@ -196,8 +196,8 @@ set_onion_key(crypto_pk_t *k)
 
 /** Return the current onion key.  Requires that the onion key has been
  * loaded or generated. */
-crypto_pk_t *
-get_onion_key(void)
+MOCK_IMPL(crypto_pk_t *,
+get_onion_key,(void))
 {
   tor_assert(onionkey);
   return onionkey;
@@ -376,8 +376,8 @@ assert_identity_keys_ok(void)
 /** Returns the current server identity key; requires that the key has
  * been set, and that we are running as a Tor server.
  */
-crypto_pk_t *
-get_server_identity_key(void)
+MOCK_IMPL(crypto_pk_t *,
+get_server_identity_key,(void))
 {
   tor_assert(server_identitykey);
   tor_assert(server_mode(get_options()));
@@ -1951,8 +1951,8 @@ get_my_declared_family(const or_options_t *options)
  *
  * Returns a negative value and sets ri_out to NULL on temporary error.
  */
-static int
-router_build_fresh_unsigned_routerinfo(routerinfo_t **ri_out)
+MOCK_IMPL(STATIC int,
+router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out))
 {
   routerinfo_t *ri = NULL;
   uint32_t addr;
@@ -2171,7 +2171,7 @@ router_dump_and_sign_extrainfo_descriptor_body(extrainfo_t *ei)
  * If ri is NULL, logs a BUG() warning and returns NULL.
  * Caller is responsible for freeing the generated extrainfo.
  */
-static extrainfo_t *
+STATIC extrainfo_t *
 router_build_fresh_signed_extrainfo(const routerinfo_t *ri)
 {
   int result = -1;
@@ -2203,7 +2203,7 @@ router_build_fresh_signed_extrainfo(const routerinfo_t *ri)
  *
  * If ei is NULL, logs a BUG() warning and zeroes the relevant fields.
  */
-static void
+STATIC void
 router_update_routerinfo_from_extrainfo(routerinfo_t *ri,
                                         const extrainfo_t *ei)
 {
@@ -2231,7 +2231,7 @@ router_update_routerinfo_from_extrainfo(routerinfo_t *ri,
  * If ri is NULL, logs a BUG() warning and returns a negative value.
  * On error, ri->cache_info is not modified.
  */
-static int
+STATIC int
 router_dump_and_sign_routerinfo_descriptor_body(routerinfo_t *ri)
 {
   if (BUG(!ri))
diff --git a/src/feature/relay/router.h b/src/feature/relay/router.h
index 497d8d243..d4ad52c9d 100644
--- a/src/feature/relay/router.h
+++ b/src/feature/relay/router.h
@@ -25,10 +25,10 @@ struct ed25519_keypair_t;
 #define TOR_ROUTERINFO_ERROR_DESC_REBUILDING (-6)
 #define TOR_ROUTERINFO_ERROR_INTERNAL_BUG    (-7)
 
-crypto_pk_t *get_onion_key(void);
+MOCK_DECL(crypto_pk_t *,get_onion_key,(void));
 time_t get_onion_key_set_at(void);
 void set_server_identity_key(crypto_pk_t *k);
-crypto_pk_t *get_server_identity_key(void);
+MOCK_DECL(crypto_pk_t *,get_server_identity_key,(void));
 int server_identity_key_is_set(void);
 void set_client_identity_key(crypto_pk_t *k);
 crypto_pk_t *get_tlsclient_identity_key(void);
@@ -124,6 +124,14 @@ STATIC smartlist_t *get_my_declared_family(const or_options_t *options);
 extern time_t desc_clean_since;
 extern const char *desc_dirty_reason;
 void set_server_identity_key_digest_testing(const uint8_t *digest);
+
+MOCK_DECL(STATIC int,
+              router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out));
+STATIC extrainfo_t *router_build_fresh_signed_extrainfo(
+                                                      const routerinfo_t *ri);
+STATIC void router_update_routerinfo_from_extrainfo(routerinfo_t *ri,
+                                                    const extrainfo_t *ei);
+STATIC int router_dump_and_sign_routerinfo_descriptor_body(routerinfo_t *ri);
 #endif
 
 #endif
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index 4132d42d1..57adee414 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -171,6 +171,31 @@ mock_get_configured_ports(void)
   return mocked_configured_ports;
 }
 
+static tor_cert_t *
+mock_tor_cert_dup_null(const tor_cert_t *cert)
+{
+  (void)cert;
+  return NULL;
+}
+
+static crypto_pk_t *mocked_server_identitykey = NULL;
+
+/* Returns mocked_server_identitykey with no checks. */
+static crypto_pk_t *
+mock_get_server_identity_key(void)
+{
+  return mocked_server_identitykey;
+}
+
+static crypto_pk_t *mocked_onionkey = NULL;
+
+/* Returns mocked_onionkey with no checks. */
+static crypto_pk_t *
+mock_get_onion_key(void)
+{
+  return mocked_onionkey;
+}
+
 /** Run unit tests for router descriptor generation logic. */
 static void
 test_dir_formats(void *arg)
@@ -182,8 +207,11 @@ test_dir_formats(void *arg)
   char *pk1_str = NULL, *pk2_str = NULL, *cp;
   size_t pk1_str_len, pk2_str_len;
   routerinfo_t *r1=NULL, *r2=NULL;
+  extrainfo_t *e1 = NULL, *e2 = NULL;
   crypto_pk_t *pk1 = NULL, *pk2 = NULL;
+  routerinfo_t *r2_out = NULL;
   routerinfo_t *rp1 = NULL, *rp2 = NULL;
+  extrainfo_t *ep1 = NULL, *ep2 = NULL;
   addr_policy_t *ex1, *ex2;
   routerlist_t *dir1 = NULL, *dir2 = NULL;
   uint8_t *rsa_cc = NULL;
@@ -192,6 +220,8 @@ test_dir_formats(void *arg)
   time_t now = time(NULL);
   port_cfg_t orport, dirport;
   char cert_buf[256];
+  int rv = -1;
+  const char *msg = NULL;
 
   (void)arg;
   pk1 = pk_generate(0);
@@ -202,6 +232,8 @@ test_dir_formats(void *arg)
   hibernate_set_state_for_testing_(HIBERNATE_STATE_LIVE);
 
   get_platform_str(platform, sizeof(platform));
+
+  /* r1 is a minimal, RSA-only descriptor */
   r1 = tor_malloc_zero(sizeof(routerinfo_t));
   r1->addr = 0xc0a80001u; /* 192.168.0.1 */
   r1->cache_info.published_on = 0;
@@ -224,6 +256,7 @@ test_dir_formats(void *arg)
   r1->nickname = tor_strdup("Magri");
   r1->platform = tor_strdup(platform);
 
+  /* r2 is a RSA + ed25519 descriptor, with an exit policy */
   ex1 = tor_malloc_zero(sizeof(addr_policy_t));
   ex2 = tor_malloc_zero(sizeof(addr_policy_t));
   ex1->policy_type = ADDR_POLICY_ACCEPT;
@@ -352,8 +385,86 @@ test_dir_formats(void *arg)
   crypto_pk_free(onion_pkey);
   tt_int_op(crypto_pk_cmp_keys(rp1->identity_pkey, pk2), OP_EQ, 0);
   tt_assert(rp1->supports_tunnelled_dir_requests);
-  //tt_assert(rp1->exit_policy == NULL);
+  tt_assert(rp1->policy_is_reject_star);
+
   tor_free(buf);
+  routerinfo_free(rp1);
+
+  /* Test extrainfo creation.
+   * We avoid calling router_build_fresh_unsigned_routerinfo(), because it's
+   * too complex. Instead, we re-use the manually-created routerinfos.
+   */
+
+  /* router_build_fresh_signed_extrainfo() requires options->Nickname */
+  tor_free(options->Nickname);
+  options->Nickname = tor_strdup(r1->nickname);
+  /* router_build_fresh_signed_extrainfo() passes the result of
+   * get_master_signing_key_cert() directly to tor_cert_dup(), which fails on
+   * NULL. But we want a NULL ei->cache_info.signing_key_cert to test the
+   * non-ed key path.
+   */
+  MOCK(tor_cert_dup, mock_tor_cert_dup_null);
+  /* router_build_fresh_signed_extrainfo() requires get_server_identity_key().
+   * Use the same one as the call to router_dump_router_to_string() above.
+   */
+  mocked_server_identitykey = pk2;
+  MOCK(get_server_identity_key, mock_get_server_identity_key);
+  /* router_dump_and_sign_routerinfo_descriptor_body() requires
+   * get_onion_key(). Use the same one as r1.
+   */
+  mocked_onionkey = pk1;
+  MOCK(get_onion_key, mock_get_onion_key);
+
+  /* Test some of the low-level static functions. */
+  e1 = router_build_fresh_signed_extrainfo(r1);
+  tt_assert(e1);
+  router_update_routerinfo_from_extrainfo(r1, e1);
+  rv = router_dump_and_sign_routerinfo_descriptor_body(r1);
+  tt_assert(rv == 0);
+  msg = "";
+  rv = routerinfo_incompatible_with_extrainfo(r1->identity_pkey, e1,
+                                              &r1->cache_info, &msg);
+  tt_str_op(msg, OP_EQ, "");
+  tt_assert(rv == 0);
+
+  /* Now cleanup */
+  tor_free(options->Nickname);
+  UNMOCK(tor_cert_dup);
+  mocked_server_identitykey = NULL;
+  UNMOCK(get_server_identity_key);
+  mocked_onionkey = NULL;
+  UNMOCK(get_onion_key);
+
+  /* Test that the signed ri is parseable */
+  tt_assert(r1->cache_info.signed_descriptor_body);
+  cp = r1->cache_info.signed_descriptor_body;
+  rp1 = router_parse_entry_from_string((const char*)cp,NULL,1,0,NULL,NULL);
+  tt_assert(rp1);
+  tt_int_op(rp1->addr,OP_EQ, r1->addr);
+  tt_int_op(rp1->or_port,OP_EQ, r1->or_port);
+  tt_int_op(rp1->dir_port,OP_EQ, r1->dir_port);
+  tt_int_op(rp1->bandwidthrate,OP_EQ, r1->bandwidthrate);
+  tt_int_op(rp1->bandwidthburst,OP_EQ, r1->bandwidthburst);
+  tt_int_op(rp1->bandwidthcapacity,OP_EQ, r1->bandwidthcapacity);
+  onion_pkey = router_get_rsa_onion_pkey(rp1->onion_pkey,
+                                         rp1->onion_pkey_len);
+  tt_int_op(crypto_pk_cmp_keys(onion_pkey, pk1), OP_EQ, 0);
+  crypto_pk_free(onion_pkey);
+  tt_int_op(crypto_pk_cmp_keys(rp1->identity_pkey, pk2), OP_EQ, 0);
+  tt_assert(rp1->supports_tunnelled_dir_requests);
+  tt_assert(rp1->policy_is_reject_star);
+
+  routerinfo_free(rp1);
+
+  /* Test that the signed ei is parseable */
+  tt_assert(e1->cache_info.signed_descriptor_body);
+  cp = e1->cache_info.signed_descriptor_body;
+  ep1 = extrainfo_parse_entry_from_string((const char*)cp,NULL,1,NULL,NULL);
+  tt_assert(ep1);
+  tt_str_op(ep1->nickname, OP_EQ, r1->nickname);
+  /* In future tests, we could check the actual extrainfo statistics. */
+
+  extrainfo_free(ep1);
 
   strlcpy(buf2,
           "router Fred 10.3.2.1 9005 0 0\n"
@@ -503,20 +614,23 @@ test_dir_formats(void *arg)
   dirserv_free_fingerprint_list();
 
  done:
-  if (r1)
-    routerinfo_free(r1);
-  if (r2)
-    routerinfo_free(r2);
-  if (rp2)
-    routerinfo_free(rp2);
+  routerinfo_free(r1);
+  routerinfo_free(r2);
+  routerinfo_free(r2_out);
+  routerinfo_free(rp1);
+  routerinfo_free(rp2);
+
+  extrainfo_free(e1);
+  extrainfo_free(e2);
+  extrainfo_free(ep1);
+  extrainfo_free(ep2);
 
   tor_free(rsa_cc);
   tor_free(buf);
   tor_free(pk1_str);
   tor_free(pk2_str);
-  if (pk1) crypto_pk_free(pk1);
-  if (pk2) crypto_pk_free(pk2);
-  if (rp1) routerinfo_free(rp1);
+  crypto_pk_free(pk1);
+  crypto_pk_free(pk2);
   tor_free(dir1); /* XXXX And more !*/
   tor_free(dir2); /* And more !*/
 }





More information about the tor-commits mailing list