mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
Add an implementation of trusted_dir_server logic to switch towards simply remembering an addr/port/keyid for each trusted dir server
svn:r2443
This commit is contained in:
@@ -34,6 +34,7 @@ static int config_get_lines(FILE *f, struct config_line_t **result);
|
||||
static void config_free_lines(struct config_line_t *front);
|
||||
static int config_compare(struct config_line_t *c, const char *key, config_type_t type, void *arg);
|
||||
static int config_assign(or_options_t *options, struct config_line_t *list);
|
||||
static int parse_dir_server_line(const char *line);
|
||||
|
||||
/** Helper: Read a list of configuration options from the command line. */
|
||||
static struct config_line_t *config_get_commandlines(int argc, char **argv) {
|
||||
@@ -205,6 +206,7 @@ static int config_assign(or_options_t *options, struct config_line_t *list) {
|
||||
config_compare(list, "DirPort", CONFIG_TYPE_INT, &options->DirPort) ||
|
||||
config_compare(list, "DirBindAddress", CONFIG_TYPE_LINELIST, &options->DirBindAddress) ||
|
||||
config_compare(list, "DirFetchPostPeriod",CONFIG_TYPE_INT, &options->DirFetchPostPeriod) ||
|
||||
config_compare(list, "DirServer", CONFIG_TYPE_LINELIST, &options->DirServers) ||
|
||||
|
||||
config_compare(list, "ExitNodes", CONFIG_TYPE_STRING, &options->ExitNodes) ||
|
||||
config_compare(list, "EntryNodes", CONFIG_TYPE_STRING, &options->EntryNodes) ||
|
||||
@@ -387,6 +389,11 @@ int config_assign_default_dirservers(void) {
|
||||
log_fn(LOG_WARN,"Bug: the default dirservers internal string is corrupt.");
|
||||
return -1;
|
||||
}
|
||||
#if 0
|
||||
parse_dir_server_line("18.244.0.188:9031 XXXX");
|
||||
parse_dir_server_line("18.244.0.188:9032 XXXX");
|
||||
parse_dir_server_line("62.116.124.106:9030 XXXX");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -535,6 +542,7 @@ static void free_options(or_options_t *options) {
|
||||
config_free_lines(options->DirBindAddress);
|
||||
config_free_lines(options->ExitPolicy);
|
||||
config_free_lines(options->SocksPolicy);
|
||||
config_free_lines(options->DirServers);
|
||||
if (options->FirewallPorts) {
|
||||
SMARTLIST_FOREACH(options->FirewallPorts, char *, cp, tor_free(cp));
|
||||
smartlist_free(options->FirewallPorts);
|
||||
@@ -573,6 +581,7 @@ static void init_options(or_options_t *options) {
|
||||
options->NumCpus = 1;
|
||||
options->RendConfigLines = NULL;
|
||||
options->FirewallPorts = NULL;
|
||||
options->DirServers = NULL;
|
||||
}
|
||||
|
||||
static char *get_default_conf_file(void)
|
||||
@@ -856,6 +865,11 @@ int getconfig(int argc, char **argv, or_options_t *options) {
|
||||
result = -1;
|
||||
}
|
||||
|
||||
for (cl = options->DirServers; cl; cl = cl->next) {
|
||||
if (parse_dir_server_line(cl->value)<0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* XXX look at the various nicknamelists and make sure they're
|
||||
* valid and don't have hostnames that are too long.
|
||||
*/
|
||||
@@ -1025,6 +1039,49 @@ void exit_policy_free(struct exit_policy_t *p) {
|
||||
}
|
||||
}
|
||||
|
||||
static int parse_dir_server_line(const char *line)
|
||||
{
|
||||
smartlist_t *items = NULL;
|
||||
int r;
|
||||
char *addrport, *address=NULL;
|
||||
uint16_t port;
|
||||
char digest[DIGEST_LEN];
|
||||
items = smartlist_create();
|
||||
smartlist_split_string(items, line, " ",
|
||||
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2);
|
||||
if (smartlist_len(items) < 2) {
|
||||
log_fn(LOG_WARN, "Too few arguments to DirServer line."); goto err;
|
||||
}
|
||||
addrport = smartlist_get(items, 0);
|
||||
if (parse_addr_port(addrport, &address, NULL, &port)<0) {
|
||||
log_fn(LOG_WARN, "Error parsing DirServer address '%s'", addrport);goto err;
|
||||
}
|
||||
if (!port) {
|
||||
log_fn(LOG_WARN, "Missing port in DirServe address '%s'",addrport);goto err;
|
||||
}
|
||||
|
||||
tor_strstrip(smartlist_get(items, 1), " ");
|
||||
if (strlen(smartlist_get(items, 1)) != HEX_DIGEST_LEN) {
|
||||
log_fn(LOG_WARN, "Key digest for DirServer is wrong length."); goto err;
|
||||
}
|
||||
if (base16_decode(digest, DIGEST_LEN,
|
||||
smartlist_get(items,1), HEX_DIGEST_LEN)<0) {
|
||||
log_fn(LOG_WARN, "Unable to decode DirServer key digest."); goto err;
|
||||
}
|
||||
|
||||
add_trusted_dir_server(address, port, digest);
|
||||
|
||||
r = 0;
|
||||
goto done;
|
||||
err:
|
||||
r = -1;
|
||||
done:
|
||||
SMARTLIST_FOREACH(items, char*, s, tor_free(s));
|
||||
smartlist_free(items);
|
||||
if (address) tor_free(address);
|
||||
return r;
|
||||
}
|
||||
|
||||
const char *get_data_directory(or_options_t *options) {
|
||||
const char *d;
|
||||
if (options->DataDirectory)
|
||||
|
||||
+74
-32
@@ -27,10 +27,21 @@
|
||||
*/
|
||||
|
||||
static void
|
||||
directory_initiate_command(routerinfo_t *router, uint8_t purpose,
|
||||
const char *payload, int payload_len);
|
||||
directory_initiate_command_router(routerinfo_t *router, uint8_t purpose,
|
||||
const char *payload, int payload_len);
|
||||
static void
|
||||
directory_send_command(connection_t *conn, routerinfo_t *router, int purpose,
|
||||
directory_initiate_command_trusted_dir(trusted_dir_server_t *dirserv,
|
||||
uint8_t purpose, const char *payload, int payload_len);
|
||||
|
||||
static void
|
||||
directory_initiate_command(const char *address, uint32_t addr, uint16_t port,
|
||||
const char *platform,
|
||||
const char *digest, uint8_t purpose,
|
||||
const char *payload, int payload_len);
|
||||
|
||||
static void
|
||||
directory_send_command(connection_t *conn, const char *platform,
|
||||
uint16_t dir_port, int purpose,
|
||||
const char *payload, int payload_len);
|
||||
static int directory_handle_command(connection_t *conn);
|
||||
|
||||
@@ -75,7 +86,7 @@ directory_post_to_dirservers(uint8_t purpose, const char *payload,
|
||||
/* Note: this posts our descriptor to ourselves, if we're an
|
||||
* authdirserver. But I think that's ok. */
|
||||
if(router->is_trusted_dir)
|
||||
directory_initiate_command(router, purpose, payload, payload_len);
|
||||
directory_initiate_command_router(router, purpose, payload, payload_len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,29 +99,37 @@ void
|
||||
directory_get_from_dirserver(uint8_t purpose, const char *payload,
|
||||
int payload_len)
|
||||
{
|
||||
routerinfo_t *ds;
|
||||
routerinfo_t *r = NULL;
|
||||
trusted_dir_server_t *ds = NULL;
|
||||
|
||||
if (purpose == DIR_PURPOSE_FETCH_DIR) {
|
||||
if (advertised_server_mode()) {
|
||||
/* only ask authdirservers, and don't ask myself */
|
||||
ds = router_pick_directory_server(1, 1);
|
||||
r = router_pick_directory_server(1, 1);
|
||||
/* XXXX NM Enable this once we actually set keys for dirservers.
|
||||
* ds = router_pick_trusteddirserver(1);
|
||||
*/
|
||||
} else {
|
||||
/* anybody with a non-zero dirport will do */
|
||||
ds = router_pick_directory_server(0, 1);
|
||||
r = router_pick_directory_server(0, 1);
|
||||
}
|
||||
} else { // (purpose == DIR_PURPOSE_FETCH_RENDDESC)
|
||||
/* only ask authdirservers, any of them will do */
|
||||
ds = router_pick_directory_server(1, 0);
|
||||
r = router_pick_directory_server(1, 0);
|
||||
/* XXXX NM Enable this once we actually set keys for dirservers.
|
||||
* ds = router_pick_trusteddirserver(0);
|
||||
*/
|
||||
}
|
||||
|
||||
if (!ds) { /* no viable dirserver found */
|
||||
if (r)
|
||||
directory_initiate_command_router(r, purpose, payload, payload_len);
|
||||
else if (ds)
|
||||
directory_initiate_command_trusted_dir(ds, purpose, payload, payload_len);
|
||||
else
|
||||
log_fn(LOG_WARN,"No running dirservers known. Not trying. (purpose %d)", purpose);
|
||||
return;
|
||||
}
|
||||
|
||||
directory_initiate_command(ds, purpose, payload, payload_len);
|
||||
}
|
||||
|
||||
|
||||
/** Launch a new connection to the directory server <b>router</b> to upload or
|
||||
* download a service or rendezvous descriptor. <b>purpose</b> determines what
|
||||
* kind of directory connection we're launching, and must be one of
|
||||
@@ -121,13 +140,31 @@ directory_get_from_dirserver(uint8_t purpose, const char *payload,
|
||||
* and <b>payload_len</b> are the service ID we want to fetch.
|
||||
*/
|
||||
static void
|
||||
directory_initiate_command(routerinfo_t *router, uint8_t purpose,
|
||||
directory_initiate_command_router(routerinfo_t *router, uint8_t purpose,
|
||||
const char *payload, int payload_len)
|
||||
{
|
||||
directory_initiate_command(router->address, router->addr, router->dir_port,
|
||||
router->platform, router->identity_digest,
|
||||
purpose, payload, payload_len);
|
||||
}
|
||||
|
||||
static void
|
||||
directory_initiate_command_trusted_dir(trusted_dir_server_t *dirserv,
|
||||
uint8_t purpose, const char *payload, int payload_len)
|
||||
{
|
||||
directory_initiate_command(dirserv->address, dirserv->addr, dirserv->dir_port,
|
||||
NULL, dirserv->digest, purpose, payload, payload_len);
|
||||
}
|
||||
|
||||
static void
|
||||
directory_initiate_command(const char *address, uint32_t addr,
|
||||
uint16_t dir_port, const char *platform,
|
||||
const char *digest, uint8_t purpose,
|
||||
const char *payload, int payload_len)
|
||||
{
|
||||
connection_t *conn;
|
||||
|
||||
tor_assert(router);
|
||||
tor_assert(router->dir_port);
|
||||
tor_assert(address && addr && dir_port && digest);
|
||||
|
||||
switch (purpose) {
|
||||
case DIR_PURPOSE_FETCH_DIR:
|
||||
@@ -154,14 +191,15 @@ directory_initiate_command(routerinfo_t *router, uint8_t purpose,
|
||||
conn->addr = options.HttpProxyAddr;
|
||||
conn->port = options.HttpProxyPort;
|
||||
} else {
|
||||
conn->addr = router->addr;
|
||||
conn->port = router->dir_port;
|
||||
conn->addr = addr;
|
||||
conn->port = dir_port;
|
||||
}
|
||||
conn->address = tor_strdup(router->address);
|
||||
conn->nickname = tor_strdup(router->nickname);
|
||||
tor_assert(router->identity_pkey);
|
||||
conn->identity_pkey = crypto_pk_dup_key(router->identity_pkey);
|
||||
crypto_pk_get_digest(conn->identity_pkey, conn->identity_digest);
|
||||
conn->address = tor_strdup(address);
|
||||
/* conn->nickname = tor_strdup(router->nickname); */
|
||||
/* tor_assert(router->identity_pkey); */
|
||||
/* conn->identity_pkey = crypto_pk_dup_key(router->identity_pkey); */
|
||||
/* crypto_pk_get_digest(conn->identity_pkey, conn->identity_digest); */
|
||||
memcpy(conn->identity_digest, digest, DIGEST_LEN);
|
||||
|
||||
conn->purpose = purpose;
|
||||
|
||||
@@ -185,7 +223,8 @@ directory_initiate_command(routerinfo_t *router, uint8_t purpose,
|
||||
/* fall through */
|
||||
case 0:
|
||||
/* queue the command on the outbuf */
|
||||
directory_send_command(conn, router, purpose, payload, payload_len);
|
||||
directory_send_command(conn, platform, dir_port,
|
||||
purpose, payload, payload_len);
|
||||
|
||||
connection_watch_events(conn, POLLIN | POLLOUT | POLLERR);
|
||||
/* writable indicates finish, readable indicates broken link,
|
||||
@@ -206,7 +245,8 @@ directory_initiate_command(routerinfo_t *router, uint8_t purpose,
|
||||
conn->state = DIR_CONN_STATE_CLIENT_SENDING;
|
||||
connection_add(conn);
|
||||
/* queue the command on the outbuf */
|
||||
directory_send_command(conn, router, purpose, payload, payload_len);
|
||||
directory_send_command(conn, platform, dir_port,
|
||||
purpose, payload, payload_len);
|
||||
connection_watch_events(conn, POLLIN | POLLOUT | POLLERR);
|
||||
}
|
||||
}
|
||||
@@ -216,7 +256,8 @@ directory_initiate_command(routerinfo_t *router, uint8_t purpose,
|
||||
* directory_initiate_command.
|
||||
*/
|
||||
static void
|
||||
directory_send_command(connection_t *conn, routerinfo_t *router, int purpose,
|
||||
directory_send_command(connection_t *conn, const char *platform,
|
||||
uint16_t dir_port, int purpose,
|
||||
const char *payload, int payload_len) {
|
||||
char tmp[8192];
|
||||
char proxystring[128];
|
||||
@@ -226,14 +267,15 @@ directory_send_command(connection_t *conn, routerinfo_t *router, int purpose,
|
||||
char *httpcommand = NULL;
|
||||
|
||||
tor_assert(conn && conn->type == CONN_TYPE_DIR);
|
||||
tor_assert(router);
|
||||
tor_assert(dir_port && conn);
|
||||
|
||||
use_newer = tor_version_as_new_as(router->platform, "0.0.9pre1");
|
||||
/* If we don't know the platform, assume it's up-to-date. */
|
||||
use_newer = platform ? tor_version_as_new_as(platform, "0.0.9pre1"):1;
|
||||
|
||||
if(router->dir_port == 80) {
|
||||
strlcpy(hoststring, router->address, sizeof(hoststring));
|
||||
if(dir_port == 80) {
|
||||
strlcpy(hoststring, conn->address, sizeof(hoststring));
|
||||
} else {
|
||||
sprintf(hoststring, "%s:%d", router->address, router->dir_port);
|
||||
sprintf(hoststring, "%s:%d", conn->address, dir_port);
|
||||
}
|
||||
if(options.HttpProxy) {
|
||||
sprintf(proxystring, "http://%s", hoststring);
|
||||
@@ -245,7 +287,7 @@ directory_send_command(connection_t *conn, routerinfo_t *router, int purpose,
|
||||
case DIR_PURPOSE_FETCH_DIR:
|
||||
tor_assert(payload == NULL);
|
||||
log_fn(LOG_DEBUG, "Asking for %scompressed directory from server running %s",
|
||||
use_newer?"":"un", router->platform);
|
||||
use_newer?"":"un", platform?platform:"<unknown version>");
|
||||
httpcommand = "GET";
|
||||
strlcpy(url, use_newer ? "/tor/dir.z" : "/", sizeof(url));
|
||||
break;
|
||||
|
||||
+13
@@ -900,6 +900,9 @@ typedef struct {
|
||||
uint32_t HttpProxyAddr; /**< Parsed IPv4 addr for http proxy, if any */
|
||||
uint16_t HttpProxyPort; /**< Parsed port for http proxy, if any */
|
||||
|
||||
struct config_line_t *DirServers; /**< List of configuration lines
|
||||
* for directory servers. */
|
||||
|
||||
} or_options_t;
|
||||
|
||||
/* XXX are these good enough defaults? */
|
||||
@@ -1397,8 +1400,17 @@ int is_legal_nickname_or_hexdigest(const char *s);
|
||||
|
||||
/********************************* routerlist.c ***************************/
|
||||
|
||||
typedef struct trusted_dir_server_t {
|
||||
char *address;
|
||||
uint32_t addr;
|
||||
uint16_t dir_port;
|
||||
char digest[DIGEST_LEN];
|
||||
int is_running;
|
||||
} trusted_dir_server_t;
|
||||
|
||||
int router_reload_router_list(void);
|
||||
routerinfo_t *router_pick_directory_server(int requireauth, int requireothers);
|
||||
trusted_dir_server_t *router_pick_trusteddirserver(int requireothers);
|
||||
int all_directory_servers_down(void);
|
||||
struct smartlist_t;
|
||||
void routerlist_add_friends(struct smartlist_t *sl, routerinfo_t *router);
|
||||
@@ -1440,6 +1452,7 @@ void routerlist_update_from_runningrouters(routerlist_t *list,
|
||||
int router_update_status_from_smartlist(routerinfo_t *r,
|
||||
time_t list_time,
|
||||
smartlist_t *running_list);
|
||||
void add_trusted_dir_server(const char *addr, uint16_t port,const char *digest);
|
||||
|
||||
/********************************* routerparse.c ************************/
|
||||
|
||||
|
||||
+127
-34
@@ -18,17 +18,19 @@ extern or_options_t options; /**< command-line and config-file options */
|
||||
|
||||
/* ********************************************************************** */
|
||||
|
||||
static smartlist_t *trusted_dir_servers = NULL;
|
||||
|
||||
/* static function prototypes */
|
||||
static routerinfo_t *
|
||||
router_pick_directory_server_impl(int requireauth, int requireothers, int fascistfirewall);
|
||||
static void mark_all_authdirservers_up(void);
|
||||
static trusted_dir_server_t *
|
||||
router_pick_trusteddirserver_impl(int requireother, int fascistfirewall);
|
||||
static void mark_all_trusteddirservers_up(void);
|
||||
static int router_resolve_routerlist(routerlist_t *dir);
|
||||
static void clear_trusted_dir_servers(void);
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/** List of digests of keys for servers that are trusted directories. */
|
||||
static smartlist_t *trusted_dir_digests = NULL;
|
||||
|
||||
/****
|
||||
* Functions to manage and access our list of known routers. (Note:
|
||||
* dirservers maintain a separate, independent list of known router
|
||||
@@ -92,7 +94,7 @@ routerinfo_t *router_pick_directory_server(int requireauth, int requireothers) {
|
||||
|
||||
log_fn(LOG_INFO,"No dirservers are reachable. Trying them all again.");
|
||||
/* mark all authdirservers as up again */
|
||||
mark_all_authdirservers_up();
|
||||
mark_all_trusteddirservers_up();
|
||||
/* try again */
|
||||
choice = router_pick_directory_server_impl(requireauth, requireothers, 0);
|
||||
if(choice)
|
||||
@@ -110,6 +112,34 @@ routerinfo_t *router_pick_directory_server(int requireauth, int requireothers) {
|
||||
return choice;
|
||||
}
|
||||
|
||||
trusted_dir_server_t *router_pick_trusteddirserver(int requireothers) {
|
||||
trusted_dir_server_t *choice;
|
||||
|
||||
choice = router_pick_trusteddirserver_impl(requireothers,
|
||||
options.FascistFirewall);
|
||||
if(choice)
|
||||
return choice;
|
||||
|
||||
log_fn(LOG_INFO,"No trusted dirservers are reachable. Trying them all again.");
|
||||
/* mark all authdirservers as up again */
|
||||
mark_all_trusteddirservers_up();
|
||||
/* try again */
|
||||
choice = router_pick_trusteddirserver_impl(requireothers, 0);
|
||||
if(choice)
|
||||
return choice;
|
||||
|
||||
log_fn(LOG_WARN,"Still no dirservers %s. Reloading and trying again.",
|
||||
options.FascistFirewall ? "reachable" : "known");
|
||||
has_fetched_directory=0; /* reset it */
|
||||
routerlist_clear_trusted_directories();
|
||||
if(router_reload_router_list()) {
|
||||
return NULL;
|
||||
}
|
||||
/* give it one last try */
|
||||
choice = router_pick_trusteddirserver_impl(requireothers, 0);
|
||||
return choice;
|
||||
}
|
||||
|
||||
/** Pick a random running router from our routerlist. If requireauth,
|
||||
* it has to be a trusted server. If requireothers, it cannot be us.
|
||||
*/
|
||||
@@ -147,21 +177,48 @@ router_pick_directory_server_impl(int requireauth, int requireothers, int fascis
|
||||
return router;
|
||||
}
|
||||
|
||||
static trusted_dir_server_t *
|
||||
router_pick_trusteddirserver_impl(int requireother, int fascistfirewall)
|
||||
{
|
||||
smartlist_t *sl;
|
||||
routerinfo_t *me;
|
||||
char buf[16];
|
||||
trusted_dir_server_t *ds;
|
||||
sl = smartlist_create();
|
||||
me = router_get_my_routerinfo();
|
||||
|
||||
SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, d,
|
||||
{
|
||||
if (!d->is_running) continue;
|
||||
if (requireother && me &&
|
||||
!memcmp(me->identity_digest, d->digest, DIGEST_LEN))
|
||||
continue;
|
||||
if (fascistfirewall) {
|
||||
sprintf(buf,"%d",d->dir_port);
|
||||
if (!smartlist_string_isin(options.FirewallPorts, buf))
|
||||
continue;
|
||||
}
|
||||
smartlist_add(sl, d);
|
||||
});
|
||||
|
||||
ds = smartlist_choose(sl);
|
||||
smartlist_free(sl);
|
||||
return ds;
|
||||
}
|
||||
|
||||
/** Go through and mark the auth dirservers as up */
|
||||
static void mark_all_authdirservers_up(void) {
|
||||
int i;
|
||||
routerinfo_t *router;
|
||||
|
||||
if(!routerlist)
|
||||
return;
|
||||
|
||||
for(i=0; i < smartlist_len(routerlist->routers); i++) {
|
||||
router = smartlist_get(routerlist->routers, i);
|
||||
if(router->is_trusted_dir) {
|
||||
tor_assert(router->dir_port > 0);
|
||||
router->is_running = 1;
|
||||
router->status_set_at = time(NULL);
|
||||
}
|
||||
static void mark_all_trusteddirservers_up(void) {
|
||||
if(routerlist) {
|
||||
SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router,
|
||||
if(router->is_trusted_dir) {
|
||||
tor_assert(router->dir_port > 0);
|
||||
router->is_running = 1;
|
||||
router->status_set_at = time(NULL);
|
||||
});
|
||||
}
|
||||
if (trusted_dir_servers) {
|
||||
SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, dir,
|
||||
dir->is_running = 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,6 +237,12 @@ int all_directory_servers_down(void) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* XXXX NM look at trusted_dir_servers instead.
|
||||
if (!trusted_dir_servers)
|
||||
return 1;
|
||||
SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, dir,
|
||||
if (dir->is_running) return 0);
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -477,14 +540,13 @@ routerinfo_t *router_get_by_nickname(const char *nickname)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* XXX008 currently this trusted_dir_digests stuff is not used. */
|
||||
/** Return true iff <b>digest</b> is the digest of the identity key of
|
||||
* a trusted directory. */
|
||||
int router_digest_is_trusted_dir(const char *digest) {
|
||||
if (!trusted_dir_digests)
|
||||
if (!trusted_dir_servers)
|
||||
return 0;
|
||||
SMARTLIST_FOREACH(trusted_dir_digests, char *, cp,
|
||||
if (!memcmp(digest, cp, DIGEST_LEN)) return 1);
|
||||
SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ent,
|
||||
if (!memcmp(digest, ent->digest, DIGEST_LEN)) return 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -586,6 +648,11 @@ void routerlist_free(routerlist_t *rl)
|
||||
void router_mark_as_down(const char *digest) {
|
||||
routerinfo_t *router;
|
||||
tor_assert(digest);
|
||||
|
||||
SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, d,
|
||||
if (!memcmp(d->digest, digest, DIGEST_LEN))
|
||||
d->is_running = 0);
|
||||
|
||||
router = router_get_by_digest(digest);
|
||||
if(!router) /* we don't seem to know about him in the first place */
|
||||
return;
|
||||
@@ -619,7 +686,9 @@ int router_add_to_routerlist(routerinfo_t *router) {
|
||||
log_fn(LOG_DEBUG, "Replacing entry for router '%s/%s' [%s]",
|
||||
router->nickname, r->nickname, hex_str(id_digest,DIGEST_LEN));
|
||||
/* Remember whether we trust this router as a dirserver. */
|
||||
if (r->is_trusted_dir)
|
||||
/*XXXXNM first test is redundant; second should move elsewhere */
|
||||
if (r->is_trusted_dir ||
|
||||
router_digest_is_trusted_dir(router->identity_digest))
|
||||
router->is_trusted_dir = 1;
|
||||
/* If the address hasn't changed; no need to re-resolve. */
|
||||
if (!strcasecmp(r->address, router->address))
|
||||
@@ -735,10 +804,7 @@ void routerlist_clear_trusted_directories(void)
|
||||
SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, r,
|
||||
r->is_trusted_dir = 0);
|
||||
}
|
||||
if (trusted_dir_digests) {
|
||||
SMARTLIST_FOREACH(trusted_dir_digests, char *, cp, tor_free(cp));
|
||||
smartlist_clear(trusted_dir_digests);
|
||||
}
|
||||
clear_trusted_dir_servers();
|
||||
}
|
||||
|
||||
/** Helper function: read routerinfo elements from s, and throw out the
|
||||
@@ -760,17 +826,12 @@ int router_load_routerlist_from_string(const char *s, int trusted)
|
||||
}
|
||||
if (trusted) {
|
||||
int i;
|
||||
if (!trusted_dir_digests)
|
||||
trusted_dir_digests = smartlist_create();
|
||||
for (i=0;i<smartlist_len(new_list->routers);++i) {
|
||||
routerinfo_t *r = smartlist_get(new_list->routers, i);
|
||||
if (r->dir_port) {
|
||||
char *b;
|
||||
log_fn(LOG_DEBUG,"Trusting router %s.", r->nickname);
|
||||
r->is_trusted_dir = 1;
|
||||
b = tor_malloc(DIGEST_LEN);
|
||||
memcpy(b, r->identity_digest, DIGEST_LEN);
|
||||
smartlist_add(trusted_dir_digests, b);
|
||||
add_trusted_dir_server(r->address, r->dir_port, r->identity_digest);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1079,6 +1140,38 @@ int router_update_status_from_smartlist(routerinfo_t *router,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void add_trusted_dir_server(const char *addr, uint16_t port, const char *digest)
|
||||
{
|
||||
trusted_dir_server_t *ent;
|
||||
uint32_t a;
|
||||
if (!trusted_dir_servers)
|
||||
trusted_dir_servers = smartlist_create();
|
||||
|
||||
if (tor_lookup_hostname(addr, &a)) {
|
||||
log_fn(LOG_WARN, "Unable to lookup address for directory server at %s",
|
||||
addr);
|
||||
return;
|
||||
}
|
||||
|
||||
ent = tor_malloc(sizeof(trusted_dir_server_t));
|
||||
ent->address = tor_strdup(addr);
|
||||
ent->addr = a;
|
||||
ent->dir_port = port;
|
||||
ent->is_running = 1;
|
||||
memcpy(ent->digest, digest, DIGEST_LEN);
|
||||
}
|
||||
|
||||
static void clear_trusted_dir_servers(void)
|
||||
{
|
||||
if (trusted_dir_servers) {
|
||||
SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ent,
|
||||
{ tor_free(ent->address); tor_free(ent); });
|
||||
smartlist_clear(trusted_dir_servers);
|
||||
} else {
|
||||
trusted_dir_servers = smartlist_create();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Local Variables:
|
||||
mode:c
|
||||
|
||||
@@ -577,17 +577,12 @@ static crypto_pk_env_t *find_dir_signing_key(const char *str)
|
||||
static int dir_signing_key_is_trusted(crypto_pk_env_t *key)
|
||||
{
|
||||
char digest[DIGEST_LEN];
|
||||
routerinfo_t *r;
|
||||
if (!key) return 0;
|
||||
if (crypto_pk_get_digest(key, digest) < 0) {
|
||||
log_fn(LOG_WARN, "Error computing dir-signing-key digest");
|
||||
return 0;
|
||||
}
|
||||
if (!(r = router_get_by_digest(digest))) {
|
||||
log_fn(LOG_WARN, "No router known with given dir-signing-key digest");
|
||||
return 0;
|
||||
}
|
||||
if (! r->is_trusted_dir) {
|
||||
if(!router_digest_is_trusted_dir(digest)) {
|
||||
log_fn(LOG_WARN, "Listed dir-signing-key is not trusted");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user