From 7fa5d224d4469de9ff69f41a245ada9b329a2840 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 15 Oct 2004 01:58:11 +0000 Subject: [PATCH] Implement "families" of coadministered nodes; prevent them all from appearing on the same circuit. svn:r2523 --- src/or/circuitbuild.c | 10 +++++----- src/or/config.c | 43 +++++++++++++++++++++++++++++++++++++++---- src/or/or.h | 7 ++++--- src/or/router.c | 22 ++++++++++++++++++++-- src/or/routerlist.c | 32 +++++++++++++++++++++++++++++--- src/or/routerparse.c | 16 ++++++++++++++++ 6 files changed, 113 insertions(+), 17 deletions(-) diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index b52f90dbae..a98821cca4 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -1080,16 +1080,16 @@ static routerinfo_t *choose_good_middle_server(cpath_build_state_t *state, excluded = smartlist_create(); if((r = router_get_by_digest(state->chosen_exit_digest))) { smartlist_add(excluded, r); - routerlist_add_friends(excluded, r); + routerlist_add_family(excluded, r); } if((r = routerlist_find_my_routerinfo())) { smartlist_add(excluded, r); - routerlist_add_friends(excluded, r); + routerlist_add_family(excluded, r); } for (i = 0, cpath = head; i < cur_len; ++i, cpath=cpath->next) { if((r = router_get_by_digest(cpath->identity_digest))) { smartlist_add(excluded, r); - routerlist_add_friends(excluded, r); + routerlist_add_family(excluded, r); } } choice = router_choose_random_node("", options.ExcludeNodes, excluded, @@ -1106,11 +1106,11 @@ static routerinfo_t *choose_good_entry_server(cpath_build_state_t *state) if((r = router_get_by_digest(state->chosen_exit_digest))) { smartlist_add(excluded, r); - routerlist_add_friends(excluded, r); + routerlist_add_family(excluded, r); } if((r = routerlist_find_my_routerinfo())) { smartlist_add(excluded, r); - routerlist_add_friends(excluded, r); + routerlist_add_family(excluded, r); } if(options.FascistFirewall) { /* exclude all ORs that listen on the wrong port */ diff --git a/src/or/config.c b/src/or/config.c index db73a2fcc9..8edce5121b 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -244,6 +244,7 @@ config_assign(or_options_t *options, struct config_line_t *list) config_compare(list, "FascistFirewall",CONFIG_TYPE_BOOL, &options->FascistFirewall) || config_compare(list, "FirewallPorts",CONFIG_TYPE_CSV, &options->FirewallPorts) || + config_compare(list, "MyFamily", CONFIG_TYPE_STRING, &options->MyFamily) || config_compare(list, "Group", CONFIG_TYPE_STRING, &options->Group) || @@ -517,6 +518,7 @@ init_options(or_options_t *options) options->RendConfigLines = NULL; options->FirewallPorts = NULL; options->DirServers = NULL; + options->MyFamily = NULL; } static char * @@ -554,6 +556,30 @@ get_default_conf_file(void) #endif } +/** Verify whether lst is a string containing valid-looking space-separated + * nicknames, or NULL. Return 0 on success. Warn and return -1 on failure. + */ +static int check_nickname_list(const char *lst, const char *name) +{ + int r = 0; + smartlist_t *sl; + + if (!lst) + return 0; + sl = smartlist_create(); + smartlist_split_string(sl, lst, ",", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); + SMARTLIST_FOREACH(sl, const char *, s, + { + if (!is_legal_nickname_or_hexdigest(s)) { + log_fn(LOG_WARN, "Invalid nickname '%s' in %s line", s, name); + r = -1; + } + }); + SMARTLIST_FOREACH(sl, char *, s, tor_free(s)); + smartlist_free(sl); + return r; +} + /** Read a configuration file into options, finding the configuration * file location based on the command line. After loading the options, * validate them for consistency. Return 0 if success, <0 if failure. */ @@ -838,6 +864,19 @@ getconfig(int argc, char **argv, or_options_t *options) } } + if (check_nickname_list(options->ExitNodes, "ExitNodes")) + return -1; + if (check_nickname_list(options->EntryNodes, "EntryNodes")) + return -1; + if (check_nickname_list(options->ExcludeNodes, "ExcludeNodes")) + return -1; + if (check_nickname_list(options->RendNodes, "RendNodes")) + return -1; + if (check_nickname_list(options->RendNodes, "RendExcludeNodes")) + return -1; + if (check_nickname_list(options->MyFamily, "MyFamily")) + return -1; + clear_trusted_dir_servers(); if (!options->DirServers) { add_default_trusted_dirservers(); @@ -848,10 +887,6 @@ getconfig(int argc, char **argv, or_options_t *options) } } - /* XXX look at the various nicknamelists and make sure they're - * valid and don't have hostnames that are too long. - */ - if (rend_config_services(options) < 0) { result = -1; } diff --git a/src/or/or.h b/src/or/or.h index e58695c79f..080d9aaaed 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -597,6 +597,8 @@ typedef struct { int is_verified; /**< Has a trusted dirserver validated this OR? */ int is_trusted_dir; /**< Do we trust this OR as a directory server? */ + smartlist_t *declared_family; /**< Nicknames of router which this router + * claims are its family. */ } routerinfo_t; /** Contents of a directory of onion routers. */ @@ -890,8 +892,6 @@ typedef struct { int NumCpus; /**< How many CPUs should we try to use? */ int RunTesting; /**< If true, create testing circuits to measure how well the * other ORs are running. */ - struct config_line_t *TrustedDirs; /**< List of fingerprints of keys that are - allowed to sign directories. */ struct config_line_t *RendConfigLines; /**< List of configuration lines * for rendezvous services. */ char *ContactInfo; /**< Contact info to be published in the directory */ @@ -902,6 +902,7 @@ typedef struct { struct config_line_t *DirServers; /**< List of configuration lines * for directory servers. */ + char *MyFamily; /**< Declared family for this OR. */ } or_options_t; /* XXX are these good enough defaults? */ @@ -1415,7 +1416,7 @@ routerinfo_t *router_pick_directory_server(int requireothers); trusted_dir_server_t *router_pick_trusteddirserver(int requireothers); int all_trusted_directory_servers_down(void); struct smartlist_t; -void routerlist_add_friends(struct smartlist_t *sl, routerinfo_t *router); +void routerlist_add_family(struct smartlist_t *sl, routerinfo_t *router); void add_nickname_list_to_smartlist(struct smartlist_t *sl, const char *list, int warn_if_down); routerinfo_t *routerlist_find_my_routerinfo(void); int router_nickname_matches(routerinfo_t *router, const char *nickname); diff --git a/src/or/router.c b/src/or/router.c index df0f428977..ab606ee69b 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -552,6 +552,13 @@ int router_rebuild_descriptor(void) { ri->is_trusted_dir = authdir_mode(); if(desc_routerinfo) /* inherit values */ ri->is_verified = desc_routerinfo->is_verified; + if (options.MyFamily) { + ri->declared_family = smartlist_create(); + smartlist_split_string(ri->declared_family, options.MyFamily, ",", + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); + } else { + ri->declared_family = NULL; + } if (desc_routerinfo) routerinfo_free(desc_routerinfo); @@ -600,6 +607,7 @@ int router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, int result=0; struct exit_policy_t *tmpe; char *bandwidth_usage; + char *family_line; #ifdef DEBUG_ROUTER_DUMP_ROUTER_TO_STRING char *s_tmp, *s_dup; const char *cp; @@ -639,6 +647,16 @@ int router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, /* How busy have we been? */ bandwidth_usage = rep_hist_get_bandwidth_lines(); + if (router->declared_family && smartlist_len(router->declared_family)) { + char *s = smartlist_join_strings(router->declared_family, " ", 0); + size_t n = strlen(s) + strlen("opt family ") + 2; /* 1 for \n, 1 for \0. */ + family_line = tor_malloc(n); + snprintf(family_line, n, "opt family %s\n", s); + tor_free(s); + } else { + family_line = tor_strdup(""); + } + /* Generate the easy portion of the router descriptor. */ result = snprintf(s, maxlen, "router %s %s %d %d %d\n" @@ -648,7 +666,7 @@ int router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, "opt uptime %ld\n" "bandwidth %d %d %d\n" "onion-key\n%s" - "signing-key\n%s%s", + "signing-key\n%s%s%s", router->nickname, router->address, router->or_port, @@ -665,7 +683,7 @@ int router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, (int) router->bandwidthburst, (int) router->bandwidthcapacity, onion_pkey, identity_pkey, - bandwidth_usage); + family_line, bandwidth_usage); tor_free(onion_pkey); tor_free(identity_pkey); diff --git a/src/or/routerlist.c b/src/or/routerlist.c index f3670a51a7..850b6383a9 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -225,11 +225,28 @@ int all_trusted_directory_servers_down(void) { return 1; } -/** Add all the friends of router to the smartlist sl. +/** Add all the family of router to the smartlist sl. */ -void routerlist_add_friends(smartlist_t *sl, routerinfo_t *router) { - +void routerlist_add_family(smartlist_t *sl, routerinfo_t *router) { + routerinfo_t *r; + if (!router->declared_family) + return; + + /* Add every r such that router declares familyhip with r, and r + * declares familyhip with router. */ + SMARTLIST_FOREACH(router->declared_family, const char *, n, + { + if (!(r = router_get_by_nickname(n))) + continue; + if (!r->declared_family) + continue; + SMARTLIST_FOREACH(r->declared_family, const char *, n2, + { + if (router_nickname_matches(router, n2)) + smartlist_add(sl, r); + }); + }); } /** Given a comma-and-whitespace separated list of nicknames, see which @@ -583,6 +600,10 @@ void routerinfo_free(routerinfo_t *router) crypto_free_pk_env(router->onion_pkey); if (router->identity_pkey) crypto_free_pk_env(router->identity_pkey); + if (router->declared_family) { + SMARTLIST_FOREACH(router->declared_family, char *, s, tor_free(s)); + smartlist_free(router->declared_family); + } exit_policy_free(router->exit_policy); tor_free(router); } @@ -611,6 +632,11 @@ routerinfo_t *routerinfo_copy(const routerinfo_t *router) (*e)->string = tor_strdup((*e)->string); e = & ((*e)->next); } + if (r->declared_family) { + r->declared_family = smartlist_create(); + SMARTLIST_FOREACH(router->declared_family, const char *, s, + smartlist_add(r->declared_family, tor_strdup(s))); + } return r; } diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 6ee1c3f915..540e8b338e 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -41,6 +41,7 @@ typedef enum { K_NETWORK_STATUS, K_UPTIME, K_DIR_SIGNING_KEY, + K_FAMILY, _UNRECOGNIZED, _ERR, _EOF, @@ -115,6 +116,7 @@ static struct { { "network-status", K_NETWORK_STATUS, NO_ARGS, NO_OBJ, DIR_ONLY }, { "uptime", K_UPTIME, ARGS, NO_OBJ, RTR_ONLY }, { "dir-signing-key", K_DIR_SIGNING_KEY, ARGS, OBJ_OK, DIR_ONLY }, + { "family", K_FAMILY, ARGS, NO_OBJ, RTR_ONLY }, { NULL, -1, NO_ARGS, NO_OBJ, ANY } }; @@ -769,6 +771,7 @@ routerinfo_t *router_parse_entry_from_string(const char *s, router = tor_malloc_zero(sizeof(routerinfo_t)); router->onion_pkey = router->identity_pkey = NULL; + router->declared_family = NULL; ports_set = bw_set = 0; if (tok->n_args == 2 || tok->n_args == 5 || tok->n_args == 6) { @@ -876,6 +879,19 @@ routerinfo_t *router_parse_entry_from_string(const char *s, log_fn(LOG_WARN,"Error in exit policy"); goto err;} ); + + if ((tok = find_first_by_keyword(tokens, K_FAMILY)) && tok->n_args) { + int i; + router->declared_family = smartlist_create(); + for (i=0;in_args;++i) { + if (!is_legal_nickname_or_hexdigest(tok->args[i])) { + log_fn(LOG_WARN, "Illegal nickname %s in family line", tok->args[i]); + goto err; + } + smartlist_add(router->declared_family, tor_strdup(tok->args[i])); + } + } + if (!(tok = find_first_by_keyword(tokens, K_ROUTER_SIGNATURE))) { log_fn(LOG_WARN, "Missing router signature"); goto err; }