Split MyFamily into user-specified version and normalized version

This change prevents a no-longer-supported behavior where we change
options that would later be written back to torrc with a SAVECONF.

Also, use the "Pointer to final pointer" trick to build the
normalized list, to avoid special-casing the first element.
This commit is contained in:
Nick Mathewson 2017-05-09 08:18:41 -04:00
parent fa04fe1674
commit b8abedfeee
3 changed files with 23 additions and 24 deletions

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, LINELIST, NULL), VAR("MyFamily", LINELIST, MyFamily_lines, 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 normalize_nickname_list(config_line_t **lst, const char *name, static int normalize_nickname_list(config_line_t **normalized_out,
const config_line_t *lst, const char *name,
char **msg); 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);
@ -916,6 +917,7 @@ or_options_free(or_options_t *options)
tor_free(options->BridgePassword_AuthDigest_); tor_free(options->BridgePassword_AuthDigest_);
tor_free(options->command_arg); tor_free(options->command_arg);
tor_free(options->master_key_fname); tor_free(options->master_key_fname);
config_free_lines(options->MyFamily);
config_free(&options_format, options); config_free(&options_format, options);
} }
@ -3880,13 +3882,14 @@ options_validate(or_options_t *old_options, or_options_t *options,
"have it group-readable."); "have it group-readable.");
} }
if (options->MyFamily && options->BridgeRelay) { if (options->MyFamily_lines && options->BridgeRelay) {
log_warn(LD_CONFIG, "Listing a family for a bridge relay is not " log_warn(LD_CONFIG, "Listing a family for a bridge relay is not "
"supported: it can reveal bridge fingerprints to censors. " "supported: it can reveal bridge fingerprints to censors. "
"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 (normalize_nickname_list(&options->MyFamily, "MyFamily", msg)) if (normalize_nickname_list(&options->MyFamily,
options->MyFamily_lines, "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();
@ -4697,16 +4700,19 @@ get_default_conf_file(int defaults_file)
* Warn and return -1 on failure. * Warn and return -1 on failure.
*/ */
static int static int
normalize_nickname_list(config_line_t **lst, const char *name, char **msg) normalize_nickname_list(config_line_t **normalized_out,
const config_line_t *lst, const char *name,
char **msg)
{ {
if (!*lst) if (!lst)
return 0; return 0;
config_line_t *new_nicknames = NULL; config_line_t *new_nicknames = NULL;
config_line_t *new_nicknames_last = NULL; config_line_t **new_nicknames_next = &new_nicknames;
config_line_t *cl;
for (cl = *lst; cl; cl = cl->next) { const config_line_t *cl;
char *line = cl->value; for (cl = lst; cl; cl = cl->next) {
const char *line = cl->value;
if (!line) if (!line)
continue; continue;
@ -4748,14 +4754,8 @@ normalize_nickname_list(config_line_t **lst, const char *name, char **msg)
next->value = normalized; next->value = normalized;
next->next = NULL; next->next = NULL;
if (!new_nicknames) { *new_nicknames_next = next;
new_nicknames = next; new_nicknames_next = &next->next;
new_nicknames_last = next;
} else {
new_nicknames_last->next = next;
new_nicknames_last = next;
}
} SMARTLIST_FOREACH_END(s); } SMARTLIST_FOREACH_END(s);
SMARTLIST_FOREACH(sl, char *, s, tor_free(s)); SMARTLIST_FOREACH(sl, char *, s, tor_free(s));
@ -4767,9 +4767,7 @@ normalize_nickname_list(config_line_t **lst, const char *name, char **msg)
} }
} }
// Replace the caller's nickname list with the normalized one *normalized_out = new_nicknames;
config_free_lines(*lst);
*lst = new_nicknames;
return 0; return 0;
} }

View File

@ -3951,7 +3951,8 @@ 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;
config_line_t *MyFamily; /**< Declared family for this OR. */ config_line_t *MyFamily_lines; /**< Declared family for this OR. */
config_line_t *MyFamily; /**< Declared family for this OR, normalized */
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

@ -878,7 +878,7 @@ test_config_fix_my_family(void *arg)
options_init(options); options_init(options);
options_init(defaults); options_init(defaults);
options->MyFamily = family; options->MyFamily_lines = family;
options_validate(NULL, options, defaults, 0, &err) ; options_validate(NULL, options, defaults, 0, &err) ;