diff options
author | Nick Mathewson <nickm@torproject.org> | 2005-12-06 06:55:43 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2005-12-06 06:55:43 +0000 |
commit | b1d034d2abb20f218b8d4af1219f0cc0e1212fec (patch) | |
tree | d199f3b50a7bd1c4ba0fe75ffff6d05a8dcddf31 | |
parent | d2123388adc8af36a19446a8eee7ee64eeef90ec (diff) | |
download | tor-b1d034d2abb20f218b8d4af1219f0cc0e1212fec.tar.gz tor-b1d034d2abb20f218b8d4af1219f0cc0e1212fec.zip |
Fix bug 212: Directory authorities should not try to download server descriptors that they know they will reject.
svn:r5514
-rw-r--r-- | src/or/dirserv.c | 96 | ||||
-rw-r--r-- | src/or/or.h | 1 | ||||
-rw-r--r-- | src/or/routerlist.c | 12 |
3 files changed, 83 insertions, 26 deletions
diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 47e095af66..b2a3c3cfd0 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -39,6 +39,12 @@ int add_fingerprint_to_dir(const char *nickname, const char *fp, smartlist_t *li static int router_is_general_exit(routerinfo_t *ri); static router_status_t dirserv_router_get_status(const routerinfo_t *router, const char **msg); +static router_status_t +dirserv_get_status_impl(const char *fp, const char *nickname, + const char *address, + uint32_t addr, uint16_t or_port, + const char *platform, const char *contact, + const char **msg, int should_log); static int dirserv_thinks_router_is_reachable(routerinfo_t *router, time_t now); @@ -219,28 +225,67 @@ dirserv_parse_fingerprint_file(const char *fname) * according to our configuration. Return the appropriate router status. * * If the status is 'FP_REJECT' and <b>msg</b> is provided, set - * *<b>msg</b> to an explanation of why. - */ + * *<b>msg</b> to an explanation of why. */ static router_status_t dirserv_router_get_status(const routerinfo_t *router, const char **msg) { - fingerprint_entry_t *nn_ent = NULL, *fp_ent = NULL; - char fp[FINGERPRINT_LEN+1]; - - if (!fingerprint_list) - fingerprint_list = smartlist_create(); + char fingerprint[FINGERPRINT_LEN+1]; - if (crypto_pk_get_fingerprint(router->identity_pkey, fp, 0)) { + if (crypto_pk_get_fingerprint(router->identity_pkey, fingerprint, 0)) { warn(LD_BUG,"Error computing fingerprint"); return -1; } - debug(LD_DIRSERV, "%d fingerprints known.", smartlist_len(fingerprint_list)); + return dirserv_get_status_impl(fingerprint, router->nickname, + router->address, + router->addr, router->or_port, + router->platform, router->contact_info, + msg, 1); +} + +/** Return true if there is no point in downloading the router described by + * <b>rs</b> because this directory would reject it. */ +int +dirserv_would_reject_router(routerstatus_t *rs) +{ + char fp[FINGERPRINT_LEN+1]; + router_status_t res; + base16_encode(fp, sizeof(fp), rs->identity_digest, DIGEST_LEN); + + res = dirserv_get_status_impl(fp, rs->nickname, + "", /* address is only used in logs */ + rs->addr, rs->or_port, + NULL, NULL, + NULL, 0); + + return (res == FP_REJECT); +} + +/** 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. + * + * If should_log is false, do not log messages. (There's not much point in + * logging that we're rejecting servers we'll not download.) + */ +static router_status_t +dirserv_get_status_impl(const char *fp, const char *nickname, + const char *address, + uint32_t addr, uint16_t or_port, + const char *platform, const char *contact, + const char **msg, int should_log) +{ + fingerprint_entry_t *nn_ent = NULL, *fp_ent = NULL; + if (!fingerprint_list) + fingerprint_list = smartlist_create(); + + if (should_log) + debug(LD_DIRSERV, "%d fingerprints known.", smartlist_len(fingerprint_list)); SMARTLIST_FOREACH(fingerprint_list, fingerprint_entry_t *, ent, { if (!strcasecmp(fp,ent->fingerprint)) fp_ent = ent; - if (!strcasecmp(router->nickname,ent->nickname)) + if (!strcasecmp(nickname,ent->nickname)) nn_ent = ent; }); @@ -258,37 +303,42 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg) if (!nn_ent) { /* No such server known with that nickname */ addr_policy_result_t rej = router_compare_addr_to_addr_policy( - router->addr, router->or_port, authdir_reject_policy); + addr, or_port, authdir_reject_policy); addr_policy_result_t inv = router_compare_addr_to_addr_policy( - router->addr, router->or_port, authdir_invalid_policy); + addr, or_port, authdir_invalid_policy); if (rej == ADDR_POLICY_PROBABLY_REJECTED || rej == ADDR_POLICY_REJECTED) { - info(LD_DIRSERV, "Rejecting '%s' because of address %s", - router->nickname, router->address); + if (should_log) + info(LD_DIRSERV, "Rejecting '%s' because of address %s", + nickname, address); if (msg) *msg = "Authdir is rejecting routers in this range."; return FP_REJECT; } if (inv == ADDR_POLICY_PROBABLY_REJECTED || inv == ADDR_POLICY_REJECTED) { - info(LD_DIRSERV, "Not marking '%s' valid because of address %s", - router->nickname, router->address); + if (should_log) + info(LD_DIRSERV, "Not marking '%s' valid because of address %s", + nickname, address); return FP_INVALID; } - if (tor_version_as_new_as(router->platform,"0.1.0.2-rc")) + if (!platform || tor_version_as_new_as(platform,"0.1.0.2-rc")) return FP_VALID; else return FP_INVALID; - info(LD_DIRSERV,"No fingerprint found for '%s'",router->nickname); + if (should_log) + info(LD_DIRSERV,"No fingerprint found for '%s'",nickname); return 0; } if (0==strcasecmp(nn_ent->fingerprint, fp)) { - debug(LD_DIRSERV,"Good fingerprint for '%s'",router->nickname); + if (should_log) + debug(LD_DIRSERV,"Good fingerprint for '%s'",nickname); return FP_NAMED; /* Right fingerprint. */ } else { - warn(LD_DIRSERV,"Mismatched fingerprint for '%s': expected '%s' got '%s'. ContactInfo '%s', platform '%s'.)", - router->nickname, nn_ent->fingerprint, fp, - router->contact_info ? router->contact_info : "", - router->platform ? router->platform : ""); + if (should_log) + warn(LD_DIRSERV,"Mismatched fingerprint for '%s': expected '%s' got '%s'. ContactInfo '%s', platform '%s'.)", + nickname, nn_ent->fingerprint, fp, + contact ? contact : "", + platform ? platform : ""); if (msg) *msg = "Rejected: There is already a verified server with this nickname and a different fingerprint."; return FP_REJECT; /* Wrong fingerprint. */ diff --git a/src/or/or.h b/src/or/or.h index 61b9240017..3eb134cd79 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1820,6 +1820,7 @@ void dirserv_orconn_tls_done(const char *address, int as_advertised); int authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg); +int dirserv_would_reject_router(routerstatus_t *rs); void dirserv_free_all(void); /********************************* dns.c ***************************/ diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 913f844dce..c84dab1345 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -2953,12 +2953,13 @@ static smartlist_t * router_list_downloadable(void) { #define MAX_OLD_SERVER_DOWNLOAD_RATE 2*60*60 + or_options_t *options = get_options(); int n_conns, i, n_downloadable = 0; connection_t **carray; smartlist_t *superseded = smartlist_create(); smartlist_t *downloading; time_t now = time(NULL); - int mirror = server_mode(get_options()) && get_options()->DirPort; + int mirror = server_mode(options) && options->DirPort; /* these are just used for logging */ int n_not_ready = 0, n_in_progress = 0, n_uptodate = 0, n_skip_old = 0, n_obsolete = 0, xx_n_unrecognized = 0, xx_n_extra_new = 0, xx_n_both = 0, @@ -2977,8 +2978,13 @@ router_list_downloadable(void) rs->should_download = 0; ++n_obsolete; } if (rs->next_attempt_at < now) { - rs->should_download = 1; - ++n_downloadable; + if (options->AuthoritativeDir && + dirserv_would_reject_router(&rs->status)) { + rs->should_download = 0; + } else { + rs->should_download = 1; + ++n_downloadable; + } } else { /* char fp[HEX_DIGEST_LEN+1]; |