[tor-commits] [tor/release-0.3.2] Merge branch 'feature18329_029_squashed' into maint-0.3.2

nickm at torproject.org nickm at torproject.org
Tue Oct 24 23:37:21 UTC 2017


commit 594cf92498c8ea12dc0b19f743d6b88d4a98f1eb
Merge: 122a7f884 02cde0d93
Author: Nick Mathewson <nickm at torproject.org>
Date:   Tue Oct 24 19:35:28 2017 -0400

    Merge branch 'feature18329_029_squashed' into maint-0.3.2

 changes/feature18329   |   9 ++++
 doc/tor.1.txt          |  11 +++++
 src/or/config.c        |  62 +++++++++++++++++++++++++++-
 src/or/config.h        |   2 +
 src/or/or.h            |   4 ++
 src/or/router.c        |  12 ++++++
 src/test/include.am    |   1 +
 src/test/test.c        |   1 +
 src/test/test_config.c |  63 ++++++++++++++++++++++++++++
 src/test/test_router.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++
 10 files changed, 273 insertions(+), 1 deletion(-)

diff --cc src/or/config.c
index a2353b94d,0b1e6bed1..b123d4935
--- a/src/or/config.c
+++ b/src/or/config.c
@@@ -253,15 -182,14 +253,16 @@@ static config_var_t option_vars_[] = 
    V(BridgePassword,              STRING,   NULL),
    V(BridgeRecordUsageByCountry,  BOOL,     "1"),
    V(BridgeRelay,                 BOOL,     "0"),
+   V(BridgeDistribution,          STRING,   NULL),
    V(CellStatistics,              BOOL,     "0"),
 +  V(PaddingStatistics,           BOOL,     "1"),
    V(LearnCircuitBuildTimeout,    BOOL,     "1"),
    V(CircuitBuildTimeout,         INTERVAL, "0"),
 -  V(CircuitIdleTimeout,          INTERVAL, "1 hour"),
 +  OBSOLETE("CircuitIdleTimeout"),
 +  V(CircuitsAvailableTimeout,    INTERVAL, "0"),
    V(CircuitStreamTimeout,        INTERVAL, "0"),
    V(CircuitPriorityHalflife,     DOUBLE,  "-100.0"), /*negative:'Use default'*/
 -  V(ClientDNSRejectInternalAddresses, BOOL,"1"),
 +  V(TestingClientDNSRejectInternalAddresses, BOOL,"1"),
    V(ClientOnly,                  BOOL,     "0"),
    V(ClientPreferIPv6ORPort,      AUTOBOOL, "auto"),
    V(ClientPreferIPv6DirPort,     AUTOBOOL, "auto"),
@@@ -3504,14 -3346,16 +3504,23 @@@ options_validate(or_options_t *old_opti
      options->DirPort_set = 0;
    }
  
 +  if (server_mode(options) && options->ConnectionPadding != -1) {
 +    REJECT("Relays must use 'auto' for the ConnectionPadding setting.");
 +  }
 +
 +  if (server_mode(options) && options->ReducedConnectionPadding != 0) {
 +    REJECT("Relays cannot set ReducedConnectionPadding. ");
 +  }
 +
