mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-28 14:23:30 +01:00
Fix an assert in directory.c. Check received network-status objects against the list we expected to get. Do not let anyone else update our network-status object.
svn:r4945
This commit is contained in:
parent
059148f588
commit
18e4d78354
@ -401,6 +401,7 @@ directory_send_command(connection_t *conn, const char *platform,
|
|||||||
tor_assert(conn->type == CONN_TYPE_DIR);
|
tor_assert(conn->type == CONN_TYPE_DIR);
|
||||||
|
|
||||||
tor_free(conn->requested_resource);
|
tor_free(conn->requested_resource);
|
||||||
|
if (resource)
|
||||||
conn->requested_resource = tor_strdup(resource);
|
conn->requested_resource = tor_strdup(resource);
|
||||||
|
|
||||||
/* come up with a string for which Host: we want */
|
/* come up with a string for which Host: we want */
|
||||||
@ -450,13 +451,13 @@ directory_send_command(connection_t *conn, const char *platform,
|
|||||||
url = tor_strdup("/tor/running-routers");
|
url = tor_strdup("/tor/running-routers");
|
||||||
break;
|
break;
|
||||||
case DIR_PURPOSE_FETCH_NETWORKSTATUS:
|
case DIR_PURPOSE_FETCH_NETWORKSTATUS:
|
||||||
httpcommand = "GET";//XXXX
|
httpcommand = "GET";
|
||||||
len = strlen(resource)+32;
|
len = strlen(resource)+32;
|
||||||
url = tor_malloc(len);
|
url = tor_malloc(len);
|
||||||
tor_snprintf(url, len, "/tor/status/%s", resource);
|
tor_snprintf(url, len, "/tor/status/%s", resource);
|
||||||
break;
|
break;
|
||||||
case DIR_PURPOSE_FETCH_SERVERDESC:
|
case DIR_PURPOSE_FETCH_SERVERDESC:
|
||||||
httpcommand = "GET";//XXXX
|
httpcommand = "GET";
|
||||||
len = strlen(resource)+32;
|
len = strlen(resource)+32;
|
||||||
url = tor_malloc(len);
|
url = tor_malloc(len);
|
||||||
tor_snprintf(url, len, "/tor/server/%s", resource);
|
tor_snprintf(url, len, "/tor/server/%s", resource);
|
||||||
@ -887,9 +888,7 @@ connection_dir_client_reached_eof(connection_t *conn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (conn->purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
|
if (conn->purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
|
||||||
/* XXXX NM We *must* make certain we get the one(s) we asked for or we
|
smartlist_t *which = NULL;
|
||||||
* could be partitioned. Also, never ask someone else for a status we
|
|
||||||
* generated! */
|
|
||||||
log_fn(LOG_INFO,"Received networkstatus objects (size %d) from server '%s:%d'",(int) body_len, conn->address, conn->port);
|
log_fn(LOG_INFO,"Received networkstatus objects (size %d) from server '%s:%d'",(int) body_len, conn->address, conn->port);
|
||||||
if (status_code != 200) {
|
if (status_code != 200) {
|
||||||
log_fn(LOG_WARN,"Received http status code %d (\"%s\") from server '%s:%d'. Failing.",
|
log_fn(LOG_WARN,"Received http status code %d (\"%s\") from server '%s:%d'. Failing.",
|
||||||
@ -897,17 +896,26 @@ connection_dir_client_reached_eof(connection_t *conn)
|
|||||||
tor_free(body); tor_free(headers); tor_free(reason);
|
tor_free(body); tor_free(headers); tor_free(reason);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (conn->requested_resource &&
|
||||||
|
!strcmpstart(conn->requested_resource,"fp/")) {
|
||||||
|
which = smartlist_create();
|
||||||
|
smartlist_split_string(which, conn->requested_resource+3, "+", 0, -1);
|
||||||
|
}
|
||||||
while (*body) {
|
while (*body) {
|
||||||
char *next = strstr(body, "\nnetwork-status-version");
|
char *next = strstr(body, "\nnetwork-status-version");
|
||||||
if (next)
|
if (next)
|
||||||
*next = '\0';
|
*next = '\0';
|
||||||
if (router_set_networkstatus(body, time(NULL), 0)<0)
|
if (router_set_networkstatus(body, time(NULL), NS_FROM_DIR, which)<0)
|
||||||
break;
|
break;
|
||||||
if (next)
|
if (next)
|
||||||
body = next+1;
|
body = next+1;
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (which) {
|
||||||
|
SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
|
||||||
|
smartlist_free(which);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC) {
|
if (conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC) {
|
||||||
|
@ -1134,7 +1134,8 @@ generate_v2_networkstatus(void)
|
|||||||
set_cached_dir(&the_v2_networkstatus, status, time(NULL));
|
set_cached_dir(&the_v2_networkstatus, status, time(NULL));
|
||||||
status = NULL; /* So it doesn't get double-freed. */
|
status = NULL; /* So it doesn't get double-freed. */
|
||||||
the_v2_networkstatus_is_dirty = 0;
|
the_v2_networkstatus_is_dirty = 0;
|
||||||
router_set_networkstatus(the_v2_networkstatus.dir, time(NULL), 0);
|
router_set_networkstatus(the_v2_networkstatus.dir, time(NULL), NS_GENERATED,
|
||||||
|
NULL);
|
||||||
|
|
||||||
r = 0;
|
r = 0;
|
||||||
done:
|
done:
|
||||||
|
@ -2072,7 +2072,10 @@ 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_single_router(const char *s, const char **msg);
|
||||||
int router_load_routerlist_from_directory(const char *s,crypto_pk_env_t *pkey,
|
int router_load_routerlist_from_directory(const char *s,crypto_pk_env_t *pkey,
|
||||||
int dir_is_recent, int dir_is_cached);
|
int dir_is_recent, int dir_is_cached);
|
||||||
int router_set_networkstatus(const char *s, time_t arrived_at, int is_cached);
|
typedef enum { NS_FROM_CACHE, NS_FROM_DIR, NS_GENERATED} networkstatus_source_t;
|
||||||
|
int router_set_networkstatus(const char *s, time_t arrived_at,
|
||||||
|
networkstatus_source_t source,
|
||||||
|
smartlist_t *requested_fingerprints);
|
||||||
addr_policy_result_t router_compare_addr_to_addr_policy(uint32_t addr,
|
addr_policy_result_t router_compare_addr_to_addr_policy(uint32_t addr,
|
||||||
uint16_t port, addr_policy_t *policy);
|
uint16_t port, addr_policy_t *policy);
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ router_reload_networkstatus(void)
|
|||||||
s = read_file_to_str(filename, 0);
|
s = read_file_to_str(filename, 0);
|
||||||
if (s) {
|
if (s) {
|
||||||
stat(filename, &st);
|
stat(filename, &st);
|
||||||
if (router_set_networkstatus(s, st.st_mtime, 1)<0) {
|
if (router_set_networkstatus(s, st.st_mtime, NS_FROM_CACHE, NULL)<0) {
|
||||||
log_fn(LOG_WARN, "Couldn't load networkstatus from \"%s\"",filename);
|
log_fn(LOG_WARN, "Couldn't load networkstatus from \"%s\"",filename);
|
||||||
}
|
}
|
||||||
tor_free(s);
|
tor_free(s);
|
||||||
@ -1199,9 +1199,11 @@ router_load_routerlist_from_directory(const char *s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** DOCDOC returns 0 on no problems, -1 on problems.
|
/** DOCDOC returns 0 on no problems, -1 on problems.
|
||||||
|
* requested fingerprints must be upcased.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
router_set_networkstatus(const char *s, time_t arrived_at, int is_cached)
|
router_set_networkstatus(const char *s, time_t arrived_at,
|
||||||
|
networkstatus_source_t source, smartlist_t *requested_fingerprints)
|
||||||
{
|
{
|
||||||
networkstatus_t *ns;
|
networkstatus_t *ns;
|
||||||
int i, found;
|
int i, found;
|
||||||
@ -1215,6 +1217,7 @@ router_set_networkstatus(const char *s, time_t arrived_at, int is_cached)
|
|||||||
}
|
}
|
||||||
if (!router_digest_is_trusted_dir(ns->identity_digest)) {
|
if (!router_digest_is_trusted_dir(ns->identity_digest)) {
|
||||||
log_fn(LOG_INFO, "Network status was signed, but not by an authoritative directory we recognize.");
|
log_fn(LOG_INFO, "Network status was signed, but not by an authoritative directory we recognize.");
|
||||||
|
networkstatus_free(ns);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
now = time(NULL);
|
now = time(NULL);
|
||||||
@ -1228,6 +1231,20 @@ router_set_networkstatus(const char *s, time_t arrived_at, int is_cached)
|
|||||||
if (!networkstatus_list)
|
if (!networkstatus_list)
|
||||||
networkstatus_list = smartlist_create();
|
networkstatus_list = smartlist_create();
|
||||||
|
|
||||||
|
if (source == NS_FROM_DIR && router_digest_is_me(ns->identity_digest)) {
|
||||||
|
/* Drop our own networkstatus when we get it from somebody else. */
|
||||||
|
networkstatus_free(ns);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
base16_encode(fp, HEX_DIGEST_LEN+1, ns->identity_digest, DIGEST_LEN);
|
||||||
|
|
||||||
|
if (requested_fingerprints &&
|
||||||
|
!smartlist_string_isin(requested_fingerprints, fp)) {
|
||||||
|
log_fn(LOG_WARN, "We received a network status with a fingerprint (%s) that we never requested. Dropping.", fp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
found = 0;
|
found = 0;
|
||||||
for (i=0; i < smartlist_len(networkstatus_list); ++i) {
|
for (i=0; i < smartlist_len(networkstatus_list); ++i) {
|
||||||
networkstatus_t *old_ns = smartlist_get(networkstatus_list, i);
|
networkstatus_t *old_ns = smartlist_get(networkstatus_list, i);
|
||||||
@ -1256,9 +1273,7 @@ router_set_networkstatus(const char *s, time_t arrived_at, int is_cached)
|
|||||||
if (!found)
|
if (!found)
|
||||||
smartlist_add(networkstatus_list, ns);
|
smartlist_add(networkstatus_list, ns);
|
||||||
|
|
||||||
base16_encode(fp, HEX_DIGEST_LEN+1, ns->identity_digest, DIGEST_LEN);
|
if (source != NS_FROM_CACHE) {
|
||||||
|
|
||||||
if (!is_cached) {
|
|
||||||
const char *datadir = get_options()->DataDirectory;
|
const char *datadir = get_options()->DataDirectory;
|
||||||
size_t len = strlen(datadir)+64;
|
size_t len = strlen(datadir)+64;
|
||||||
char *fn = tor_malloc(len+1);
|
char *fn = tor_malloc(len+1);
|
||||||
|
Loading…
Reference in New Issue
Block a user