mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-24 20:33:31 +01:00
Remove descriptor_list and use routerlist instead. Make directories manage routerlist a little better.
svn:r4854
This commit is contained in:
parent
a47765a16d
commit
0e649ac60a
276
src/or/dirserv.c
276
src/or/dirserv.c
@ -235,22 +235,14 @@ dirserv_free_fingerprint_list()
|
||||
* Descriptor list
|
||||
*/
|
||||
|
||||
/** List of routerinfo_t for all server descriptors that this dirserv
|
||||
* is holding.
|
||||
* XXXX This should eventually get coalesced into routerlist.c
|
||||
*/
|
||||
static smartlist_t *descriptor_list = NULL;
|
||||
|
||||
/** Release all storage that the dirserv is holding for server
|
||||
* descriptors. */
|
||||
void
|
||||
dirserv_free_descriptors()
|
||||
static smartlist_t *
|
||||
get_descriptor_list(void)
|
||||
{
|
||||
if (!descriptor_list)
|
||||
return;
|
||||
SMARTLIST_FOREACH(descriptor_list, routerinfo_t *, ri,
|
||||
routerinfo_free(ri));
|
||||
smartlist_clear(descriptor_list);
|
||||
routerlist_t *routerlist;
|
||||
router_get_routerlist(&routerlist);
|
||||
if (!routerlist)
|
||||
return NULL;
|
||||
return routerlist->routers;
|
||||
}
|
||||
|
||||
/** Return -1 if <b>ri</b> has a private or otherwise bad address,
|
||||
@ -274,6 +266,64 @@ dirserv_router_has_valid_address(routerinfo_t *ri)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dirserv_wants_to_reject_router(routerinfo_t *ri, int *verified,
|
||||
const char **msg)
|
||||
{
|
||||
/* Okay. Now check whether the fingerprint is recognized. */
|
||||
int r = dirserv_router_fingerprint_is_known(ri);
|
||||
time_t now;
|
||||
if (r==-1) {
|
||||
log_fn(LOG_WARN, "Known nickname '%s', wrong fingerprint. Not adding (ContactInfo '%s', platform '%s').",
|
||||
ri->nickname, ri->contact_info ? ri->contact_info : "",
|
||||
ri->platform ? ri->platform : "");
|
||||
*msg = "Rejected: There is already a verified server with this nickname and a different fingerprint.";
|
||||
return -1;
|
||||
} else if (r==0) {
|
||||
char fp[FINGERPRINT_LEN+1];
|
||||
log_fn(LOG_INFO, "Unknown nickname '%s' (%s:%d). Will try to add.",
|
||||
ri->nickname, ri->address, ri->or_port);
|
||||
if (crypto_pk_get_fingerprint(ri->identity_pkey, fp, 1) < 0) {
|
||||
log_fn(LOG_WARN, "Error computing fingerprint for '%s'", ri->nickname);
|
||||
} else {
|
||||
log_fn(LOG_INFO, "Fingerprint line: %s %s", ri->nickname, fp);
|
||||
}
|
||||
*verified = 0;
|
||||
} else {
|
||||
*verified = 1;
|
||||
}
|
||||
/* Is there too much clock skew? */
|
||||
now = time(NULL);
|
||||
if (ri->published_on > now+ROUTER_ALLOW_SKEW) {
|
||||
log_fn(LOG_NOTICE, "Publication time for nickname '%s' is too far (%d minutes) in the future; possible clock skew. Not adding (ContactInfo '%s', platform '%s').",
|
||||
ri->nickname, (int)((ri->published_on-now)/60),
|
||||
ri->contact_info ? ri->contact_info : "",
|
||||
ri->platform ? ri->platform : "");
|
||||
*msg = "Rejected: Your clock is set too far in the future, or your timezone is not correct.";
|
||||
return -1;
|
||||
}
|
||||
if (ri->published_on < now-ROUTER_MAX_AGE) {
|
||||
log_fn(LOG_NOTICE, "Publication time for router with nickname '%s' is too far (%d minutes) in the past. Not adding (ContactInfo '%s', platform '%s').",
|
||||
ri->nickname, (int)((now-ri->published_on)/60),
|
||||
ri->contact_info ? ri->contact_info : "",
|
||||
ri->platform ? ri->platform : "");
|
||||
*msg = "Rejected: Server is expired, or your clock is too far in the past, or your timezone is not correct.";
|
||||
return -1;
|
||||
}
|
||||
if (dirserv_router_has_valid_address(ri) < 0) {
|
||||
log_fn(LOG_NOTICE, "Router with nickname '%s' has invalid address '%s'. Not adding (ContactInfo '%s', platform '%s').",
|
||||
ri->nickname, ri->address,
|
||||
ri->contact_info ? ri->contact_info : "",
|
||||
ri->platform ? ri->platform : "");
|
||||
*msg = "Rejected: Address is not an IP, or IP is a private address.";
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Parse the server descriptor at *desc and maybe insert it into the
|
||||
* list of server descriptors, and (if the descriptor is well-formed)
|
||||
* advance *desc immediately past the descriptor's end. Set msg to a
|
||||
@ -288,17 +338,12 @@ dirserv_router_has_valid_address(routerinfo_t *ri)
|
||||
int
|
||||
dirserv_add_descriptor(const char **desc, const char **msg)
|
||||
{
|
||||
routerinfo_t *ri = NULL, *ri_old=NULL;
|
||||
int i, r, found=-1;
|
||||
routerinfo_t *ri = NULL;
|
||||
char *start, *end;
|
||||
char *desc_tmp = NULL;
|
||||
size_t desc_len;
|
||||
time_t now;
|
||||
int verified=1; /* whether we knew its fingerprint already */
|
||||
tor_assert(msg);
|
||||
*msg = NULL;
|
||||
if (!descriptor_list)
|
||||
descriptor_list = smartlist_create();
|
||||
|
||||
start = strstr(*desc, "router ");
|
||||
if (!start) {
|
||||
@ -323,104 +368,11 @@ dirserv_add_descriptor(const char **desc, const char **msg)
|
||||
*msg = "Rejected: Couldn't parse server descriptor.";
|
||||
return -1;
|
||||
}
|
||||
/* Okay. Now check whether the fingerprint is recognized. */
|
||||
r = dirserv_router_fingerprint_is_known(ri);
|
||||
if (r==-1) {
|
||||
log_fn(LOG_WARN, "Known nickname '%s', wrong fingerprint. Not adding (ContactInfo '%s', platform '%s').",
|
||||
ri->nickname, ri->contact_info ? ri->contact_info : "",
|
||||
ri->platform ? ri->platform : "");
|
||||
*msg = "Rejected: There is already a verified server with this nickname and a different fingerprint.";
|
||||
routerinfo_free(ri);
|
||||
*desc = end;
|
||||
if (router_add_to_routerlist(ri, msg)) {
|
||||
return -1;
|
||||
} else if (r==0) {
|
||||
char fp[FINGERPRINT_LEN+1];
|
||||
log_fn(LOG_INFO, "Unknown nickname '%s' (%s:%d). Will try to add.",
|
||||
ri->nickname, ri->address, ri->or_port);
|
||||
if (crypto_pk_get_fingerprint(ri->identity_pkey, fp, 1) < 0) {
|
||||
log_fn(LOG_WARN, "Error computing fingerprint for '%s'", ri->nickname);
|
||||
} else {
|
||||
log_fn(LOG_INFO, "Fingerprint line: %s %s", ri->nickname, fp);
|
||||
return ri->is_verified ? 1 : 0;
|
||||
}
|
||||
verified = 0;
|
||||
}
|
||||
/* Is there too much clock skew? */
|
||||
now = time(NULL);
|
||||
if (ri->published_on > now+ROUTER_ALLOW_SKEW) {
|
||||
log_fn(LOG_NOTICE, "Publication time for nickname '%s' is too far (%d minutes) in the future; possible clock skew. Not adding (ContactInfo '%s', platform '%s').",
|
||||
ri->nickname, (int)((ri->published_on-now)/60),
|
||||
ri->contact_info ? ri->contact_info : "",
|
||||
ri->platform ? ri->platform : "");
|
||||
*msg = "Rejected: Your clock is set too far in the future, or your timezone is not correct.";
|
||||
routerinfo_free(ri);
|
||||
*desc = end;
|
||||
return -1;
|
||||
}
|
||||
if (ri->published_on < now-ROUTER_MAX_AGE) {
|
||||
log_fn(LOG_NOTICE, "Publication time for router with nickname '%s' is too far (%d minutes) in the past. Not adding (ContactInfo '%s', platform '%s').",
|
||||
ri->nickname, (int)((now-ri->published_on)/60),
|
||||
ri->contact_info ? ri->contact_info : "",
|
||||
ri->platform ? ri->platform : "");
|
||||
*msg = "Rejected: Server is expired, or your clock is too far in the past, or your timezone is not correct.";
|
||||
routerinfo_free(ri);
|
||||
*desc = end;
|
||||
return -1;
|
||||
}
|
||||
if (dirserv_router_has_valid_address(ri) < 0) {
|
||||
log_fn(LOG_NOTICE, "Router with nickname '%s' has invalid address '%s'. Not adding (ContactInfo '%s', platform '%s').",
|
||||
ri->nickname, ri->address,
|
||||
ri->contact_info ? ri->contact_info : "",
|
||||
ri->platform ? ri->platform : "");
|
||||
*msg = "Rejected: Address is not an IP, or IP is a private address.";
|
||||
routerinfo_free(ri);
|
||||
*desc = end;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Do we already have an entry for this router? */
|
||||
for (i = 0; i < smartlist_len(descriptor_list); ++i) {
|
||||
ri_old = smartlist_get(descriptor_list, i);
|
||||
if (!memcmp(ri->identity_digest, ri_old->identity_digest, DIGEST_LEN)) {
|
||||
found = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found >= 0) {
|
||||
char hex_digest[HEX_DIGEST_LEN+1];
|
||||
base16_encode(hex_digest, HEX_DIGEST_LEN+1, ri->identity_digest,DIGEST_LEN);
|
||||
/* if so, decide whether to update it. */
|
||||
if (ri_old->published_on >= ri->published_on) {
|
||||
/* We already have a newer or equal-time descriptor */
|
||||
log_fn(LOG_INFO,"We already have a new enough desc for server %s (nickname '%s'). Not adding.",hex_digest,ri->nickname);
|
||||
*msg = "We already have a newer descriptor.";
|
||||
/* This isn't really an error; return success. */
|
||||
routerinfo_free(ri);
|
||||
*desc = end;
|
||||
return verified;
|
||||
}
|
||||
/* We don't already have a newer one; we'll update this one. */
|
||||
log_fn(LOG_INFO,"Dirserv updating desc for server %s (nickname '%s')",hex_digest,ri->nickname);
|
||||
if (ri->addr == ri_old->addr && ri->or_port == ri_old->or_port) {
|
||||
ri->last_reachable = ri_old->last_reachable; /* these carry over */
|
||||
ri->testing_since = ri_old->testing_since;
|
||||
}
|
||||
*msg = verified?"Verified server updated":"Unverified server updated. (Have you sent us your key fingerprint?)";
|
||||
routerinfo_free(ri_old);
|
||||
smartlist_del_keeporder(descriptor_list, found);
|
||||
} else {
|
||||
/* Add at the end. */
|
||||
log_fn(LOG_INFO,"Dirserv adding desc for nickname '%s'",ri->nickname);
|
||||
*msg = verified?"Verified server added":"Unverified server added. (Have you sent us your key fingerprint?)";
|
||||
}
|
||||
|
||||
ri->is_verified = verified ||
|
||||
tor_version_as_new_as(ri->platform,"0.1.0.2-rc");
|
||||
smartlist_add(descriptor_list, ri);
|
||||
|
||||
*desc = end;
|
||||
directory_set_dirty();
|
||||
|
||||
return verified;
|
||||
}
|
||||
|
||||
/** Remove all descriptors whose nicknames or fingerprints no longer
|
||||
@ -431,27 +383,33 @@ static void
|
||||
directory_remove_invalid(void)
|
||||
{
|
||||
int i;
|
||||
int r;
|
||||
routerinfo_t *ent;
|
||||
int changed = 0;
|
||||
smartlist_t *descriptor_list = get_descriptor_list();
|
||||
|
||||
if (!descriptor_list)
|
||||
descriptor_list = smartlist_create();
|
||||
return;
|
||||
|
||||
for (i = 0; i < smartlist_len(descriptor_list); ++i) {
|
||||
ent = smartlist_get(descriptor_list, i);
|
||||
r = dirserv_router_fingerprint_is_known(ent);
|
||||
routerinfo_t *ent = smartlist_get(descriptor_list, i);
|
||||
int r = dirserv_router_fingerprint_is_known(ent);
|
||||
if (r<0) {
|
||||
log(LOG_INFO, "Router '%s' is now verified with a key; removing old router with same name and different key.",
|
||||
ent->nickname);
|
||||
routerinfo_free(ent);
|
||||
smartlist_del(descriptor_list, i--);
|
||||
changed = 1;
|
||||
} else if (r>0 && !ent->is_verified) {
|
||||
log(LOG_INFO, "Router '%s' is now approved.", ent->nickname);
|
||||
ent->is_verified = 1;
|
||||
changed = 1;
|
||||
} else if (r==0 && ent->is_verified) {
|
||||
log(LOG_INFO, "Router '%s' is no longer approved.", ent->nickname);
|
||||
ent->is_verified = 0;
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
if (changed)
|
||||
directory_set_dirty();
|
||||
}
|
||||
|
||||
/** Write a list of unregistered descriptors into a newly allocated
|
||||
@ -467,6 +425,7 @@ dirserver_getinfo_unregistered(const char *question)
|
||||
char *answer;
|
||||
routerinfo_t *ent;
|
||||
int min_bw = atoi(question);
|
||||
smartlist_t *descriptor_list = get_descriptor_list();
|
||||
|
||||
if (!descriptor_list)
|
||||
return tor_strdup("");
|
||||
@ -608,7 +567,11 @@ list_server_status(smartlist_t *routers, char **router_status_out)
|
||||
* been found unreachable for the past several testing periods.
|
||||
*/
|
||||
void
|
||||
dirserv_log_unreachable_servers(time_t now) {
|
||||
dirserv_log_unreachable_servers(time_t now)
|
||||
{
|
||||
smartlist_t *descriptor_list = get_descriptor_list();
|
||||
if (!descriptor_list)
|
||||
return;
|
||||
|
||||
SMARTLIST_FOREACH(descriptor_list, routerinfo_t *, ri,
|
||||
{
|
||||
@ -631,7 +594,9 @@ dirserv_log_unreachable_servers(time_t now) {
|
||||
* (This function can go away when we merge descriptor-list and router-list.)
|
||||
*/
|
||||
void
|
||||
dirserv_router_has_begun_reachability_testing(char *digest, time_t now) {
|
||||
dirserv_router_has_begun_reachability_testing(char *digest, time_t now)
|
||||
{
|
||||
smartlist_t *descriptor_list = get_descriptor_list();
|
||||
if (!descriptor_list)
|
||||
return;
|
||||
SMARTLIST_FOREACH(descriptor_list, routerinfo_t *, ri,
|
||||
@ -642,30 +607,6 @@ dirserv_router_has_begun_reachability_testing(char *digest, time_t now) {
|
||||
});
|
||||
}
|
||||
|
||||
/** Remove any descriptors from the directory that are more than <b>age</b>
|
||||
* seconds old.
|
||||
*/
|
||||
void
|
||||
dirserv_remove_old_servers(int age)
|
||||
{
|
||||
int i;
|
||||
time_t cutoff;
|
||||
routerinfo_t *ent;
|
||||
if (!descriptor_list)
|
||||
descriptor_list = smartlist_create();
|
||||
|
||||
cutoff = time(NULL) - age;
|
||||
for (i = 0; i < smartlist_len(descriptor_list); ++i) {
|
||||
ent = smartlist_get(descriptor_list, i);
|
||||
if (ent->published_on <= cutoff) {
|
||||
/* descriptor_list[i] is too old. Remove it. */
|
||||
routerinfo_free(ent);
|
||||
smartlist_del(descriptor_list, i--);
|
||||
directory_set_dirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Given a (possibly empty) list of config_line_t, each line of which contains
|
||||
* a list of comma-separated version numbers surrounded by optional space,
|
||||
* allocate and return a new string containing the version numbers, in order,
|
||||
@ -704,12 +645,13 @@ dirserv_dump_directory_to_string(char **dir_out,
|
||||
char *buf = NULL;
|
||||
size_t buf_len;
|
||||
size_t identity_pkey_len;
|
||||
smartlist_t *descriptor_list = get_descriptor_list();
|
||||
|
||||
tor_assert(dir_out);
|
||||
*dir_out = NULL;
|
||||
|
||||
if (!descriptor_list)
|
||||
descriptor_list = smartlist_create();
|
||||
return -1;
|
||||
|
||||
if (list_server_status(descriptor_list, &router_status))
|
||||
return -1;
|
||||
@ -722,14 +664,13 @@ dirserv_dump_directory_to_string(char **dir_out,
|
||||
|
||||
recommended_versions = format_versions_list(get_options()->RecommendedVersions);
|
||||
|
||||
dirserv_remove_old_servers(ROUTER_MAX_AGE);
|
||||
published_on = time(NULL);
|
||||
format_iso_time(published, published_on);
|
||||
|
||||
buf_len = 2048+strlen(recommended_versions)+
|
||||
strlen(router_status);
|
||||
SMARTLIST_FOREACH(descriptor_list, routerinfo_t *, ri,
|
||||
buf_len += strlen(ri->signed_descriptor));
|
||||
buf_len += ri->signed_descriptor_len);
|
||||
buf = tor_malloc(buf_len);
|
||||
/* We'll be comparing against buf_len throughout the rest of the
|
||||
function, though strictly speaking we shouldn't be able to exceed
|
||||
@ -997,9 +938,7 @@ generate_runningrouters(void)
|
||||
crypto_pk_env_t *private_key = get_identity_key();
|
||||
char *identity_pkey; /* Identity key, DER64-encoded. */
|
||||
size_t identity_pkey_len;
|
||||
|
||||
if (!descriptor_list)
|
||||
descriptor_list = smartlist_create();
|
||||
smartlist_t *descriptor_list = get_descriptor_list();
|
||||
|
||||
if (list_server_status(descriptor_list, &router_status)) {
|
||||
goto err;
|
||||
@ -1113,6 +1052,12 @@ generate_v2_networkstatus(void)
|
||||
struct in_addr in;
|
||||
uint32_t addr;
|
||||
crypto_pk_env_t *private_key = get_identity_key();
|
||||
smartlist_t *descriptor_list = get_descriptor_list();
|
||||
|
||||
if (!descriptor_list) {
|
||||
log_fn(LOG_WARN, "Couldn't get router list.");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (resolve_my_address(options, &addr, &hostname)<0) {
|
||||
log_fn(LOG_WARN, "Couldn't resolve my hostname");
|
||||
@ -1285,22 +1230,12 @@ dirserv_get_networkstatus_v2(const char **directory, const char *key,
|
||||
void
|
||||
dirserv_get_routerdescs(smartlist_t *descs_out, const char *key)
|
||||
{
|
||||
smartlist_t *complete_list;
|
||||
|
||||
/* This is annoying. Can we unify these? */
|
||||
if (descriptor_list)
|
||||
complete_list = descriptor_list;
|
||||
else {
|
||||
routerlist_t *rlst;
|
||||
router_get_routerlist(&rlst);
|
||||
complete_list = rlst->routers;
|
||||
}
|
||||
|
||||
smartlist_t *complete_list = get_descriptor_list();
|
||||
if (!complete_list)
|
||||
return;
|
||||
|
||||
if (!strcmp(key, "/tor/server/all")) {
|
||||
smartlist_add_all(descs_out, descriptor_list);
|
||||
smartlist_add_all(descs_out, complete_list);
|
||||
} else if (!strcmp(key, "/tor/server/authority")) {
|
||||
routerinfo_t *ri = router_get_my_routerinfo();
|
||||
if (ri)
|
||||
@ -1323,7 +1258,7 @@ dirserv_get_routerdescs(smartlist_t *descs_out, const char *key)
|
||||
smartlist_free(hexdigests);
|
||||
/* XXXX should always return own descriptor. or special-case it. or
|
||||
* something. */
|
||||
SMARTLIST_FOREACH(descriptor_list, routerinfo_t *, ri,
|
||||
SMARTLIST_FOREACH(complete_list, routerinfo_t *, ri,
|
||||
SMARTLIST_FOREACH(digests, const char *, d,
|
||||
if (!memcmp(d,ri->identity_digest,DIGEST_LEN)) {
|
||||
smartlist_add(descs_out,ri);
|
||||
@ -1352,6 +1287,7 @@ dirserv_orconn_tls_done(const char *address,
|
||||
int as_advertised)
|
||||
{
|
||||
int i;
|
||||
smartlist_t *descriptor_list = get_descriptor_list();
|
||||
tor_assert(address);
|
||||
tor_assert(digest_rcvd);
|
||||
tor_assert(nickname_rcvd);
|
||||
@ -1359,6 +1295,8 @@ dirserv_orconn_tls_done(const char *address,
|
||||
if (!descriptor_list)
|
||||
return;
|
||||
|
||||
// XXXXNM We should really have a better solution here than dropping
|
||||
// XXXXNM whole routers; otherwise, they come back way too easily.
|
||||
for (i = 0; i < smartlist_len(descriptor_list); ++i) {
|
||||
routerinfo_t *ri = smartlist_get(descriptor_list, i);
|
||||
int drop = 0;
|
||||
@ -1399,12 +1337,6 @@ dirserv_free_all(void)
|
||||
smartlist_free(fingerprint_list);
|
||||
fingerprint_list = NULL;
|
||||
}
|
||||
if (descriptor_list) {
|
||||
SMARTLIST_FOREACH(descriptor_list, routerinfo_t *, ri,
|
||||
routerinfo_free(ri));
|
||||
smartlist_free(descriptor_list);
|
||||
descriptor_list = NULL;
|
||||
}
|
||||
clear_cached_dir(&the_directory);
|
||||
clear_cached_dir(&the_runningrouters);
|
||||
clear_cached_dir(&cached_directory);
|
||||
|
@ -692,8 +692,6 @@ run_scheduled_events(time_t now)
|
||||
routerlist_remove_old_routers(ROUTER_MAX_AGE);
|
||||
|
||||
if (authdir_mode(options)) {
|
||||
/* Dump any old descriptors. */
|
||||
dirserv_remove_old_servers(ROUTER_MAX_AGE);
|
||||
dirserv_log_unreachable_servers(now);
|
||||
if (!we_are_hibernating()) { /* try to determine reachability */
|
||||
router_retry_connections(1);
|
||||
|
17
src/or/or.h
17
src/or/or.h
@ -736,15 +736,16 @@ typedef struct {
|
||||
addr_policy_t *exit_policy; /**< What streams will this OR permit
|
||||
* to exit? */
|
||||
long uptime; /**< How many seconds the router claims to have been up */
|
||||
smartlist_t *declared_family; /**< Nicknames of router which this router
|
||||
* claims are its family. */
|
||||
char *contact_info; /**< Declared contact info for this router. */
|
||||
|
||||
/* local info */
|
||||
int is_running; /**< As far as we know, is this OR currently running? */
|
||||
time_t status_set_at; /**< When did we last update is_running? */
|
||||
int is_verified; /**< Has a trusted dirserver validated this OR? */
|
||||
|
||||
smartlist_t *declared_family; /**< Nicknames of router which this router
|
||||
* claims are its family. */
|
||||
|
||||
char *contact_info; /**< Declared contact info for this router. */
|
||||
int is_verified; /**< Has a trusted dirserver validated this OR?
|
||||
* (For Authdir: Have we validated this OR?)
|
||||
*/
|
||||
|
||||
/* The below items are used only by authdirservers right now for
|
||||
* reachability testing. */
|
||||
@ -1636,7 +1637,6 @@ void dirserv_free_descriptors(void);
|
||||
int list_server_status(smartlist_t *routers, char **router_status_out);
|
||||
void dirserv_log_unreachable_servers(time_t now);
|
||||
void dirserv_router_has_begun_reachability_testing(char *digest, time_t now);
|
||||
void dirserv_remove_old_servers(int age);
|
||||
int dirserv_dump_directory_to_string(char **dir_out,
|
||||
crypto_pk_env_t *private_key);
|
||||
void directory_set_dirty(void);
|
||||
@ -1654,6 +1654,8 @@ void dirserv_orconn_tls_done(const char *address,
|
||||
const char *digest_rcvd,
|
||||
const char *nickname,
|
||||
int as_advertised);
|
||||
int dirserv_wants_to_reject_router(routerinfo_t *ri, int *verified,
|
||||
const char **msg);
|
||||
void dirserv_free_all(void);
|
||||
|
||||
/********************************* dns.c ***************************/
|
||||
@ -1991,6 +1993,7 @@ void free_trusted_dir_servers(void);
|
||||
routerinfo_t *routerinfo_copy(const routerinfo_t *router);
|
||||
void router_mark_as_down(const char *digest);
|
||||
void routerlist_remove_old_routers(int age);
|
||||
int router_add_to_routerlist(routerinfo_t *router, const char **msg);
|
||||
int router_load_single_router(const char *s, const char **msg);
|
||||
int router_load_routerlist_from_directory(const char *s,crypto_pk_env_t *pkey,
|
||||
int dir_is_recent, int dir_is_cached);
|
||||
|
@ -861,40 +861,59 @@ router_mark_as_down(const char *digest)
|
||||
* *<b>msg</b> a static string describing the reason for refusing the
|
||||
* routerinfo.
|
||||
*/
|
||||
static int
|
||||
int
|
||||
router_add_to_routerlist(routerinfo_t *router, const char **msg)
|
||||
{
|
||||
int i;
|
||||
routerinfo_t *r;
|
||||
char id_digest[DIGEST_LEN];
|
||||
int authdir = get_options()->AuthoritativeDir;
|
||||
int authdir_verified = 0;
|
||||
|
||||
tor_assert(routerlist);
|
||||
crypto_pk_get_digest(router->identity_pkey, id_digest);
|
||||
|
||||
if (authdir) {
|
||||
if (dirserv_wants_to_reject_router(router, &authdir_verified, msg))
|
||||
return -1;
|
||||
router->is_verified = authdir_verified;
|
||||
if (tor_version_as_new_as(router->platform,"0.1.0.2-rc"))
|
||||
router->is_verified = 1;
|
||||
}
|
||||
|
||||
/* If we have a router with this name, and the identity key is the same,
|
||||
* choose the newer one. If the identity key has changed, drop the router.
|
||||
*/
|
||||
for (i = 0; i < smartlist_len(routerlist->routers); ++i) {
|
||||
r = smartlist_get(routerlist->routers, i);
|
||||
|
||||
if (!crypto_pk_cmp_keys(router->identity_pkey, r->identity_pkey)) {
|
||||
if (router->published_on > r->published_on) {
|
||||
log_fn(LOG_DEBUG, "Replacing entry for router '%s/%s' [%s]",
|
||||
router->nickname, r->nickname, hex_str(id_digest,DIGEST_LEN));
|
||||
//XXXRD /* Remember whether we trust this router as a dirserver. */
|
||||
routerinfo_free(r);
|
||||
smartlist_set(routerlist->routers, i, router);
|
||||
return 0;
|
||||
} else {
|
||||
routerinfo_t *old_router = smartlist_get(routerlist->routers, i);
|
||||
if (!crypto_pk_cmp_keys(router->identity_pkey,old_router->identity_pkey)) {
|
||||
if (router->published_on <= old_router->published_on) {
|
||||
log_fn(LOG_DEBUG, "Skipping not-new descriptor for router '%s'",
|
||||
router->nickname);
|
||||
if (!authdir)
|
||||
/* Update the is_running status to whatever we were told. */
|
||||
r->is_running = router->is_running;
|
||||
old_router->is_running = router->is_running;
|
||||
routerinfo_free(router);
|
||||
if (msg) *msg = "Router descriptor was not new.";
|
||||
return -1;
|
||||
} else {
|
||||
log_fn(LOG_DEBUG, "Replacing entry for router '%s/%s' [%s]",
|
||||
router->nickname, old_router->nickname,
|
||||
hex_str(id_digest,DIGEST_LEN));
|
||||
if (router->addr == old_router->addr &&
|
||||
router->or_port == old_router->or_port) {
|
||||
/* these carry over when the address and orport are unchanged.*/
|
||||
router->last_reachable = old_router->last_reachable;
|
||||
router->testing_since = old_router->testing_since;
|
||||
}
|
||||
} else if (!strcasecmp(router->nickname, r->nickname)) {
|
||||
if (msg)
|
||||
*msg = authdir_verified ? "Verified server updated":
|
||||
"Unverified server updated. (Have you sent us your key finerprint?)";
|
||||
routerinfo_free(old_router);
|
||||
smartlist_set(routerlist->routers, i, router);
|
||||
directory_set_dirty();
|
||||
return 0;
|
||||
}
|
||||
} else if (!strcasecmp(router->nickname, old_router->nickname)) {
|
||||
/* nicknames match, keys don't. */
|
||||
if (router->is_verified) {
|
||||
/* The new verified router replaces the old one; remove the
|
||||
@ -905,14 +924,15 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg)
|
||||
* make new ones with the new key.
|
||||
*/
|
||||
connection_t *conn;
|
||||
while ((conn = connection_get_by_identity_digest(r->identity_digest,
|
||||
CONN_TYPE_OR))) {
|
||||
log_fn(LOG_INFO,"Closing conn to obsolete router '%s'", r->nickname);
|
||||
while ((conn = connection_get_by_identity_digest(
|
||||
old_router->identity_digest, CONN_TYPE_OR))) {
|
||||
log_fn(LOG_INFO,"Closing conn to obsolete router '%s'",
|
||||
old_router->nickname);
|
||||
connection_mark_for_close(conn);
|
||||
}
|
||||
routerinfo_free(r);
|
||||
routerinfo_free(old_router);
|
||||
smartlist_del_keeporder(routerlist->routers, i--);
|
||||
} else if (r->is_verified) {
|
||||
} else if (old_router->is_verified) {
|
||||
/* Can't replace a verified router with an unverified one. */
|
||||
log_fn(LOG_DEBUG, "Skipping unverified entry for verified router '%s'",
|
||||
router->nickname);
|
||||
@ -925,16 +945,13 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg)
|
||||
/* We haven't seen a router with this name before. Add it to the end of
|
||||
* the list. */
|
||||
smartlist_add(routerlist->routers, router);
|
||||
directory_set_dirty();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Remove any routers from the routerlist that are more than <b>age</b>
|
||||
* seconds old.
|
||||
*
|
||||
* (This function is just like dirserv_remove_old_servers. One day we should
|
||||
* merge them.)
|
||||
*/
|
||||
//XXXRD
|
||||
void
|
||||
routerlist_remove_old_routers(int age)
|
||||
{
|
||||
@ -956,7 +973,7 @@ routerlist_remove_old_routers(int age)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Code to parse a single router descriptor and insert it into the
|
||||
* routerlist. Return -1 if the descriptor was ill-formed; 0 if the
|
||||
* descriptor was well-formed but could not be added; and 1 if the
|
||||
@ -965,6 +982,8 @@ routerlist_remove_old_routers(int age)
|
||||
* If we don't add it and <b>msg</b> is not NULL, then assign to
|
||||
* *<b>msg</b> a static string describing the reason for refusing the
|
||||
* descriptor.
|
||||
*
|
||||
* This is used only by the controller.
|
||||
*/
|
||||
int
|
||||
router_load_single_router(const char *s, const char **msg)
|
||||
@ -1350,6 +1369,7 @@ routers_update_status_from_entry(smartlist_t *routers,
|
||||
time_t list_time,
|
||||
const char *s)
|
||||
{
|
||||
int authdir = get_options()->AuthoritativeDir;
|
||||
int is_running = 1;
|
||||
int is_verified = 0;
|
||||
int hex_digest_set = 0;
|
||||
@ -1421,12 +1441,21 @@ routers_update_status_from_entry(smartlist_t *routers,
|
||||
{
|
||||
int nickname_matches = is_verified && !strcasecmp(r->nickname, nickname);
|
||||
int digest_matches = !memcmp(digest, r->identity_digest, DIGEST_LEN);
|
||||
if (!authdir) {
|
||||
/* If we're not an authoritative directory, update verified status.
|
||||
*/
|
||||
if (nickname_matches && digest_matches)
|
||||
r->is_verified = 1;
|
||||
else if (digest_matches)
|
||||
r->is_verified = 0;
|
||||
}
|
||||
if (digest_matches)
|
||||
if (r->status_set_at < list_time) {
|
||||
if (!authdir || is_running)
|
||||
/* If we're an authoritative directory, only believe that servers
|
||||
* are down when we hear it ourselves. Otherwise, believe
|
||||
* what we're told.
|
||||
*/
|
||||
r->is_running = is_running;
|
||||
r->status_set_at = time(NULL);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user