+   if (options->BridgeDistribution) {
+     if (!options->BridgeRelay) {
+       REJECT("You set BridgeDistribution, but you didn't set BridgeRelay!");
+     }
+     if (check_bridge_distribution_setting(options->BridgeDistribution) < 0) {
+       REJECT("Invalid BridgeDistribution value.");
+     }
+   }
+ 
 -
    if (options->MinUptimeHidServDirectoryV2 < 0) {
      log_warn(LD_CONFIG, "MinUptimeHidServDirectoryV2 option must be at "
                          "least 0 seconds. Changing to 0.");
@@@ -4686,7 -4507,9 +4695,9 @@@ options_transition_affects_descriptor(c
        get_effective_bwburst(old_options) !=
          get_effective_bwburst(new_options) ||
        !opt_streq(old_options->ContactInfo, new_options->ContactInfo) ||
+       !opt_streq(old_options->BridgeDistribution,
+                  new_options->BridgeDistribution) ||
 -      !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) ||
        old_options->AccountingMax != new_options->AccountingMax ||
        old_options->AccountingRule != new_options->AccountingRule ||
@@@ -6584,11 -6350,65 +6595,60 @@@ warn_client_dns_cache(const char *optio
  }
  
  /**
+  * Validate the configured bridge distribution method from a BridgeDistribution
+  * config line.
+  *
+  * The input <b>bd</b>, is a string taken from the BridgeDistribution config
+  * line (if present).  If the option wasn't set, return 0 immediately.  The
+  * BridgeDistribution option is then validated.  Currently valid, recognised
+  * options are:
+  *
+  * - "none"
+  * - "any"
+  * - "https"
+  * - "email"
+  * - "moat"
+  * - "hyphae"
+  *
+  * If the option string is unrecognised, a warning will be logged and 0 is
+  * returned.  If the option string contains an invalid character, -1 is
+  * returned.
+  **/
+ STATIC int
+ check_bridge_distribution_setting(const char *bd)
+ {
+   if (bd == NULL)
+     return 0;
+ 
+   const char *RECOGNIZED[] = {
+     "none", "any", "https", "email", "moat", "hyphae"
+   };
+   unsigned i;
+   for (i = 0; i < ARRAY_LENGTH(RECOGNIZED); ++i) {
+     if (!strcmp(bd, RECOGNIZED[i]))
+       return 0;
+   }
+ 
+   const char *cp = bd;
+   //  Method = (KeywordChar | "_") +
+   while (TOR_ISALNUM(*cp) || *cp == '-' || *cp == '_')
+     ++cp;
+ 
+   if (*cp == 0) {
+     log_warn(LD_CONFIG, "Unrecognized BridgeDistribution value %s. I'll "
+            "assume you know what you are doing...", escaped(bd));
+     return 0; // we reached the end of the string; all is well
+   } else {
+     return -1; // we found a bad character in the string.
+   }
+ }
+ 
+ /**
   * Parse port configuration for a single port type.
   *
 - * Read entries of the "FooPort" type from the list <b>ports</b>, and
 - * entries of the "FooListenAddress" type from the list
 - * <b>listenaddrs</b>.  Two syntaxes are supported: a legacy syntax
 - * where FooPort is at most a single entry containing a port number and
 - * where FooListenAddress has any number of address:port combinations;
 - * and a new syntax where there are no FooListenAddress entries and
 - * where FooPort can have any number of entries of the format
 - * "[Address:][Port] IsolationOptions".
 + * Read entries of the "FooPort" type from the list <b>ports</b>.  Syntax is
 + * that FooPort can have any number of entries of the format
 + *  "[Address:][Port] IsolationOptions".
   *
   * In log messages, describe the port type as <b>portname</b>.
   *
diff --cc src/or/config.h
index af945f16b,096937cb6..efdd8c59b
--- a/src/or/config.h
+++ b/src/or/config.h
@@@ -203,7 -199,8 +203,9 @@@ STATIC int parse_port_config(smartlist_
                    const char *defaultaddr,
                    int defaultport,
                    const unsigned flags);
++
+ STATIC int check_bridge_distribution_setting(const char *bd);
 -#endif
 +#endif /* defined(CONFIG_PRIVATE) */
  
 -#endif
 +#endif /* !defined(TOR_CONFIG_H) */
  
diff --cc src/test/test_config.c
index 58268705e,396f06adf..68eb5419c
--- a/src/test/test_config.c
+++ b/src/test/test_config.c
@@@ -4784,668 -4890,65 +4784,727 @@@ test_config_parse_port_config__ports__s
    config_free_lines(config_port_valid); config_port_valid = NULL;
  }
  
 +static void
 +test_config_parse_log_severity(void *data)
 +{
 +  int ret;
 +  const char *severity_log_lines[] = {
 +    "debug file /tmp/debug.log",
 +    "debug\tfile /tmp/debug.log",
 +    "[handshake]debug [~net,~mm]info notice stdout",
 +    "[handshake]debug\t[~net,~mm]info\tnotice\tstdout",
 +    NULL
 +  };
 +  int i;
 +  log_severity_list_t *severity;
 +
 +  (void) data;
 +
 +  severity = tor_malloc(sizeof(log_severity_list_t));
 +  for (i = 0; severity_log_lines[i]; i++) {
 +    memset(severity, 0, sizeof(log_severity_list_t));
 +    ret = parse_log_severity_config(&severity_log_lines[i], severity);
 +    tt_int_op(ret, OP_EQ, 0);
 +  }
 +
 + done:
 +  tor_free(severity);
 +}
 +
 +static void
 +test_config_include_limit(void *data)
 +{
 +  (void)data;
 +
 +  config_line_t *result = NULL;
 +  char *torrc_path = NULL;
 +  char *dir = tor_strdup(get_fname("test_include_limit"));
 +  tt_ptr_op(dir, OP_NE, NULL);
 +
 +#ifdef _WIN32
 +  tt_int_op(mkdir(dir), OP_EQ, 0);
 +#else
 +  tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
 +#endif
 +
 +  tor_asprintf(&torrc_path, "%s"PATH_SEPARATOR"torrc", dir);
 +  char torrc_contents[1000];
 +  tor_snprintf(torrc_contents, sizeof(torrc_contents), "%%include %s",
 +               torrc_path);
 +  tt_int_op(write_str_to_file(torrc_path, torrc_contents, 0), OP_EQ, 0);
 +
 +  tt_int_op(config_get_lines_include(torrc_contents, &result, 0, NULL),
 +            OP_EQ, -1);
 +
 + done:
 +  config_free_lines(result);
 +  tor_free(torrc_path);
 +  tor_free(dir);
 +}
 +
 +static void
 +test_config_include_does_not_exist(void *data)
 +{
 +  (void)data;
 +
 +  config_line_t *result = NULL;
 +  char *dir = tor_strdup(get_fname("test_include_does_not_exist"));
 +  char *missing_path = NULL;
 +  tt_ptr_op(dir, OP_NE, NULL);
 +
 +#ifdef _WIN32
 +  tt_int_op(mkdir(dir), OP_EQ, 0);
 +#else
 +  tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
 +#endif
 +
 +  tor_asprintf(&missing_path, "%s"PATH_SEPARATOR"missing", dir);
 +  char torrc_contents[1000];
 +  tor_snprintf(torrc_contents, sizeof(torrc_contents), "%%include %s",
 +               missing_path);
 +
 +  tt_int_op(config_get_lines_include(torrc_contents, &result, 0, NULL),
 +            OP_EQ, -1);
 +
 + done:
 +  config_free_lines(result);
 +  tor_free(dir);
 +  tor_free(missing_path);
 +}
 +
 +static void
 +test_config_include_error_in_included_file(void *data)
 +{
 +  (void)data;
 +  config_line_t *result = NULL;
 +
 +  char *dir = tor_strdup(get_fname("test_error_in_included_file"));
 +  char *invalid_path = NULL;
 +  tt_ptr_op(dir, OP_NE, NULL);
 +
 +#ifdef _WIN32
 +  tt_int_op(mkdir(dir), OP_EQ, 0);
 +#else
 +  tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
 +#endif
 +
 +  tor_asprintf(&invalid_path, "%s"PATH_SEPARATOR"invalid", dir);
 +  tt_int_op(write_str_to_file(invalid_path, "unclosed \"", 0), OP_EQ, 0);
 +
 +  char torrc_contents[1000];
 +  tor_snprintf(torrc_contents, sizeof(torrc_contents), "%%include %s",
 +               invalid_path);
 +
 +  tt_int_op(config_get_lines_include(torrc_contents, &result, 0, NULL),
 +            OP_EQ, -1);
 +
 + done:
 +  config_free_lines(result);
 +  tor_free(dir);
 +  tor_free(invalid_path);
 +}
 +
 +static void
 +test_config_include_empty_file_folder(void *data)
 +{
 +  (void)data;
 +  config_line_t *result = NULL;
 +
 +  char *folder_path = NULL;
 +  char *file_path = NULL;
 +  char *dir = tor_strdup(get_fname("test_include_empty_file_folder"));
 +  tt_ptr_op(dir, OP_NE, NULL);
 +
 +#ifdef _WIN32
 +  tt_int_op(mkdir(dir), OP_EQ, 0);
 +#else
 +  tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
 +#endif
 +
 +  tor_asprintf(&folder_path, "%s"PATH_SEPARATOR"empty_dir", dir);
 +#ifdef _WIN32
 +  tt_int_op(mkdir(folder_path), OP_EQ, 0);
 +#else
 +  tt_int_op(mkdir(folder_path, 0700), OP_EQ, 0);
 +#endif
 +  tor_asprintf(&file_path, "%s"PATH_SEPARATOR"empty_file", dir);
 +  tt_int_op(write_str_to_file(file_path, "", 0), OP_EQ, 0);
 +
 +  char torrc_contents[1000];
 +  tor_snprintf(torrc_contents, sizeof(torrc_contents),
 +               "%%include %s\n"
 +               "%%include %s\n",
 +               folder_path, file_path);
 +
 +  int include_used;
 +  tt_int_op(config_get_lines_include(torrc_contents, &result, 0,&include_used),
 +            OP_EQ, 0);
 +  tt_ptr_op(result, OP_EQ, NULL);
 +  tt_int_op(include_used, OP_EQ, 1);
 +
 + done:
 +  config_free_lines(result);
 +  tor_free(folder_path);
 +  tor_free(file_path);
 +  tor_free(dir);
 +}
 +
 +#ifndef _WIN32
 +static void
 +test_config_include_no_permission(void *data)
 +{
 +  (void)data;
 +  config_line_t *result = NULL;
 +
 +  char *folder_path = NULL;
 +  char *dir = NULL;
 +  if (geteuid() == 0)
 +    tt_skip();
 +
 +  dir = tor_strdup(get_fname("test_include_forbidden_folder"));
 +  tt_ptr_op(dir, OP_NE, NULL);
 +
 +  tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
 +
 +  tor_asprintf(&folder_path, "%s"PATH_SEPARATOR"forbidden_dir", dir);
 +  tt_int_op(mkdir(folder_path, 0100), OP_EQ, 0);
 +
 +  char torrc_contents[1000];
 +  tor_snprintf(torrc_contents, sizeof(torrc_contents),
 +               "%%include %s\n",
 +               folder_path);
 +
 +  int include_used;
 +  tt_int_op(config_get_lines_include(torrc_contents, &result, 0,&include_used),
 +            OP_EQ, -1);
 +  tt_ptr_op(result, OP_EQ, NULL);
 +
 + done:
 +  config_free_lines(result);
 +  tor_free(folder_path);
 +  if (dir)
 +    chmod(dir, 0700);
 +  tor_free(dir);
 +}
 +#endif
 +
 +static void
 +test_config_include_recursion_before_after(void *data)
 +{
 +  (void)data;
 +
 +  config_line_t *result = NULL;
 +  char *torrc_path = NULL;
 +  char *dir = tor_strdup(get_fname("test_include_recursion_before_after"));
 +  tt_ptr_op(dir, OP_NE, NULL);
 +
 +#ifdef _WIN32
 +  tt_int_op(mkdir(dir), OP_EQ, 0);
 +#else
 +  tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
 +#endif
 +
 +  tor_asprintf(&torrc_path, "%s"PATH_SEPARATOR"torrc", dir);
 +
 +  char file_contents[1000];
 +  const int limit = MAX_INCLUDE_RECURSION_LEVEL;
 +  int i;
 +  // Loop backwards so file_contents has the contents of the first file by the
 +  // end of the loop
 +  for (i = limit; i > 0; i--) {
 +    if (i < limit) {
 +      tor_snprintf(file_contents, sizeof(file_contents),
 +                   "Test %d\n"
 +                   "%%include %s%d\n"
 +                   "Test %d\n",
 +                   i, torrc_path, i + 1, 2 * limit - i);
 +    } else {
 +      tor_snprintf(file_contents, sizeof(file_contents), "Test %d\n", i);
 +    }
 +
 +    if (i > 1) {
 +      char *file_path = NULL;
 +      tor_asprintf(&file_path, "%s%d", torrc_path, i);
 +      tt_int_op(write_str_to_file(file_path, file_contents, 0), OP_EQ, 0);
 +      tor_free(file_path);
 +    }
 +  }
 +
 +  int include_used;
 +  tt_int_op(config_get_lines_include(file_contents, &result, 0, &include_used),
 +            OP_EQ, 0);
 +  tt_ptr_op(result, OP_NE, NULL);
 +  tt_int_op(include_used, OP_EQ, 1);
 +
 +  int len = 0;
 +  config_line_t *next;
 +  for (next = result; next != NULL; next = next->next) {
 +    char expected[10];
 +    tor_snprintf(expected, sizeof(expected), "%d", len + 1);
 +    tt_str_op(next->key, OP_EQ, "Test");
 +    tt_str_op(next->value, OP_EQ, expected);
 +    len++;
 +  }
 +  tt_int_op(len, OP_EQ, 2 * limit - 1);
 +
 + done:
 +  config_free_lines(result);
 +  tor_free(dir);
 +  tor_free(torrc_path);
 +}
 +
 +static void
 +test_config_include_recursion_after_only(void *data)
 +{
 +  (void)data;
 +
 +  config_line_t *result = NULL;
 +  char *torrc_path = NULL;
 +  char *dir = tor_strdup(get_fname("test_include_recursion_after_only"));
 +  tt_ptr_op(dir, OP_NE, NULL);
 +
 +#ifdef _WIN32
 +  tt_int_op(mkdir(dir), OP_EQ, 0);
 +#else
 +  tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
 +#endif
 +
 +  tor_asprintf(&torrc_path, "%s"PATH_SEPARATOR"torrc", dir);
 +
 +  char file_contents[1000];
 +  const int limit = MAX_INCLUDE_RECURSION_LEVEL;
 +  int i;
 +  // Loop backwards so file_contents has the contents of the first file by the
 +  // end of the loop
 +  for (i = limit; i > 0; i--) {
 +    int n = (i - limit - 1) * -1;
 +    if (i < limit) {
 +      tor_snprintf(file_contents, sizeof(file_contents),
 +                   "%%include %s%d\n"
 +                   "Test %d\n",
 +                   torrc_path, i + 1, n);
 +    } else {
 +      tor_snprintf(file_contents, sizeof(file_contents), "Test %d\n", n);
 +    }
 +
 +    if (i > 1) {
 +      char *file_path = NULL;
 +      tor_asprintf(&file_path, "%s%d", torrc_path, i);
 +      tt_int_op(write_str_to_file(file_path, file_contents, 0), OP_EQ, 0);
 +      tor_free(file_path);
 +    }
 +  }
 +
 +  int include_used;
 +  tt_int_op(config_get_lines_include(file_contents, &result, 0, &include_used),
 +            OP_EQ, 0);
 +  tt_ptr_op(result, OP_NE, NULL);
 +  tt_int_op(include_used, OP_EQ, 1);
 +
 +  int len = 0;
 +  config_line_t *next;
 +  for (next = result; next != NULL; next = next->next) {
 +    char expected[10];
 +    tor_snprintf(expected, sizeof(expected), "%d", len + 1);
 +    tt_str_op(next->key, OP_EQ, "Test");
 +    tt_str_op(next->value, OP_EQ, expected);
 +    len++;
 +  }
 +  tt_int_op(len, OP_EQ, limit);
 +
 + done:
 +  config_free_lines(result);
 +  tor_free(dir);
 +  tor_free(torrc_path);
 +}
 +
 +static void
 +test_config_include_folder_order(void *data)
 +{
 +  (void)data;
 +
 +  config_line_t *result = NULL;
 +  char *torrcd = NULL;
 +  char *path = NULL;
 +  char *path2 = NULL;
 +  char *dir = tor_strdup(get_fname("test_include_folder_order"));
 +  tt_ptr_op(dir, OP_NE, NULL);
 +
 +#ifdef _WIN32
 +  tt_int_op(mkdir(dir), OP_EQ, 0);
 +#else
 +  tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
 +#endif
 +
 +  tor_asprintf(&torrcd, "%s"PATH_SEPARATOR"%s", dir, "torrc.d");
 +
 +#ifdef _WIN32
 +  tt_int_op(mkdir(torrcd), OP_EQ, 0);
 +#else
 +  tt_int_op(mkdir(torrcd, 0700), OP_EQ, 0);
 +#endif
 +
 +  // test that files in subfolders are ignored
 +  tor_asprintf(&path, "%s"PATH_SEPARATOR"%s", torrcd, "subfolder");
 +
 +#ifdef _WIN32
 +  tt_int_op(mkdir(path), OP_EQ, 0);
 +#else
 +  tt_int_op(mkdir(path, 0700), OP_EQ, 0);
 +#endif
 +
 +  tor_asprintf(&path2, "%s"PATH_SEPARATOR"%s", path, "01_ignore");
 +  tt_int_op(write_str_to_file(path2, "ShouldNotSee 1\n", 0), OP_EQ, 0);
 +  tor_free(path);
 +
 +  // test that files starting with . are ignored
 +  tor_asprintf(&path, "%s"PATH_SEPARATOR"%s", torrcd, ".dot");
 +  tt_int_op(write_str_to_file(path, "ShouldNotSee 2\n", 0), OP_EQ, 0);
 +  tor_free(path);
 +
 +  // test file order
 +  tor_asprintf(&path, "%s"PATH_SEPARATOR"%s", torrcd, "01_1st");
 +  tt_int_op(write_str_to_file(path, "Test 1\n", 0), OP_EQ, 0);
 +  tor_free(path);
 +
 +  tor_asprintf(&path, "%s"PATH_SEPARATOR"%s", torrcd, "02_2nd");
 +  tt_int_op(write_str_to_file(path, "Test 2\n", 0), OP_EQ, 0);
 +  tor_free(path);
 +
 +  tor_asprintf(&path, "%s"PATH_SEPARATOR"%s", torrcd, "aa_3rd");
 +  tt_int_op(write_str_to_file(path, "Test 3\n", 0), OP_EQ, 0);
 +  tor_free(path);
 +
 +  tor_asprintf(&path, "%s"PATH_SEPARATOR"%s", torrcd, "ab_4th");
 +  tt_int_op(write_str_to_file(path, "Test 4\n", 0), OP_EQ, 0);
 +  tor_free(path);
 +
 +  char torrc_contents[1000];
 +  tor_snprintf(torrc_contents, sizeof(torrc_contents),
 +               "%%include %s\n",
 +               torrcd);
 +
 +  int include_used;
 +  tt_int_op(config_get_lines_include(torrc_contents, &result, 0,&include_used),
 +            OP_EQ, 0);
 +  tt_ptr_op(result, OP_NE, NULL);
 +  tt_int_op(include_used, OP_EQ, 1);
 +
 +  int len = 0;
 +  config_line_t *next;
 +  for (next = result; next != NULL; next = next->next) {
 +    char expected[10];
 +    tor_snprintf(expected, sizeof(expected), "%d", len + 1);
 +    tt_str_op(next->key, OP_EQ, "Test");
 +    tt_str_op(next->value, OP_EQ, expected);
 +    len++;
 +  }
 +  tt_int_op(len, OP_EQ, 4);
 +
 + done:
 +  config_free_lines(result);
 +  tor_free(torrcd);
 +  tor_free(path);
 +  tor_free(path2);
 +  tor_free(dir);
 +}
 +
 +static void
 +test_config_include_path_syntax(void *data)
 +{
 +  (void)data;
 +
 +  config_line_t *result = NULL;
 +  char *dir = tor_strdup(get_fname("test_include_path_syntax"));
 +  char *esc_dir = NULL, *dir_with_pathsep = NULL,
 +    *esc_dir_with_pathsep = NULL, *torrc_contents = NULL;
 +  tt_ptr_op(dir, OP_NE, NULL);
 +
 +#ifdef _WIN32
 +  tt_int_op(mkdir(dir), OP_EQ, 0);
 +#else
 +  tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
 +#endif
 +
 +  esc_dir = esc_for_log(dir);
 +  tor_asprintf(&dir_with_pathsep, "%s%s", dir, PATH_SEPARATOR);
 +  esc_dir_with_pathsep = esc_for_log(dir_with_pathsep);
 +
 +  tor_asprintf(&torrc_contents,
 +               "%%include %s\n"
 +               "%%include %s%s \n" // space to avoid suppressing newline
 +               "%%include %s\n",
 +               esc_dir,
 +               dir, PATH_SEPARATOR,
 +               esc_dir_with_pathsep);
 +
 +  int include_used;
 +  tt_int_op(config_get_lines_include(torrc_contents, &result, 0,&include_used),
 +            OP_EQ, 0);
 +  tt_ptr_op(result, OP_EQ, NULL);
 +  tt_int_op(include_used, OP_EQ, 1);
 +
 + done:
 +  config_free_lines(result);
 +  tor_free(dir);
 +  tor_free(torrc_contents);
 +  tor_free(esc_dir);
 +  tor_free(dir_with_pathsep);
 +  tor_free(esc_dir_with_pathsep);
 +}
 +
 +static void
 +test_config_include_not_processed(void *data)
 +{
 +  (void)data;
 +
 +  char torrc_contents[1000] = "%include does_not_exist\n";
 +  config_line_t *result = NULL;
 +  tt_int_op(config_get_lines(torrc_contents, &result, 0),OP_EQ, 0);
 +  tt_ptr_op(result, OP_NE, NULL);
 +
 +  int len = 0;
 +  config_line_t *next;
 +  for (next = result; next != NULL; next = next->next) {
 +    tt_str_op(next->key, OP_EQ, "%include");
 +    tt_str_op(next->value, OP_EQ, "does_not_exist");
 +    len++;
 +  }
 +  tt_int_op(len, OP_EQ, 1);
 +
 + done:
 +  config_free_lines(result);
 +}
 +
 +static void
 +test_config_include_has_include(void *data)
 +{
 +  (void)data;
 +
 +  config_line_t *result = NULL;
 +  char *dir = tor_strdup(get_fname("test_include_has_include"));
 +  tt_ptr_op(dir, OP_NE, NULL);
 +
 +#ifdef _WIN32
 +  tt_int_op(mkdir(dir), OP_EQ, 0);
 +#else
 +  tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
 +#endif
 +
 +  char torrc_contents[1000] = "Test 1\n";
 +  int include_used;
 +
 +  tt_int_op(config_get_lines_include(torrc_contents, &result, 0,&include_used),
 +            OP_EQ, 0);
 +  tt_int_op(include_used, OP_EQ, 0);
 +  config_free_lines(result);
 +
 +  tor_snprintf(torrc_contents, sizeof(torrc_contents), "%%include %s\n", dir);
 +  tt_int_op(config_get_lines_include(torrc_contents, &result, 0,&include_used),
 +            OP_EQ, 0);
 +  tt_int_op(include_used, OP_EQ, 1);
 +
 + done:
 +  config_free_lines(result);
 +  tor_free(dir);
 +}
 +
 +static void
 +test_config_include_flag_both_without(void *data)
 +{
 +  (void)data;
 +
 +  char *errmsg = NULL;
 +  char conf_empty[1000];
 +  tor_snprintf(conf_empty, sizeof(conf_empty),
 +               "DataDirectory %s\n",
 +               get_fname(NULL));
 +  // test with defaults-torrc and torrc without include
 +  int ret = options_init_from_string(conf_empty, conf_empty, CMD_RUN_UNITTESTS,
 +                                     NULL, &errmsg);
 +  tt_int_op(ret, OP_EQ, 0);
 +
 +  const or_options_t *options = get_options();
 +  tt_int_op(options->IncludeUsed, OP_EQ, 0);
 +
 + done:
 +  tor_free(errmsg);
 +}
 +
 +static void
 +test_config_include_flag_torrc_only(void *data)
 +{
 +  (void)data;
 +
 +  char *errmsg = NULL;
 +  char *path = NULL;
 +  char *dir = tor_strdup(get_fname("test_include_flag_torrc_only"));
 +  tt_ptr_op(dir, OP_NE, NULL);
 +
 +#ifdef _WIN32
 +  tt_int_op(mkdir(dir), OP_EQ, 0);
 +#else
 +  tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
 +#endif
 +
 +  tor_asprintf(&path, "%s"PATH_SEPARATOR"%s", dir, "dummy");
 +  tt_int_op(write_str_to_file(path, "\n", 0), OP_EQ, 0);
 +
 +  char conf_empty[1000];
 +  tor_snprintf(conf_empty, sizeof(conf_empty),
 +               "DataDirectory %s\n",
 +               get_fname(NULL));
 +  char conf_include[1000];
 +  tor_snprintf(conf_include, sizeof(conf_include), "%%include %s", path);
 +
 +  // test with defaults-torrc without include and torrc with include
 +  int ret = options_init_from_string(conf_empty, conf_include,
 +                                     CMD_RUN_UNITTESTS, NULL, &errmsg);
 +  tt_int_op(ret, OP_EQ, 0);
 +
 +  const or_options_t *options = get_options();
 +  tt_int_op(options->IncludeUsed, OP_EQ, 1);
 +
 + done:
 +  tor_free(errmsg);
 +  tor_free(path);
 +  tor_free(dir);
 +}
 +
 +static void
 +test_config_include_flag_defaults_only(void *data)
 +{
 +  (void)data;
 +
 +  char *errmsg = NULL;
 +  char *path = NULL;
 +  char *dir = tor_strdup(get_fname("test_include_flag_defaults_only"));
 +  tt_ptr_op(dir, OP_NE, NULL);
 +
 +#ifdef _WIN32
 +  tt_int_op(mkdir(dir), OP_EQ, 0);
 +#else
 +  tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
 +#endif
 +
 +  tor_asprintf(&path, "%s"PATH_SEPARATOR"%s", dir, "dummy");
 +  tt_int_op(write_str_to_file(path, "\n", 0), OP_EQ, 0);
 +
 +  char conf_empty[1000];
 +  tor_snprintf(conf_empty, sizeof(conf_empty),
 +               "DataDirectory %s\n",
 +               get_fname(NULL));
 +  char conf_include[1000];
 +  tor_snprintf(conf_include, sizeof(conf_include), "%%include %s", path);
 +
 +  // test with defaults-torrc with include and torrc without include
 +  int ret = options_init_from_string(conf_include, conf_empty,
 +                                     CMD_RUN_UNITTESTS, NULL, &errmsg);
 +  tt_int_op(ret, OP_EQ, 0);
 +
 +  const or_options_t *options = get_options();
 +  tt_int_op(options->IncludeUsed, OP_EQ, 0);
 +
 + done:
 +  tor_free(errmsg);
 +  tor_free(path);
 +  tor_free(dir);
 +}
 +
 +static void
 +test_config_dup_and_filter(void *arg)
 +{
 +  (void)arg;
 +  /* Test normal input. */
 +  config_line_t *line = NULL;
 +  config_line_append(&line, "abc", "def");
 +  config_line_append(&line, "ghi", "jkl");
 +  config_line_append(&line, "ABCD", "mno");
 +
 +  config_line_t *line_dup = config_lines_dup_and_filter(line, "aBc");
 +  tt_ptr_op(line_dup, OP_NE, NULL);
 +  tt_ptr_op(line_dup->next, OP_NE, NULL);
 +  tt_ptr_op(line_dup->next->next, OP_EQ, NULL);
 +
 +  tt_str_op(line_dup->key, OP_EQ, "abc");
 +  tt_str_op(line_dup->value, OP_EQ, "def");
 +  tt_str_op(line_dup->next->key, OP_EQ, "ABCD");
 +  tt_str_op(line_dup->next->value, OP_EQ, "mno");
 +
 +  /* empty output */
 +  config_free_lines(line_dup);
 +  line_dup = config_lines_dup_and_filter(line, "skdjfsdkljf");
 +  tt_ptr_op(line_dup, OP_EQ, NULL);
 +
 +  /* empty input */
 +  config_free_lines(line_dup);
 +  line_dup = config_lines_dup_and_filter(NULL, "abc");
 +  tt_ptr_op(line_dup, OP_EQ, NULL);
 +
 + done:
 +  config_free_lines(line);
 +  config_free_lines(line_dup);
 +}
 +
