summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2005-12-06 06:55:43 +0000
committerNick Mathewson <nickm@torproject.org>2005-12-06 06:55:43 +0000
commitb1d034d2abb20f218b8d4af1219f0cc0e1212fec (patch)
treed199f3b50a7bd1c4ba0fe75ffff6d05a8dcddf31
parentd2123388adc8af36a19446a8eee7ee64eeef90ec (diff)
downloadtor-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.c96
-rw-r--r--src/or/or.h1
-rw-r--r--src/or/routerlist.c12
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];