MyFamily config string is now a list. #4998

This commit is contained in:
Daniel Pinto 2017-04-14 13:04:37 +01:00
parent b081a7ed21
commit fa04fe1674
5 changed files with 104 additions and 61 deletions

View File

@ -1813,14 +1813,15 @@ is non-zero):
If we have more onionskins queued for processing than we can process in If we have more onionskins queued for processing than we can process in
this amount of time, reject new ones. (Default: 1750 msec) this amount of time, reject new ones. (Default: 1750 msec)
[[MyFamily]] **MyFamily** __node__,__node__,__...__:: [[MyFamily]] **MyFamily** __node__::
Declare that this Tor server is controlled or administered by a group or Declare that this Tor server is controlled or administered by a group or
organization identical or similar to that of the other servers, defined by organization identical or similar to that of the other servers, defined by
their identity fingerprints. When two servers both declare their identity fingerprints. This option can be repeated many times, for
that they are in the same \'family', Tor clients will not use them in the multiple families. When two servers both declare that they are in the
same circuit. (Each server only needs to list the other servers in its same \'family', Tor clients will not use them in the same circuit. (Each
family; it doesn't need to list itself, but it won't hurt.) Do not list server only needs to list the other servers in its family; it doesn't need to
any bridge relay as it would compromise its concealment. + list itself, but it won't hurt.) Do not list any bridge relay as it would
compromise its concealment. +
+ +
When listing a node, it's better to list it by fingerprint than by When listing a node, it's better to list it by fingerprint than by
nickname: fingerprints are more reliable. nickname: fingerprints are more reliable.

View File

@ -395,7 +395,7 @@ static config_var_t option_vars_[] = {
V(MaxOnionQueueDelay, MSEC_INTERVAL, "1750 msec"), V(MaxOnionQueueDelay, MSEC_INTERVAL, "1750 msec"),
V(MaxUnparseableDescSizeToLog, MEMUNIT, "10 MB"), V(MaxUnparseableDescSizeToLog, MEMUNIT, "10 MB"),
V(MinMeasuredBWsForAuthToIgnoreAdvertised, INT, "500"), V(MinMeasuredBWsForAuthToIgnoreAdvertised, INT, "500"),
V(MyFamily, STRING, NULL), V(MyFamily, LINELIST, NULL),
V(NewCircuitPeriod, INTERVAL, "30 seconds"), V(NewCircuitPeriod, INTERVAL, "30 seconds"),
OBSOLETE("NamingAuthoritativeDirectory"), OBSOLETE("NamingAuthoritativeDirectory"),
V(NATDListenAddress, LINELIST, NULL), V(NATDListenAddress, LINELIST, NULL),
@ -707,7 +707,8 @@ static int options_transition_affects_workers(
const or_options_t *old_options, const or_options_t *new_options); const or_options_t *old_options, const or_options_t *new_options);
static int options_transition_affects_descriptor( static int options_transition_affects_descriptor(
const or_options_t *old_options, const or_options_t *new_options); const or_options_t *old_options, const or_options_t *new_options);
static int check_nickname_list(char **lst, const char *name, char **msg); static int normalize_nickname_list(config_line_t **lst, const char *name,
char **msg);
static char *get_bindaddr_from_transport_listen_line(const char *line, static char *get_bindaddr_from_transport_listen_line(const char *line,
const char *transport); const char *transport);
static int parse_ports(or_options_t *options, int validate_only, static int parse_ports(or_options_t *options, int validate_only,
@ -3885,7 +3886,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
"You should also make sure you aren't listing this bridge's " "You should also make sure you aren't listing this bridge's "
"fingerprint in any other MyFamily."); "fingerprint in any other MyFamily.");
} }
if (check_nickname_list(&options->MyFamily, "MyFamily", msg)) if (normalize_nickname_list(&options->MyFamily, "MyFamily", msg))
return -1; return -1;
for (cl = options->NodeFamilies; cl; cl = cl->next) { for (cl = options->NodeFamilies; cl; cl = cl->next) {
routerset_t *rs = routerset_new(); routerset_t *rs = routerset_new();
@ -4593,7 +4594,7 @@ options_transition_affects_descriptor(const or_options_t *old_options,
get_effective_bwburst(old_options) != get_effective_bwburst(old_options) !=
get_effective_bwburst(new_options) || get_effective_bwburst(new_options) ||
!opt_streq(old_options->ContactInfo, new_options->ContactInfo) || !opt_streq(old_options->ContactInfo, new_options->ContactInfo) ||
!opt_streq(old_options->MyFamily, new_options->MyFamily) || !config_lines_eq(old_options->MyFamily, new_options->MyFamily) ||
!opt_streq(old_options->AccountingStart, new_options->AccountingStart) || !opt_streq(old_options->AccountingStart, new_options->AccountingStart) ||
old_options->AccountingMax != new_options->AccountingMax || old_options->AccountingMax != new_options->AccountingMax ||
old_options->AccountingRule != new_options->AccountingRule || old_options->AccountingRule != new_options->AccountingRule ||
@ -4689,27 +4690,33 @@ get_default_conf_file(int defaults_file)
#endif #endif
} }
/** Verify whether lst is a string containing valid-looking comma-separated /** Verify whether lst is a list of strings containing valid-looking
* nicknames, or NULL. Will normalise <b>lst</b> to prefix '$' to any nickname * comma-separated nicknames, or NULL. Will normalise <b>lst</b> to prefix '$'
* or fingerprint that needs it. Return 0 on success. * to any nickname or fingerprint that needs it. Also splits comma-separated
* list elements into multiple elements. Return 0 on success.
* Warn and return -1 on failure. * Warn and return -1 on failure.
*/ */
static int static int
check_nickname_list(char **lst, const char *name, char **msg) normalize_nickname_list(config_line_t **lst, const char *name, char **msg)
{ {
int r = 0;
smartlist_t *sl;
int changes = 0;
if (!*lst) if (!*lst)
return 0; return 0;
sl = smartlist_new();
smartlist_split_string(sl, *lst, ",", config_line_t *new_nicknames = NULL;
config_line_t *new_nicknames_last = NULL;
config_line_t *cl;
for (cl = *lst; cl; cl = cl->next) {
char *line = cl->value;
if (!line)
continue;
int valid_line = 1;
smartlist_t *sl = smartlist_new();
smartlist_split_string(sl, line, ",",
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK|SPLIT_STRIP_SPACE, 0); SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK|SPLIT_STRIP_SPACE, 0);
SMARTLIST_FOREACH_BEGIN(sl, char *, s) SMARTLIST_FOREACH_BEGIN(sl, char *, s)
{ {
char *normalized = NULL;
if (!is_legal_nickname_or_hexdigest(s)) { if (!is_legal_nickname_or_hexdigest(s)) {
// check if first char is dollar // check if first char is dollar
if (s[0] != '$') { if (s[0] != '$') {
@ -4718,36 +4725,53 @@ check_nickname_list(char **lst, const char *name, char **msg)
tor_asprintf(&prepended, "$%s", s); tor_asprintf(&prepended, "$%s", s);
if (is_legal_nickname_or_hexdigest(prepended)) { if (is_legal_nickname_or_hexdigest(prepended)) {
// The nickname is valid when it's prepended, swap the current // The nickname is valid when it's prepended, set it as the
// version with a prepended one // normalized version
tor_free(s); normalized = prepended;
SMARTLIST_REPLACE_CURRENT(sl, s, prepended); } else {
changes = 1;
continue;
}
// Still not valid, free and fallback to error message // Still not valid, free and fallback to error message
tor_free(prepended); tor_free(prepended);
} }
}
if (!normalized) {
tor_asprintf(msg, "Invalid nickname '%s' in %s line", s, name); tor_asprintf(msg, "Invalid nickname '%s' in %s line", s, name);
r = -1; valid_line = 0;
break; break;
} }
} else {
normalized = tor_strdup(s);
} }
SMARTLIST_FOREACH_END(s);
// Replace the caller's nickname list with a fixed one config_line_t *next = tor_malloc_zero(sizeof(*next));
if (changes && r == 0) { next->key = tor_strdup(cl->key);
char *newNicknames = smartlist_join_strings(sl, ", ", 0, NULL); next->value = normalized;
tor_free(*lst); next->next = NULL;
*lst = newNicknames;
if (!new_nicknames) {
new_nicknames = next;
new_nicknames_last = next;
} else {
new_nicknames_last->next = next;
new_nicknames_last = next;
} }
} SMARTLIST_FOREACH_END(s);
SMARTLIST_FOREACH(sl, char *, s, tor_free(s)); SMARTLIST_FOREACH(sl, char *, s, tor_free(s));
smartlist_free(sl); smartlist_free(sl);
return r; if (!valid_line) {
config_free_lines(new_nicknames);
return -1;
}
}
// Replace the caller's nickname list with the normalized one
config_free_lines(*lst);
*lst = new_nicknames;
return 0;
} }
/** Learn config file name from command line arguments, or use the default. /** Learn config file name from command line arguments, or use the default.

View File

@ -3951,7 +3951,7 @@ typedef struct {
/** If set, use these bridge authorities and not the default one. */ /** If set, use these bridge authorities and not the default one. */
config_line_t *AlternateBridgeAuthority; config_line_t *AlternateBridgeAuthority;
char *MyFamily; /**< Declared family for this OR. */ config_line_t *MyFamily; /**< Declared family for this OR. */
config_line_t *NodeFamilies; /**< List of config lines for config_line_t *NodeFamilies; /**< List of config lines for
* node families */ * node families */
smartlist_t *NodeFamilySets; /**< List of parsed NodeFamilies values. */ smartlist_t *NodeFamilySets; /**< List of parsed NodeFamilies values. */

View File

@ -2278,14 +2278,12 @@ router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e)
} }
if (options->MyFamily && ! options->BridgeRelay) { if (options->MyFamily && ! options->BridgeRelay) {
smartlist_t *family;
if (!warned_nonexistent_family) if (!warned_nonexistent_family)
warned_nonexistent_family = smartlist_new(); warned_nonexistent_family = smartlist_new();
family = smartlist_new();
ri->declared_family = smartlist_new(); ri->declared_family = smartlist_new();
smartlist_split_string(family, options->MyFamily, ",", config_line_t *family;
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK|SPLIT_STRIP_SPACE, 0); for (family = options->MyFamily; family; family = family->next) {
SMARTLIST_FOREACH_BEGIN(family, char *, name) { char *name = family->value;
const node_t *member; const node_t *member;
if (!strcasecmp(name, options->Nickname)) if (!strcasecmp(name, options->Nickname))
goto skip; /* Don't list ourself, that's redundant */ goto skip; /* Don't list ourself, that's redundant */
@ -2324,13 +2322,11 @@ router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e)
} }
skip: skip:
tor_free(name); tor_free(name);
} SMARTLIST_FOREACH_END(name); }
/* remove duplicates from the list */ /* remove duplicates from the list */
smartlist_sort_strings(ri->declared_family); smartlist_sort_strings(ri->declared_family);
smartlist_uniq_strings(ri->declared_family); smartlist_uniq_strings(ri->declared_family);
smartlist_free(family);
} }
/* Now generate the extrainfo. */ /* Now generate the extrainfo. */

