Browse Source

Merge remote-tracking branch 'public/deprecation_v2'

Nick Mathewson 7 years ago
parent
commit
507f07de09
9 changed files with 162 additions and 30 deletions
  1. 4 0
      doc/tor.1.txt
  2. 83 10
      src/or/config.c
  3. 2 2
      src/or/config.h
  4. 48 7
      src/or/confparse.c
  5. 12 1
      src/or/confparse.h
  6. 3 2
      src/or/control.c
  7. 2 1
      src/or/shared_random_state.c
  8. 2 1
      src/or/statefile.c
  9. 6 6
      src/test/test_options.c

+ 4 - 0
doc/tor.1.txt

@@ -84,6 +84,10 @@ COMMAND-LINE OPTIONS
 [[opt-list-torrc-options]] **--list-torrc-options**::
     List all valid options.
 
+[[opt-list-deprecated-options]] **--list-deprecated-options**::
+    List all valid options that are scheduled to become obsolete in a
+    future version. (This is a warning, not a promise.)
+
 [[opt-version]] **--version**::
     Display Tor version and exit.
 

+ 83 - 10
src/or/config.c

@@ -588,6 +588,44 @@ static const config_var_t testing_tor_network_defaults[] = {
 #undef V
 #undef OBSOLETE
 
+static const config_deprecation_t option_deprecation_notes_[] = {
+  { "AllowDotExit", "Unrestricted use of the .exit notation can be used for "
+    "a wide variety of application-level attacks." },
+  { "AllowInvalidNodes", "There is no reason to enable this option; at best "
+    "it will make you easier to track." },
+  { "AllowSingleHopCircuits", "Almost no relays actually allow single-hop "
+    "exits, making this option pointless." },
+  { "AllowSingleHopExits", "Turning this on will make your relay easier "
+    "to abuse." },
+  { "ClientDNSRejectInternalAddresses", "Turning this on makes your client "
+    "easier to fingerprint, and may open you to esoteric attacks." },
+  { "ExcludeSingleHopRelays", "Turning it on makes your client easier to "
+    "fingerprint." },
+  { "FastFirstHopPK", "Changing this option does not make your client more "
+    "secure, but does make it easier to fingerprint." },
+  { "CloseHSClientCircuitsImmediatelyOnTimeout", "This option makes your "
+    "client easier to fingerprint." },
+  { "CloseHSServiceRendCircuitsImmediatelyOnTimeout", "This option makes "
+    "your hidden services easier to fingerprint." },
+  { "WarnUnsafeSocks", "Changing this option makes it easier for you "
+    "to accidentally lose your anonymity by leaking DNS information" },
+  { "TLSECGroup", "The default is a nice secure choice; the other option "
+    "is less secure." },
+  { "UseNTorHandshake", "The ntor handshake should always be used." },
+
+  { "ControlListenAddress", "Use ControlPort instead." },
+  { "DirListenAddress", "Use DirPort instead, possibly with the "
+    "NoAdvertise sub-option" },
+  { "DNSListenAddress", "Use DNSPort instead." },
+  { "SocksListenAddress", "Use SocksPort instead." },
+  { "TransListenAddress", "Use TransPort instead." },
+  { "NATDListenAddress", "Use NATDPort instead." },
+  { "ORListenAddress", "Use ORPort instead, possibly with the "
+    "NoAdvertise sub-option" },
+
+  { NULL, NULL }
+};
+
 #ifdef _WIN32
 static char *get_windows_conf_root(void);
 #endif
@@ -636,6 +674,7 @@ STATIC config_format_t options_format = {
   OR_OPTIONS_MAGIC,
   STRUCT_OFFSET(or_options_t, magic_),
   option_abbrevs_,
+  option_deprecation_notes_,
   option_vars_,
   options_validate_cb,
   NULL
@@ -1999,6 +2038,7 @@ static const struct {
   { "-h",                     TAKES_NO_ARGUMENT },
   { "--help",                 TAKES_NO_ARGUMENT },
   { "--list-torrc-options",   TAKES_NO_ARGUMENT },
+  { "--list-deprecated-options",TAKES_NO_ARGUMENT },
   { "--nt-service",           TAKES_NO_ARGUMENT },
   { "-nt-service",            TAKES_NO_ARGUMENT },
   { NULL, 0 },
@@ -2135,14 +2175,13 @@ option_get_assignment(const or_options_t *options, const char *key)
  * what went wrong.
  */
 setopt_err_t
-options_trial_assign(config_line_t *list, int use_defaults,
-                     int clear_first, char **msg)
+options_trial_assign(config_line_t *list, unsigned flags, char **msg)
 {
   int r;
   or_options_t *trial_options = config_dup(&options_format, get_options());
 
   if ((r=config_assign(&options_format, trial_options,
-                       list, use_defaults, clear_first, msg)) < 0) {
+                       list, flags, msg)) < 0) {
     or_options_free(trial_options);
     return r;
   }
@@ -2185,7 +2224,6 @@ static void
 list_torrc_options(void)
 {
   int i;
-  smartlist_t *lines = smartlist_new();
   for (i = 0; option_vars_[i].name; ++i) {
     const config_var_t *var = &option_vars_[i];
     if (var->type == CONFIG_TYPE_OBSOLETE ||
@@ -2193,7 +2231,16 @@ list_torrc_options(void)
       continue;
     printf("%s\n", var->name);
   }
-  smartlist_free(lines);
+}
+
+/** Print all deprecated but non-obsolete torrc options. */
+static void
+list_deprecated_options(void)
+{
+  const config_deprecation_t *d;
+  for (d = option_deprecation_notes_; d->name; ++d) {
+    printf("%s\n", d->name);
+  }
 }
 
 /** Last value actually set by resolve_my_address. */
@@ -4647,10 +4694,15 @@ options_init_from_torrc(int argc, char **argv)
     exit(0);
   }
   if (config_line_find(cmdline_only_options, "--list-torrc-options")) {
-    /* For documenting validating whether we've documented everything. */
+    /* For validating whether we've documented everything. */
     list_torrc_options();
     exit(0);
   }
+  if (config_line_find(cmdline_only_options, "--list-deprecated-options")) {
+    /* For validating whether what we have deprecated really exists. */
+    list_deprecated_options();
+    exit(0);
+  }
 
   if (config_line_find(cmdline_only_options, "--version")) {
     printf("Tor version %s.\n",get_version());
@@ -4829,7 +4881,8 @@ options_init_from_string(const char *cf_defaults, const char *cf,
       err = SETOPT_ERR_PARSE;
       goto err;
     }
-    retval = config_assign(&options_format, newoptions, cl, 0, 0, msg);
+    retval = config_assign(&options_format, newoptions, cl,
+                           CAL_WARN_DEPRECATIONS, msg);
     config_free_lines(cl);
     if (retval < 0) {
       err = SETOPT_ERR_PARSE;
@@ -4845,7 +4898,7 @@ options_init_from_string(const char *cf_defaults, const char *cf,
 
   /* Go through command-line variables too */
   retval = config_assign(&options_format, newoptions,
-                         global_cmdline_options, 0, 0, msg);
+                         global_cmdline_options, CAL_WARN_DEPRECATIONS, msg);
   if (retval < 0) {
     err = SETOPT_ERR_PARSE;
     goto err;
@@ -4893,7 +4946,7 @@ options_init_from_string(const char *cf_defaults, const char *cf,
         err = SETOPT_ERR_PARSE;
         goto err;
       }
-      retval = config_assign(&options_format, newoptions, cl, 0, 0, msg);
+      retval = config_assign(&options_format, newoptions, cl, 0, msg);
       config_free_lines(cl);
       if (retval < 0) {
         err = SETOPT_ERR_PARSE;
@@ -4904,7 +4957,7 @@ options_init_from_string(const char *cf_defaults, const char *cf,
     }
     /* Assign command-line variables a second time too */
     retval = config_assign(&options_format, newoptions,
-                           global_cmdline_options, 0, 0, msg);
+                           global_cmdline_options, 0, msg);
     if (retval < 0) {
       err = SETOPT_ERR_PARSE;
       goto err;
@@ -6116,6 +6169,20 @@ config_parse_unix_port(const char *addrport, char **path_out)
 }
 #endif /* defined(HAVE_SYS_UN_H) */
 
+static void
+warn_client_dns_cache(const char *option, int disabling)
+{
+  if (disabling)
+    return;
+
+  warn_deprecated_option(option,
+      "Client-side DNS cacheing enables a wide variety of route-"
+      "capture attacks. If a single bad exit node lies to you about "
+      "an IP address, cacheing that address would make you visit "
+      "an address of the attacker's choice every time you connected "
+      "to your destination.");
+}
+
 /**
  * Parse port configuration for a single port type.
  *
@@ -6484,21 +6551,27 @@ parse_port_config(smartlist_t *out,
           }
         }
         if (!strcasecmp(elt, "CacheIPv4DNS")) {
+          warn_client_dns_cache(elt, no);
           cache_ipv4 = ! no;
           continue;
         } else if (!strcasecmp(elt, "CacheIPv6DNS")) {
+          warn_client_dns_cache(elt, no);
           cache_ipv6 = ! no;
           continue;
         } else if (!strcasecmp(elt, "CacheDNS")) {
+          warn_client_dns_cache(elt, no);
           cache_ipv4 = cache_ipv6 = ! no;
           continue;
         } else if (!strcasecmp(elt, "UseIPv4Cache")) {
+          warn_client_dns_cache(elt, no);
           use_cached_ipv4 = ! no;
           continue;
         } else if (!strcasecmp(elt, "UseIPv6Cache")) {
+          warn_client_dns_cache(elt, no);
           use_cached_ipv6 = ! no;
           continue;
         } else if (!strcasecmp(elt, "UseDNSCache")) {
+          warn_client_dns_cache(elt, no);
           use_cached_ipv4 = use_cached_ipv6 = ! no;
           continue;
         } else if (!strcasecmp(elt, "PreferIPv6Automap")) {

+ 2 - 2
src/or/config.h

@@ -29,8 +29,8 @@ const char *escaped_safe_str_client(const char *address);
 const char *escaped_safe_str(const char *address);
 const char *get_version(void);
 const char *get_short_version(void);
-setopt_err_t options_trial_assign(config_line_t *list, int use_defaults,
-                                  int clear_first, char **msg);
+setopt_err_t options_trial_assign(config_line_t *list, unsigned flags,
+                                  char **msg);
 
 uint32_t get_last_resolved_addr(void);
 void reset_last_resolved_addr(void);

+ 48 - 7
src/or/confparse.c

@@ -181,6 +181,26 @@ config_free_lines(config_line_t *front)
   }
 }
 
+/** If <b>key</b> is a deprecated configuration option, return the message
+ * explaining why it is deprecated (which may be an empty string). Return NULL
+ * if it is not deprecated. The <b>key</b> field must be fully expanded. */
+static const char *
+config_find_deprecation(const config_format_t *fmt, const char *key)
+{
+  if (BUG(fmt == NULL) || BUG(key == NULL))
+    return NULL;
+  if (fmt->deprecations == NULL)
+    return NULL;
+
+  const config_deprecation_t *d;
+  for (d = fmt->deprecations; d->name; ++d) {
+    if (!strcasecmp(d->name, key)) {
+      return d->why_deprecated ? d->why_deprecated : "";
+    }
+  }
+  return NULL;
+}
+
 /** As config_find_option, but return a non-const pointer. */
 config_var_t *
 config_find_option_mutable(config_format_t *fmt, const char *key)
@@ -463,6 +483,16 @@ config_mark_lists_fragile(const config_format_t *fmt, void *options)
   }
 }
 
+void
+warn_deprecated_option(const char *what, const char *why)
+{
+  const char *space = (why && strlen(why)) ? " " : "";
+  log_warn(LD_CONFIG, "The %s option is deprecated, and will most likely "
+           "be removed in a future version of Tor.%s%s (If you think this is "
+           "a mistake, please let us know!)",
+           what, space, why);
+}
+
 /** If <b>c</b> is a syntactically valid configuration line, update
  * <b>options</b> with its value and return 0.  Otherwise return -1 for bad
  * key, -2 for bad value.
@@ -474,9 +504,12 @@ config_mark_lists_fragile(const config_format_t *fmt, void *options)
  */
 static int
 config_assign_line(const config_format_t *fmt, void *options,
-                   config_line_t *c, int use_defaults,
-                   int clear_first, bitarray_t *options_seen, char **msg)
+                   config_line_t *c, unsigned flags,
+                   bitarray_t *options_seen, char **msg)
 {
+  const unsigned use_defaults = flags & CAL_USE_DEFAULTS;
+  const unsigned clear_first = flags & CAL_CLEAR_FIRST;
+  const unsigned warn_deprecations = flags & CAL_WARN_DEPRECATIONS;
   const config_var_t *var;
 
   CONFIG_CHECK(fmt, options);
@@ -502,6 +535,12 @@ config_assign_line(const config_format_t *fmt, void *options,
     c->key = tor_strdup(var->name);
   }
 
+  const char *deprecation_msg;
+  if (warn_deprecations &&
+      (deprecation_msg = config_find_deprecation(fmt, var->name))) {
+    warn_deprecated_option(var->name, deprecation_msg);
+  }
+
   if (!strlen(c->value)) {
     /* reset or clear it, then return */
     if (!clear_first) {
@@ -604,7 +643,7 @@ config_lines_dup(const config_line_t *inp)
  * escape that value. Return NULL if no such key exists. */
 config_line_t *
 config_get_assigned_option(const config_format_t *fmt, const void *options,
-                             const char *key, int escape_val)
+                           const char *key, int escape_val)
 {
   const config_var_t *var;
   const void *value;
@@ -804,11 +843,13 @@ options_trial_assign() calls config_assign(1, 1)
 */
 int
 config_assign(const config_format_t *fmt, void *options, config_line_t *list,
-              int use_defaults, int clear_first, char **msg)
+              unsigned config_assign_flags, char **msg)
 {
   config_line_t *p;
   bitarray_t *options_seen;
   const int n_options = config_count_options(fmt);
+  const unsigned clear_first = config_assign_flags & CAL_CLEAR_FIRST;
+  const unsigned use_defaults = config_assign_flags & CAL_USE_DEFAULTS;
 
   CONFIG_CHECK(fmt, options);
 
@@ -832,8 +873,8 @@ config_assign(const config_format_t *fmt, void *options, config_line_t *list,
   /* pass 3: assign. */
   while (list) {
     int r;
-    if ((r=config_assign_line(fmt, options, list, use_defaults,
-                              clear_first, options_seen, msg))) {
+    if ((r=config_assign_line(fmt, options, list, config_assign_flags,
+                              options_seen, msg))) {
       bitarray_free(options_seen);
       return r;
     }
@@ -1029,7 +1070,7 @@ config_dup(const config_format_t *fmt, const void *old)
     line = config_get_assigned_option(fmt, old, fmt->vars[i].name, 0);
     if (line) {
       char *msg = NULL;
-      if (config_assign(fmt, newopts, line, 0, 0, &msg) < 0) {
+      if (config_assign(fmt, newopts, line, 0, &msg) < 0) {
         log_err(LD_BUG, "config_get_assigned_option() generated "
                 "something we couldn't config_assign(): %s", msg);
         tor_free(msg);

+ 12 - 1
src/or/confparse.h

@@ -48,6 +48,11 @@ typedef struct config_abbrev_t {
   int warn;
 } config_abbrev_t;
 
+typedef struct config_deprecation_t {
+  const char *name;
+  const char *why_deprecated;
+} config_deprecation_t;
+
 /* Handy macro for declaring "In the config file or on the command line,
  * you can abbreviate <b>tok</b>s as <b>tok</b>". */
 #define PLURAL(tok) { #tok, #tok "s", 0, 0 }
@@ -76,6 +81,7 @@ typedef struct config_format_t {
   off_t magic_offset; /**< Offset of the magic value within the struct. */
   config_abbrev_t *abbrevs; /**< List of abbreviations that we expand when
                              * parsing this format. */
+  const config_deprecation_t *deprecations; /** List of deprecated options */
   config_var_t *vars; /**< List of variables we recognize, their default
                        * values, and where we stick them in the structure. */
   validate_fn_t validate_fn; /**< Function to validate config. */
@@ -92,6 +98,10 @@ typedef struct config_format_t {
                *(uint32_t*)STRUCT_VAR_P(cfg,fmt->magic_offset));        \
   STMT_END
 
+#define CAL_USE_DEFAULTS      (1u<<0)
+#define CAL_CLEAR_FIRST       (1u<<1)
+#define CAL_WARN_DEPRECATIONS (1u<<2)
+
 void *config_new(const config_format_t *fmt);
 void config_line_append(config_line_t **lst,
                         const char *key, const char *val);
@@ -114,7 +124,7 @@ char *config_dump(const config_format_t *fmt, const void *default_options,
                   int comment_defaults);
 int config_assign(const config_format_t *fmt, void *options,
                   config_line_t *list,
-                  int use_defaults, int clear_first, char **msg);
+                  unsigned flags, char **msg);
 config_var_t *config_find_option_mutable(config_format_t *fmt,
                                          const char *key);
 const config_var_t *config_find_option(const config_format_t *fmt,
@@ -125,6 +135,7 @@ void config_free_lines(config_line_t *front);
 const char *config_expand_abbrev(const config_format_t *fmt,
                                  const char *option,
                                  int command_line, int warn_obsolete);
+void warn_deprecated_option(const char *what, const char *why);
 
 #endif
 

+ 3 - 2
src/or/control.c

@@ -871,7 +871,8 @@ control_setconf_helper(control_connection_t *conn, uint32_t len, char *body,
   config_line_t *lines=NULL;
   char *start = body;
   char *errstring = NULL;
-  const int clear_first = 1;
+  const unsigned flags =
+    CAL_CLEAR_FIRST | (use_defaults ? CAL_USE_DEFAULTS : 0);
 
   char *config;
   smartlist_t *entries = smartlist_new();
@@ -931,7 +932,7 @@ control_setconf_helper(control_connection_t *conn, uint32_t len, char *body,
   }
   tor_free(config);
 
-  opt_err = options_trial_assign(lines, use_defaults, clear_first, &errstring);
+  opt_err = options_trial_assign(lines, flags, &errstring);
   {
     const char *msg;
     switch (opt_err) {

+ 2 - 1
src/or/shared_random_state.c

@@ -86,6 +86,7 @@ static const config_format_t state_format = {
   SR_DISK_STATE_MAGIC,
   STRUCT_OFFSET(sr_disk_state_t, magic_),
   NULL,
+  NULL,
   state_vars,
   disk_state_validate_cb,
   &state_extra_var,
@@ -700,7 +701,7 @@ disk_state_load_from_disk_impl(const char *fname)
     }
 
     disk_state = disk_state_new(time(NULL));
-    config_assign(&state_format, disk_state, lines, 0, 0, &errmsg);
+    config_assign(&state_format, disk_state, lines, 0, &errmsg);
     config_free_lines(lines);
     if (errmsg) {
       log_warn(LD_DIR, "SR: Reading state error: %s", errmsg);

+ 2 - 1
src/or/statefile.c

@@ -121,6 +121,7 @@ static const config_format_t state_format = {
   OR_STATE_MAGIC,
   STRUCT_OFFSET(or_state_t, magic_),
   state_abbrevs_,
+  NULL,
   state_vars_,
   or_state_validate_cb,
   &state_extra_var,
@@ -349,7 +350,7 @@ or_state_load(void)
     if (config_get_lines(contents, &lines, 0)<0)
       goto done;
     assign_retval = config_assign(&state_format, new_state,
-                                  lines, 0, 0, &errmsg);
+                                  lines, 0, &errmsg);
     config_free_lines(lines);
     if (assign_retval<0)
       badstate = 1;

+ 6 - 6
src/test/test_options.c

@@ -121,7 +121,7 @@ test_options_validate_impl(const char *configuration,
   r = config_get_lines(configuration, &cl, 1);
   tt_int_op(r, OP_EQ, 0);
 
-  r = config_assign(&options_format, opt, cl, 0, 0, &msg);
+  r = config_assign(&options_format, opt, cl, 0, &msg);
   tt_int_op(r, OP_EQ, 0);
 
   r = options_validate(NULL, opt, dflt, 0, &msg);
@@ -223,7 +223,7 @@ test_have_enough_mem_for_dircache(void *arg)
   r = config_get_lines(configuration, &cl, 1);
   tt_int_op(r, OP_EQ, 0);
 
-  r = config_assign(&options_format, opt, cl, 0, 0, &msg);
+  r = config_assign(&options_format, opt, cl, 0, &msg);
   tt_int_op(r, OP_EQ, 0);
 
   /* 300 MB RAM available, DirCache enabled */
@@ -246,7 +246,7 @@ test_have_enough_mem_for_dircache(void *arg)
   r = config_get_lines(configuration, &cl, 1);
   tt_int_op(r, OP_EQ, 0);
 
-  r = config_assign(&options_format, opt, cl, 0, 0, &msg);
+  r = config_assign(&options_format, opt, cl, 0, &msg);
   tt_int_op(r, OP_EQ, 0);
 
   /* 300 MB RAM available, DirCache enabled, Bridge */
@@ -269,7 +269,7 @@ test_have_enough_mem_for_dircache(void *arg)
   r = config_get_lines(configuration, &cl, 1);
   tt_int_op(r, OP_EQ, 0);
 
-  r = config_assign(&options_format, opt, cl, 0, 0, &msg);
+  r = config_assign(&options_format, opt, cl, 0, &msg);
   tt_int_op(r, OP_EQ, 0);
 
   /* 200 MB RAM available, DirCache disabled */
@@ -354,7 +354,7 @@ get_options_test_data(const char *conf)
   result->def_opt = options_new();
   rv = config_get_lines(conf, &cl, 1);
   tt_assert(rv == 0);
-  rv = config_assign(&options_format, result->opt, cl, 0, 0, &msg);
+  rv = config_assign(&options_format, result->opt, cl, 0, &msg);
   if (msg) {
     /* Display the parse error message by comparing it with an empty string */
     tt_str_op(msg, OP_EQ, "");
@@ -365,7 +365,7 @@ get_options_test_data(const char *conf)
   result->opt->TokenBucketRefillInterval = 1;
   rv = config_get_lines(TEST_OPTIONS_OLD_VALUES, &cl, 1);
   tt_assert(rv == 0);
-  rv = config_assign(&options_format, result->def_opt, cl, 0, 0, &msg);
+  rv = config_assign(&options_format, result->def_opt, cl, 0, &msg);
   if (msg) {
     /* Display the parse error message by comparing it with an empty string */
     tt_str_op(msg, OP_EQ, "");