+ /* If we're not configured to be a bridge, but we set
+  * BridgeDistribution, then options_validate () should return -1. */
+ static void
+ test_config_check_bridge_distribution_setting_not_a_bridge(void *arg) {
+   or_options_t* options = get_options_mutable();
+   or_options_t* old_options = options;
+   or_options_t* default_options = options;
+   char* message = (char*)("");
+   int ret;
+ 
+   (void)arg;
+ 
+   options->BridgeRelay = 0;
+   options->BridgeDistribution = (char*)("https");
+ 
+   ret = options_validate(old_options, options, default_options, 0, &message);
+ 
+   tt_int_op(ret, OP_EQ, -1);
+  done:
+   return;
+ }
+ 
+ /* If the BridgeDistribution setting was valid, 0 should be returned. */
+ static void
+ test_config_check_bridge_distribution_setting_valid(void *arg) {
+   int ret = check_bridge_distribution_setting("https");
+ 
+   (void)arg;
+ 
+   tt_int_op(ret, OP_EQ, 0);
+  done:
+   return;
+ }
+ 
+ /* If the BridgeDistribution setting was invalid, -1 should be returned. */
+ static void
+ test_config_check_bridge_distribution_setting_invalid(void *arg) {
+   int ret = check_bridge_distribution_setting("hyphens-are-not-allowed");
+ 
+   (void)arg;
+ 
+   tt_int_op(ret, OP_EQ, -1);
+  done:
+   return;
+ }
+ 
+ /* If the BridgeDistribution setting was unrecognised, a warning should be
+  * logged and 0 should be returned. */
+ static void
+ test_config_check_bridge_distribution_setting_unrecognised(void *arg) {
+   int ret = check_bridge_distribution_setting("unicorn");
+ 
+   (void)arg;
+ 
+   tt_int_op(ret, OP_EQ, 0);
+  done:
+   return;
+ }
+ 
  #define CONFIG_TEST(name, flags)                          \
    { #name, test_config_ ## name, flags, NULL, NULL }
  
@@@ -5471,24 -4974,11 +5530,28 @@@ struct testcase_t config_tests[] = 
    CONFIG_TEST(parse_port_config__ports__no_ports_given, 0),
    CONFIG_TEST(parse_port_config__ports__server_options, 0),
    CONFIG_TEST(parse_port_config__ports__ports_given, 0),
 +  CONFIG_TEST(parse_log_severity, 0),
 +  CONFIG_TEST(include_limit, 0),
 +  CONFIG_TEST(include_does_not_exist, 0),
 +  CONFIG_TEST(include_error_in_included_file, 0),
 +  CONFIG_TEST(include_empty_file_folder, 0),
 +#ifndef _WIN32
 +  CONFIG_TEST(include_no_permission, 0),
 +#endif
 +  CONFIG_TEST(include_recursion_before_after, 0),
 +  CONFIG_TEST(include_recursion_after_only, 0),
 +  CONFIG_TEST(include_folder_order, 0),
 +  CONFIG_TEST(include_path_syntax, 0),
 +  CONFIG_TEST(include_not_processed, 0),
 +  CONFIG_TEST(include_has_include, 0),
 +  CONFIG_TEST(include_flag_both_without, TT_FORK),
 +  CONFIG_TEST(include_flag_torrc_only, TT_FORK),
 +  CONFIG_TEST(include_flag_defaults_only, TT_FORK),
 +  CONFIG_TEST(dup_and_filter, 0),
+   CONFIG_TEST(check_bridge_distribution_setting_not_a_bridge, TT_FORK),
+   CONFIG_TEST(check_bridge_distribution_setting_valid, 0),
+   CONFIG_TEST(check_bridge_distribution_setting_invalid, 0),
+   CONFIG_TEST(check_bridge_distribution_setting_unrecognised, 0),
    END_OF_TESTCASES
  };
  





More information about the tor-commits mailing list