View File

@ -854,9 +854,23 @@ static void
test_config_fix_my_family(void *arg) test_config_fix_my_family(void *arg)
{ {
char *err = NULL; char *err = NULL;
const char *family = "$1111111111111111111111111111111111111111, " config_line_t *family = tor_malloc_zero(sizeof(config_line_t));
family->key = tor_strdup("MyFamily");
family->value = tor_strdup("$1111111111111111111111111111111111111111, "
"1111111111111111111111111111111111111112, " "1111111111111111111111111111111111111112, "
"$1111111111111111111111111111111111111113"; "$1111111111111111111111111111111111111113");
config_line_t *family2 = tor_malloc_zero(sizeof(config_line_t));
family2->key = tor_strdup("MyFamily");
family2->value = tor_strdup("1111111111111111111111111111111111111114");
config_line_t *family3 = tor_malloc_zero(sizeof(config_line_t));
family3->key = tor_strdup("MyFamily");
family3->value = tor_strdup("$1111111111111111111111111111111111111115");
family->next = family2;
family2->next = family3;
family3->next = NULL;
or_options_t* options = options_new(); or_options_t* options = options_new();
or_options_t* defaults = options_new(); or_options_t* defaults = options_new();
@ -864,7 +878,7 @@ test_config_fix_my_family(void *arg)
options_init(options); options_init(options);
options_init(defaults); options_init(defaults);
options->MyFamily = tor_strdup(family); options->MyFamily = family;
options_validate(NULL, options, defaults, 0, &err) ; options_validate(NULL, options, defaults, 0, &err) ;
@ -872,10 +886,18 @@ test_config_fix_my_family(void *arg)
TT_FAIL(("options_validate failed: %s", err)); TT_FAIL(("options_validate failed: %s", err));
} }
tt_str_op(options->MyFamily,OP_EQ, const char *valid[] = { "$1111111111111111111111111111111111111111",
"$1111111111111111111111111111111111111111, " "$1111111111111111111111111111111111111112",
"$1111111111111111111111111111111111111112, " "$1111111111111111111111111111111111111113",
"$1111111111111111111111111111111111111113"); "$1111111111111111111111111111111111111114",
"$1111111111111111111111111111111111111115" };
int ret_size = 0;
config_line_t *ret;
for (ret = options->MyFamily; ret && ret_size < 5; ret = ret->next) {
tt_str_op(ret->value, OP_EQ, valid[ret_size]);
ret_size++;
}
tt_int_op(ret_size, OP_EQ, 5);
done: done:
if (err != NULL) { if (err != NULL) {