[tor-commits] [tor/master] Add a function to canonicalize nodefamilies per prop298

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


commit d29e3a02d57aef402a1aaf9747ef44393b043d98
Author: Nick Mathewson <nickm at torproject.org>
Date:   Sat Nov 24 10:53:38 2018 -0500

    Add a function to canonicalize nodefamilies per prop298
    
    This is the same as the regular canonical nodefamily format, except
    that unrecognized elements are preserved.
---
 src/feature/nodelist/nodefamily.c | 45 +++++++++++++++++++++++++++++++++++++--
 src/feature/nodelist/nodefamily.h |  5 ++++-
 src/test/test_nodelist.c          | 31 +++++++++++++++++++++++++++
 3 files changed, 78 insertions(+), 3 deletions(-)

diff --git a/src/feature/nodelist/nodefamily.c b/src/feature/nodelist/nodefamily.c
index 29659ed93..944ad5475 100644
--- a/src/feature/nodelist/nodefamily.c
+++ b/src/feature/nodelist/nodefamily.c
@@ -93,13 +93,47 @@ nodefamily_parse(const char *s, const uint8_t *rsa_id_self,
 {
   smartlist_t *sl = smartlist_new();
   smartlist_split_string(sl, s, NULL, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
-  nodefamily_t *result = nodefamily_from_members(sl, rsa_id_self, flags);
+  nodefamily_t *result = nodefamily_from_members(sl, rsa_id_self, flags, NULL);
   SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
   smartlist_free(sl);
   return result;
 }
 
 /**
+ * Canonicalize the family list <b>s</b>, returning a newly allocated string.
+ *
+ * The canonicalization rules are fully specified in dir-spec.txt, but,
+ * briefly: $hexid entries are put in caps, $hexid[=~]foo entries are
+ * truncated, nicknames are put into lowercase, unrecognized entries are left
+ * alone, and everything is sorted.
+ **/
+char *
+nodefamily_canonicalize(const char *s, const uint8_t *rsa_id_self,
+                        unsigned flags)
+{
+  smartlist_t *sl = smartlist_new();
+  smartlist_t *result_members = smartlist_new();
+  smartlist_split_string(sl, s, NULL, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+  nodefamily_t *nf = nodefamily_from_members(sl, rsa_id_self, flags,
+                                             result_members);
+
+  char *formatted = nodefamily_format(nf);
+  smartlist_split_string(result_members, formatted, NULL,
+                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+  smartlist_sort_strings(result_members);
+  char *combined = smartlist_join_strings(result_members, " ", 0, NULL);
+
+  nodefamily_free(nf);
+  SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
+  smartlist_free(sl);
+  SMARTLIST_FOREACH(result_members, char *, cp, tor_free(cp));
+  smartlist_free(result_members);
+  tor_free(formatted);
+
+  return combined;
+}
+
+/**
  * qsort helper for encoded nodefamily elements.
  **/
 static int
@@ -117,11 +151,15 @@ compare_members(const void *a, const void *b)
  * family declaration if it is not there already.
  *
  * The <b>flags</b> element is interpreted as in nodefamily_parse().
+ *
+ * If <b>unrecognized</b> is provided, fill it copies of any unrecognized
+ * members.  (Note that malformed $hexids are not considered unrecognized.)
  **/
 nodefamily_t *
 nodefamily_from_members(const smartlist_t *members,
                         const uint8_t *rsa_id_self,
-                        unsigned flags)
+                        unsigned flags,
+                        smartlist_t *unrecognized_out)
 {
   const int n_self = rsa_id_self ? 1 : 0;
   int n_bad_elements = 0;
@@ -146,6 +184,9 @@ nodefamily_from_members(const smartlist_t *members,
         ptr[0] = NODEFAMILY_BY_RSA_ID;
         memcpy(ptr+1, digest_buf, DIGEST_LEN);
       }
+    } else {
+      if (unrecognized_out)
+        smartlist_add_strdup(unrecognized_out, cp);
     }
 
     if (bad_element) {
diff --git a/src/feature/nodelist/nodefamily.h b/src/feature/nodelist/nodefamily.h
index 342f161a0..ea1076876 100644
--- a/src/feature/nodelist/nodefamily.h
+++ b/src/feature/nodelist/nodefamily.h
@@ -27,7 +27,8 @@ nodefamily_t *nodefamily_parse(const char *s,
                                unsigned flags);
 nodefamily_t *nodefamily_from_members(const struct smartlist_t *members,
                                       const uint8_t *rsa_id_self,
-                                      unsigned flags);
+                                      unsigned flags,
+                                      smartlist_t *unrecognized_out);
 void nodefamily_free_(nodefamily_t *family);
 #define nodefamily_free(family) \
   FREE_AND_NULL(nodefamily_t, nodefamily_free_, (family))
@@ -41,6 +42,8 @@ bool nodefamily_contains_node(const nodefamily_t *family,
 void nodefamily_add_nodes_to_smartlist(const nodefamily_t *family,
                                        struct smartlist_t *out);
 char *nodefamily_format(const nodefamily_t *family);
+char *nodefamily_canonicalize(const char *s, const uint8_t *rsa_id_self,
+                              unsigned flags);
 
 void nodefamily_free_all(void);
 
diff --git a/src/test/test_nodelist.c b/src/test/test_nodelist.c
index afbcc60ac..ed919f4ed 100644
--- a/src/test/test_nodelist.c
+++ b/src/test/test_nodelist.c
@@ -610,6 +610,36 @@ test_nodelist_node_nodefamily(void *arg)
   smartlist_free(nodes);
 }
 
+static void
+test_nodelist_nodefamily_canonicalize(void *arg)
+{
+  (void)arg;
+  char *c = NULL;
+
+  c = nodefamily_canonicalize("", NULL, 0);
+  tt_str_op(c, OP_EQ, "");
+  tor_free(c);
+
+  uint8_t own_id[20];
+  memset(own_id, 0, sizeof(own_id));
+  c = nodefamily_canonicalize(
+           "alice BOB caroL %potrzebie !!!@#@# "
+           "$bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb=fred "
+           "ffffffffffffffffffffffffffffffffffffffff "
+           "$cccccccccccccccccccccccccccccccccccccccc ", own_id, 0);
+  tt_str_op(c, OP_EQ,
+           "!!!@#@# "
+           "$0000000000000000000000000000000000000000 "
+           "$BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB "
+           "$CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC "
+           "$FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF "
+           "%potrzebie "
+           "alice bob carol");
+
+ done:
+  tor_free(c);
+}
+
 #define NODE(name, flags) \
   { #name, test_nodelist_##name, (flags), NULL, NULL }
 
@@ -623,5 +653,6 @@ struct testcase_t nodelist_tests[] = {
   NODE(nodefamily_lookup, TT_FORK),
   NODE(nickname_matches, 0),
   NODE(node_nodefamily, TT_FORK),
+  NODE(nodefamily_canonicalize, 0),
   END_OF_TESTCASES
 };





More information about the tor-commits mailing list