Browse Source

r15966@catbus: nickm | 2007-10-19 13:56:28 -0400
Voting side of proposal 122


svn:r12052

Nick Mathewson 16 years ago
parent
commit
6ca4eebb57
3 changed files with 68 additions and 35 deletions
  1. 5 3
      ChangeLog
  2. 5 1
      doc/TODO
  3. 58 31
      src/or/dirserv.c

+ 5 - 3
ChangeLog

@@ -4,6 +4,11 @@ Changes in version 0.2.0.9-alpha - 2007-10-??
       of v2 networkstatus documents.  Clients and caches now their opinions
       about routers on these consensus documents.  Clients only download
       router descriptors listed in the consensus.
+    - Authorities now list servers who have the same nickname as a different
+      named server, but list them with a new flag, "Unnamed". (122)
+    - If the consensus list a router as "Unnamed", the name is assigned
+      to a different router: do not identify the router by that name.
+      (Partially implements proposal 122.)
 
   o Major bugfixes:
     - Stop publishing a new server descriptor just because we HUP or
@@ -16,9 +21,6 @@ Changes in version 0.2.0.9-alpha - 2007-10-??
       that it shouldn't be considered to exist at all anymore. Now we
       clear all the flags for routers that fall out of the networkstatus
       consensus. Fixes bug 529.
-    - If the consensus list a router as "Unnamed", the name is assigned
-      to a different router: do not identify the router by that name.
-      (Partially implements proposal 122.)
 
   o Minor features (v3 directory protocol):
     - Allow tor-gencert to generate a new certificate without replacing the

+ 5 - 1
doc/TODO

@@ -95,8 +95,12 @@ Things we'd like to do in 0.2.0.x:
       - Merge into tor-spec.txt.
     . 122: Network status entries need an Unnamed flag
       - Merge into dir-spec.txt
-      - Implement voting side
+      o Implement voting side
+        o Set Named and Unnamed sensibly
+        o Don't reject Unnamed routers.
       - Implement consensus side
+        - Generic "pick which voting method to use" code.
+        - 
       o Implement client side
 
   - Refactoring:

+ 58 - 31
src/or/dirserv.c

@@ -64,7 +64,8 @@ static int dirserv_add_extrainfo(extrainfo_t *ei, const char **msg);
 #define FP_NAMED   1  /**< Listed in fingerprint file. */
 #define FP_INVALID 2  /**< Believed invalid. */
 #define FP_REJECT  4  /**< We will not publish this router. */
-#define FP_BADEXIT 8 /**< We'll tell clients not to use this as an exit. */
+#define FP_BADEXIT 8  /**< We'll tell clients not to use this as an exit. */
+#define FP_UNNAMED 16 /**< Another router has this name in fingerprint file. */
 
 /** Encapsulate a nickname and an FP_* status; target of status_by_digest
  * map. */
@@ -309,6 +310,28 @@ dirserv_would_reject_router(routerstatus_t *rs)
   return (res & FP_REJECT) != 0;
 }
 
+/** Helper: Based only on the ID/Nickname combination,
+ * return FP_UNNAMED (unnamed), FP_NAMED (named), or 0 (neither).
+ */
+static uint32_t
+dirserv_get_name_status(const char *id_digest, const char *nickname)
+{
+  char fp[HEX_DIGEST_LEN+1];
+  char *fp_by_name;
+
+  base16_encode(fp, sizeof(fp), id_digest, DIGEST_LEN);
+
+  if ((fp_by_name =
+       strmap_get_lc(fingerprint_list->fp_by_name, nickname))) {
+    if (!strcasecmp(fp, fp_by_name)) {
+      return FP_NAMED;
+    } else {
+      return FP_UNNAMED; /* Wrong fingerprint. */
+    }
+  }
+  return 0;
+}
+
 /** Helper: As dirserv_get_router_status, but takes the router fingerprint
  * (hex, no spaces), nickname, address (used for logging only), IP address, OR
  * port, platform (logging only) and contact info (logging only) as arguments.
@@ -323,44 +346,39 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname,
                         const char *platform, const char *contact,
                         const char **msg, int should_log)
 {
-  char fp[HEX_DIGEST_LEN+1];
   int reject_unlisted = get_options()->AuthDirRejectUnlisted;
   uint32_t result = 0;
   router_status_t *status_by_digest;
-  char *fp_by_name;
+
   if (!fingerprint_list)
     fingerprint_list = authdir_config_new();
 
-  base16_encode(fp, sizeof(fp), id_digest, DIGEST_LEN);
-
   if (should_log)
     log_debug(LD_DIRSERV, "%d fingerprints, %d digests known.",
               strmap_size(fingerprint_list->fp_by_name),
               digestmap_size(fingerprint_list->status_by_digest));
 
-  if ((fp_by_name =
-       strmap_get_lc(fingerprint_list->fp_by_name, nickname))) {
-    if (!strcasecmp(fp, fp_by_name)) {
-      result |= FP_NAMED;
-      if (should_log)
-        log_debug(LD_DIRSERV,"Good fingerprint for '%s'",nickname);
-    } else {
-      if (should_log) {
-        char *esc_contact = esc_for_log(contact);
-        log_warn(LD_DIRSERV,
-                 "Mismatched fingerprint for '%s': expected '%s' got '%s'. "
-                 "ContactInfo '%s', platform '%s'.)",
-                 nickname, fp_by_name, fp,
-                 esc_contact,
-                 platform ? escaped(platform) : "");
-        tor_free(esc_contact);
-      }
-      if (msg)
-        *msg = "Rejected: There is already a named server with this nickname "
-          "and a different fingerprint.";
-      return FP_REJECT; /* Wrong fingerprint. */
+  result = dirserv_get_name_status(id_digest, nickname);
+  if (result & FP_NAMED) {
+    if (should_log)
+      log_debug(LD_DIRSERV,"Good fingerprint for '%s'",nickname);
+  }
+  if (result & FP_UNNAMED) {
+    if (should_log) {
+      char *esc_contact = esc_for_log(contact);
+      log_warn(LD_DIRSERV,
+               "Mismatched fingerprint for '%s'. "
+               "ContactInfo '%s', platform '%s'.)",
+               nickname,
+               esc_contact,
+               platform ? escaped(platform) : "");
+      tor_free(esc_contact);
     }
+    if (msg)
+      *msg = "Rejected: There is already a named server with this nickname "
+        "and a different fingerprint.";
   }
