Browse Source

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


svn:r12052

Nick Mathewson 18 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
       of v2 networkstatus documents.  Clients and caches now their opinions
       about routers on these consensus documents.  Clients only download
       about routers on these consensus documents.  Clients only download
       router descriptors listed in the consensus.
       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:
   o Major bugfixes:
     - Stop publishing a new server descriptor just because we HUP or
     - 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
       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
       clear all the flags for routers that fall out of the networkstatus
       consensus. Fixes bug 529.
       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):
   o Minor features (v3 directory protocol):
     - Allow tor-gencert to generate a new certificate without replacing the
     - 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.
       - Merge into tor-spec.txt.
     . 122: Network status entries need an Unnamed flag
     . 122: Network status entries need an Unnamed flag
       - Merge into dir-spec.txt
       - 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
       - Implement consensus side
+        - Generic "pick which voting method to use" code.
+        - 
       o Implement client side
       o Implement client side
 
 
   - Refactoring:
   - 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_NAMED   1  /**< Listed in fingerprint file. */
 #define FP_INVALID 2  /**< Believed invalid. */
 #define FP_INVALID 2  /**< Believed invalid. */
 #define FP_REJECT  4  /**< We will not publish this router. */
 #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
 /** Encapsulate a nickname and an FP_* status; target of status_by_digest
  * map. */
  * map. */
@@ -309,6 +310,28 @@ dirserv_would_reject_router(routerstatus_t *rs)
   return (res & FP_REJECT) != 0;
   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
 /** Helper: As dirserv_get_router_status, but takes the router fingerprint
  * (hex, no spaces), nickname, address (used for logging only), IP address, OR
  * (hex, no spaces), nickname, address (used for logging only), IP address, OR
  * port, platform (logging only) and contact info (logging only) as arguments.
  * 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 *platform, const char *contact,
                         const char **msg, int should_log)
                         const char **msg, int should_log)
 {
 {
-  char fp[HEX_DIGEST_LEN+1];
   int reject_unlisted = get_options()->AuthDirRejectUnlisted;
   int reject_unlisted = get_options()->AuthDirRejectUnlisted;
   uint32_t result = 0;
   uint32_t result = 0;
   router_status_t *status_by_digest;
   router_status_t *status_by_digest;
-  char *fp_by_name;
+
   if (!fingerprint_list)
   if (!fingerprint_list)
     fingerprint_list = authdir_config_new();
     fingerprint_list = authdir_config_new();
 
 
-  base16_encode(fp, sizeof(fp), id_digest, DIGEST_LEN);
-
   if (should_log)
   if (should_log)
     log_debug(LD_DIRSERV, "%d fingerprints, %d digests known.",
     log_debug(LD_DIRSERV, "%d fingerprints, %d digests known.",
               strmap_size(fingerprint_list->fp_by_name),
               strmap_size(fingerprint_list->fp_by_name),
               digestmap_size(fingerprint_list->status_by_digest));
               digestmap_size(fingerprint_list->status_by_digest));
 
 
-  if ((fp_by_name =
+  result = dirserv_get_name_status(id_digest, nickname);
-       strmap_get_lc(fingerprint_list->fp_by_name, nickname))) {
+  if (result & FP_NAMED) {
-    if (!strcasecmp(fp, fp_by_name)) {
+    if (should_log)
-      result |= FP_NAMED;
+      log_debug(LD_DIRSERV,"Good fingerprint for '%s'",nickname);
-      if (should_log)
+  }
-        log_debug(LD_DIRSERV,"Good fingerprint for '%s'",nickname);
+  if (result & FP_UNNAMED) {
-    } else {
+    if (should_log) {
-      if (should_log) {
+      char *esc_contact = esc_for_log(contact);
-        char *esc_contact = esc_for_log(contact);
+      log_warn(LD_DIRSERV,
-        log_warn(LD_DIRSERV,
+               "Mismatched fingerprint for '%s'. "
-                 "Mismatched fingerprint for '%s': expected '%s' got '%s'. "
+               "ContactInfo '%s', platform '%s'.)",
-                 "ContactInfo '%s', platform '%s'.)",
+               nickname,
-                 nickname, fp_by_name, fp,
+               esc_contact,
-                 esc_contact,
+               platform ? escaped(platform) : "");
-                 platform ? escaped(platform) : "");
+      tor_free(esc_contact);
-        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. */
     }
     }
+    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,
   status_by_digest = digestmap_get(fingerprint_list->status_by_digest,
                                    id_digest);
                                    id_digest);
   if (status_by_digest)
   if (status_by_digest)
@@ -1670,7 +1688,7 @@ routerstatus_format_entry(char *buf, size_t buf_len,
     return 0;
     return 0;
   cp = buf + strlen(buf);
   cp = buf + strlen(buf);
   r = tor_snprintf(cp, buf_len - (cp-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. */
                   /* These must stay in alphabetical order. */
                    rs->is_authority?" Authority":"",
                    rs->is_authority?" Authority":"",
                    rs->is_bad_exit?" BadExit":"",
                    rs->is_bad_exit?" BadExit":"",
@@ -1678,8 +1696,9 @@ routerstatus_format_entry(char *buf, size_t buf_len,
                    rs->is_fast?" Fast":"",
                    rs->is_fast?" Fast":"",
                    rs->is_possible_guard?" Guard":"",
                    rs->is_possible_guard?" Guard":"",
                    rs->is_named?" Named":"",
                    rs->is_named?" Named":"",
-                   rs->is_stable?" Stable":"",
                    rs->is_running?" Running":"",
                    rs->is_running?" Running":"",
+                   rs->is_stable?" Stable":"",
+                   rs->is_unnamed?" Unnamed":"",
                    rs->is_v2_dir?" V2Dir":"",
                    rs->is_v2_dir?" V2Dir":"",
                    rs->is_valid?" Valid":"");
                    rs->is_valid?" Valid":"");
   if (r<0) {
   if (r<0) {
@@ -1816,7 +1835,13 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs,
     router_is_active(ri, now) &&
     router_is_active(ri, now) &&
     !dirserv_thinks_router_is_unreliable(now, ri, 0, 1);
     !dirserv_thinks_router_is_unreliable(now, ri, 0, 1);
   rs->is_running = ri->is_running; /* computed above */
   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_valid = ri->is_valid;
   rs->is_possible_guard = rs->is_fast && rs->is_stable &&
   rs->is_possible_guard = rs->is_fast && rs->is_stable &&
     (!rs->is_exit || exits_can_be_guards) &&
     (!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");
     tor_version_as_new_as(ri->platform,"0.1.1.9-alpha");
 
 
   if (!strcasecmp(ri->nickname, UNNAMED_ROUTER_NICKNAME))
   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;
   rs->published_on = ri->cache_info.published_on;
   memcpy(rs->identity_digest, ri->cache_info.identity_digest, DIGEST_LEN);
   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);
                 0, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
   if (listbadexits)
   if (listbadexits)
     smartlist_add(v3_out->known_flags, tor_strdup("BadExit"));
     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("Named"));
+    smartlist_add(v3_out->known_flags, tor_strdup("Unnamed"));
+  }
   smartlist_sort_strings(v3_out->known_flags);
   smartlist_sort_strings(v3_out->known_flags);
 
 
   voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
   voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));