diff --git a/ChangeLog b/ChangeLog index 472396bbc7..bd6f760956 100644 --- a/ChangeLog +++ b/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 diff --git a/doc/TODO b/doc/TODO index 54ce19ea16..10ffdd881a 100644 --- a/doc/TODO +++ b/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: diff --git a/src/or/dirserv.c b/src/or/dirserv.c index e773714eac..00bf89ee6f 100644 --- a/src/or/dirserv.c +++ b/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));