+
   status_by_digest = digestmap_get(fingerprint_list->status_by_digest,
                                    id_digest);
   if (status_by_digest)
@@ -1670,7 +1688,7 @@ routerstatus_format_entry(char *buf, size_t buf_len,
     return 0;
   cp = buf + strlen(buf);
   r = tor_snprintf(cp, buf_len - (cp-buf),
-                   "s%s%s%s%s%s%s%s%s%s%s\n",
+                   "s%s%s%s%s%s%s%s%s%s%s%s\n",
                   /* These must stay in alphabetical order. */
                    rs->is_authority?" Authority":"",
                    rs->is_bad_exit?" BadExit":"",
@@ -1678,8 +1696,9 @@ routerstatus_format_entry(char *buf, size_t buf_len,
                    rs->is_fast?" Fast":"",
                    rs->is_possible_guard?" Guard":"",
                    rs->is_named?" Named":"",
-                   rs->is_stable?" Stable":"",
                    rs->is_running?" Running":"",
+                   rs->is_stable?" Stable":"",
+                   rs->is_unnamed?" Unnamed":"",
                    rs->is_v2_dir?" V2Dir":"",
                    rs->is_valid?" Valid":"");
   if (r<0) {
@@ -1816,7 +1835,13 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs,
     router_is_active(ri, now) &&
     !dirserv_thinks_router_is_unreliable(now, ri, 0, 1);
   rs->is_running = ri->is_running; /* computed above */
-  rs->is_named = naming && ri->is_named;
+
+  if (naming) {
+    uint32_t name_status = dirserv_get_name_status(
+                         ri->cache_info.identity_digest, ri->nickname);
+    rs->is_named = (naming && (name_status & FP_NAMED)) ? 1 : 0;
+    rs->is_unnamed = (naming && (name_status & FP_UNNAMED)) ? 1 : 0;
+  }
   rs->is_valid = ri->is_valid;
   rs->is_possible_guard = rs->is_fast && rs->is_stable &&
     (!rs->is_exit || exits_can_be_guards) &&
@@ -1831,7 +1856,7 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs,
     tor_version_as_new_as(ri->platform,"0.1.1.9-alpha");
 
   if (!strcasecmp(ri->nickname, UNNAMED_ROUTER_NICKNAME))
-    rs->is_named = 0;
+    rs->is_named = rs->is_unnamed = 0;
 
   rs->published_on = ri->cache_info.published_on;
   memcpy(rs->identity_digest, ri->cache_info.identity_digest, DIGEST_LEN);
@@ -1979,8 +2004,10 @@ generate_networkstatus_vote_obj(crypto_pk_env_t *private_key,
                 0, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
   if (listbadexits)
     smartlist_add(v3_out->known_flags, tor_strdup("BadExit"));
-  if (naming)
+  if (naming) {
     smartlist_add(v3_out->known_flags, tor_strdup("Named"));
+    smartlist_add(v3_out->known_flags, tor_strdup("Unnamed"));
+  }
   smartlist_sort_strings(v3_out->known_flags);
 
   voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));