/* Helper for disk_state_load_from_disk(). */
STATIC int
disk_state_load_from_disk_impl(const char *fname)
{
  int ret;
  char *content = NULL;
  sr_state_t *parsed_state = NULL;
  sr_disk_state_t *disk_state = NULL;

  /* Read content of file so we can parse it. */
  if ((content = read_file_to_str(fname, 0, NULL)) == NULL) {
    log_warn(LD_FS, "SR: Unable to read SR state file %s",
             escaped(fname));
    ret = -errno;
    goto error;
  }

  {
    config_line_t *lines = NULL;
    char *errmsg = NULL;

    /* Every error in this code path will return EINVAL. */
    ret = -EINVAL;
    if (config_get_lines(content, &lines, 0) < 0) {
      config_free_lines(lines);
      goto error;
    }

    disk_state = disk_state_new(time(NULL));
    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);
      tor_free(errmsg);
      goto error;
    }
  }

  /* So far so good, we've loaded our state file into our disk state. Let's
   * validate it and then parse it. */
  if (disk_state_validate(disk_state) < 0) {
    ret = -EINVAL;
    goto error;
  }

  parsed_state = disk_state_parse(disk_state);
  if (parsed_state == NULL) {
    ret = -EINVAL;
    goto error;
  }
  state_set(parsed_state);
  disk_state_set(disk_state);
  tor_free(content);
  log_info(LD_DIR, "SR: State loaded successfully from file %s", fname);
  return 0;

 error:
  disk_state_free(disk_state);
  tor_free(content);
  return ret;
}
/* Reset disk state that is free allocated memory and zeroed the object. */
static void
disk_state_reset(void)
{
  /* Free allocated memory */
  config_free_lines(sr_disk_state->Commit);
  config_free_lines(sr_disk_state->SharedRandValues);
  config_free_lines(sr_disk_state->ExtraLines);
  tor_free(sr_disk_state->TorVersion);

  /* Clean up the struct */
  memset(sr_disk_state, 0, sizeof(*sr_disk_state));

  /* Reset it with useful data */
  sr_disk_state->magic_ = SR_DISK_STATE_MAGIC;
  sr_disk_state->TorVersion = tor_strdup(get_version());
}
Exemple #3
0
/** Helper: parse the config string and strdup into key/value
 * strings. Set *result to the list, or NULL if parsing the string
 * failed.  Return 0 on success, -1 on failure. Warn and ignore any
 * misformatted lines.
 *
 * If <b>extended</b> is set, then treat keys beginning with / and with + as
 * indicating "clear" and "append" respectively. */
int
config_get_lines(const char *string, config_line_t **result, int extended)
{
  config_line_t *list = NULL, **next;
  char *k, *v;
  const char *parse_err;

  next = &list;
  do {
    k = v = NULL;
    string = parse_config_line_from_str_verbose(string, &k, &v, &parse_err);
    if (!string) {
      log_warn(LD_CONFIG, "Error while parsing configuration: %s",
               parse_err?parse_err:"<unknown>");
      config_free_lines(list);
      tor_free(k);
      tor_free(v);
      return -1;
    }
    if (k && v) {
      unsigned command = CONFIG_LINE_NORMAL;
      if (extended) {
        if (k[0] == '+') {
          char *k_new = tor_strdup(k+1);
          tor_free(k);
          k = k_new;
          command = CONFIG_LINE_APPEND;
        } else if (k[0] == '/') {
          char *k_new = tor_strdup(k+1);
          tor_free(k);
          k = k_new;
          tor_free(v);
          v = tor_strdup("");
          command = CONFIG_LINE_CLEAR;
        }
      }
      /* This list can get long, so we keep a pointer to the end of it
       * rather than using config_line_append over and over and getting
       * n^2 performance. */
      *next = tor_malloc_zero(sizeof(config_line_t));
      (*next)->key = k;
      (*next)->value = v;
      (*next)->next = NULL;
      (*next)->command = command;
      next = &((*next)->next);
    } else {
      tor_free(k);
      tor_free(v);
    }
  } while (*string);

  *result = list;
  return 0;
}
Exemple #4
0
static void
test_pt_get_transport_options(void *arg)
{
  char **execve_args;
  smartlist_t *transport_list = smartlist_new();
  managed_proxy_t *mp;
  or_options_t *options = get_options_mutable();
  char *opt_str = NULL;
  config_line_t *cl = NULL;
  (void)arg;

  execve_args = tor_malloc(sizeof(char*)*2);
  execve_args[0] = tor_strdup("cheeseshop");
  execve_args[1] = NULL;

  mp = managed_proxy_create(transport_list, execve_args, 1);
  tt_ptr_op(mp, OP_NE, NULL);
  opt_str = get_transport_options_for_server_proxy(mp);
  tt_ptr_op(opt_str, OP_EQ, NULL);

  smartlist_add_strdup(mp->transports_to_launch, "gruyere");
  smartlist_add_strdup(mp->transports_to_launch, "roquefort");
  smartlist_add_strdup(mp->transports_to_launch, "stnectaire");

  tt_assert(options);

  cl = tor_malloc_zero(sizeof(config_line_t));
  cl->value = tor_strdup("gruyere melty=10 hardness=se;ven");
  options->ServerTransportOptions = cl;

  cl = tor_malloc_zero(sizeof(config_line_t));
  cl->value = tor_strdup("stnectaire melty=4 hardness=three");
  cl->next = options->ServerTransportOptions;
  options->ServerTransportOptions = cl;

  cl = tor_malloc_zero(sizeof(config_line_t));
  cl->value = tor_strdup("pepperjack melty=12 hardness=five");
  cl->next = options->ServerTransportOptions;
  options->ServerTransportOptions = cl;

  opt_str = get_transport_options_for_server_proxy(mp);
  tt_str_op(opt_str, OP_EQ,
            "gruyere:melty=10;gruyere:hardness=se\\;ven;"
            "stnectaire:melty=4;stnectaire:hardness=three");

 done:
  tor_free(opt_str);
  config_free_lines(cl);
  managed_proxy_destroy(mp, 0);
  smartlist_free(transport_list);
}
Exemple #5
0
/**
 * Output a histogram of current circuit build times to
 * the or_state_t state structure.
 */
void
circuit_build_times_update_state(circuit_build_times_t *cbt,
                                 or_state_t *state)
{
  uint32_t *histogram;
  build_time_t i = 0;
  build_time_t nbins = 0;
  config_line_t **next, *line;

  histogram = circuit_build_times_create_histogram(cbt, &nbins);
  // write to state
  config_free_lines(state->BuildtimeHistogram);
  next = &state->BuildtimeHistogram;
  *next = NULL;

  state->TotalBuildTimes = cbt->total_build_times;
  state->CircuitBuildAbandonedCount = 0;

  for (i = 0; i < CBT_NCIRCUITS_TO_OBSERVE; i++) {
    if (cbt->circuit_build_times[i] == CBT_BUILD_ABANDONED)
      state->CircuitBuildAbandonedCount++;
  }

  for (i = 0; i < nbins; i++) {
    // compress the histogram by skipping the blanks
    if (histogram[i] == 0) continue;
    *next = line = tor_malloc_zero(sizeof(config_line_t));
    line->key = tor_strdup("CircuitBuildTimeBin");
    tor_asprintf(&line->value, "%d %d",
            CBT_BIN_TO_MS(i), histogram[i]);
    next = &(line->next);
  }

  if (!unit_tests) {
    if (!get_options()->AvoidDiskWrites)
      or_state_mark_dirty(get_or_state(), 0);
  }

  tor_free(histogram);
}
Exemple #6
0
static void
test_storagedir_save_labeled(void *arg)
{
  (void)arg;
  char *dirname = tor_strdup(get_fname_rnd("store_dir"));
  storage_dir_t *d = NULL;
  uint8_t *inp = tor_malloc_zero(8192);
  config_line_t *labels = NULL;
  char *fname = NULL;
  uint8_t *saved = NULL;

  d = storage_dir_new(dirname, 10);
  tt_assert(d);

  crypto_rand((char *)inp, 8192);

  config_line_append(&labels, "Foo", "bar baz");
  config_line_append(&labels, "quux", "quuzXxz");
  const char expected[] =
    "Foo bar baz\n"
    "quux quuzXxz\n";

  int r = storage_dir_save_labeled_to_file(d, labels, inp, 8192, &fname);
  tt_int_op(r, OP_EQ, 0);

  size_t n = 0;
  saved = storage_dir_read(d, fname, 1, &n);
  tt_assert(memchr(saved, '\0', n));
  tt_str_op((char*)saved, OP_EQ, expected); /* NUL guarantees strcmp works */
  tt_mem_op(saved+strlen(expected)+1, OP_EQ, inp, 8192);

 done:
  storage_dir_free(d);
  tor_free(dirname);
  tor_free(inp);
  tor_free(fname);
  config_free_lines(labels);
  tor_free(saved);
}
Exemple #7
0
/** Reload the persistent state from disk, generating a new state as needed.
 * Return 0 on success, less than 0 on failure.
 */
int
or_state_load(void)
{
  or_state_t *new_state = NULL;
  char *contents = NULL, *fname;
  char *errmsg = NULL;
  int r = -1, badstate = 0;

  fname = get_datadir_fname("state");
  switch (file_status(fname)) {
    case FN_FILE:
      if (!(contents = read_file_to_str(fname, 0, NULL))) {
        log_warn(LD_FS, "Unable to read state file \"%s\"", fname);
        goto done;
      }
      break;
    case FN_NOENT:
      break;
    case FN_ERROR:
    case FN_DIR:
    default:
      log_warn(LD_GENERAL,"State file \"%s\" is not a file? Failing.", fname);
      goto done;
  }
  new_state = tor_malloc_zero(sizeof(or_state_t));
  new_state->_magic = OR_STATE_MAGIC;
  config_init(&state_format, new_state);
  if (contents) {
    config_line_t *lines=NULL;
    int assign_retval;
    if (config_get_lines(contents, &lines, 0)<0)
      goto done;
    assign_retval = config_assign(&state_format, new_state,
                                  lines, 0, 0, &errmsg);
    config_free_lines(lines);
    if (assign_retval<0)
      badstate = 1;
    if (errmsg) {
      log_warn(LD_GENERAL, "%s", errmsg);
      tor_free(errmsg);
    }
  }

  if (!badstate && or_state_validate(NULL, new_state, 1, &errmsg) < 0)
    badstate = 1;

  if (errmsg) {
    log_warn(LD_GENERAL, "%s", errmsg);
    tor_free(errmsg);
  }

  if (badstate && !contents) {
    log_warn(LD_BUG, "Uh oh.  We couldn't even validate our own default state."
             " This is a bug in Tor.");
    goto done;
  } else if (badstate && contents) {
    or_state_save_broken(fname);

    tor_free(contents);
    config_free(&state_format, new_state);

    new_state = tor_malloc_zero(sizeof(or_state_t));
    new_state->_magic = OR_STATE_MAGIC;
    config_init(&state_format, new_state);
  } else if (contents) {
    log_info(LD_GENERAL, "Loaded state from \"%s\"", fname);
  } else {
    log_info(LD_GENERAL, "Initialized state");
  }
  if (or_state_set(new_state) == -1) {
    or_state_save_broken(fname);
  }
  new_state = NULL;
  if (!contents) {
    global_state->next_write = 0;
    or_state_save(time(NULL));
  }
  r = 0;

 done:
  tor_free(fname);
  tor_free(contents);
  if (new_state)
    config_free(&state_format, new_state);

  return r;
}
Exemple #8
0
static void
test_router_get_my_family(void *arg)
{
  (void)arg;
  or_options_t *options = options_new();
  smartlist_t *sl = NULL;
  char *join = NULL;
  // Overwrite the result of router_get_my_identity_digest().  This
  // happens to be okay, but only for testing.
  set_server_identity_key_digest_testing(
                                   (const uint8_t*)"holeinthebottomofthe");

  setup_capture_of_logs(LOG_WARN);

  // No family listed -- so there's no list.
  sl = get_my_declared_family(options);
  tt_ptr_op(sl, OP_EQ, NULL);
  expect_no_log_entry();

#define CLEAR() do {                                    \
    if (sl) {                                           \
      SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));  \
      smartlist_free(sl);                               \
    }                                                   \
    tor_free(join);                                     \
    mock_clean_saved_logs();                            \
  } while (0)

  // Add a single nice friendly hex member.  This should be enough
  // to have our own ID added.
  tt_ptr_op(options->MyFamily, OP_EQ, NULL);
  config_line_append(&options->MyFamily, "MyFamily",
                     "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");

  sl = get_my_declared_family(options);
  tt_ptr_op(sl, OP_NE, NULL);
  tt_int_op(smartlist_len(sl), OP_EQ, 2);
  join = smartlist_join_strings(sl, " ", 0, NULL);
  tt_str_op(join, OP_EQ,
            "$686F6C65696E746865626F74746F6D6F66746865 "
            "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
  expect_no_log_entry();
  CLEAR();

  // Add a hex member with a ~.  The ~ part should get removed.
  config_line_append(&options->MyFamily, "MyFamily",
                     "$0123456789abcdef0123456789abcdef01234567~Muffin");
  sl = get_my_declared_family(options);
  tt_ptr_op(sl, OP_NE, NULL);
  tt_int_op(smartlist_len(sl), OP_EQ, 3);
  join = smartlist_join_strings(sl, " ", 0, NULL);
  tt_str_op(join, OP_EQ,
            "$0123456789ABCDEF0123456789ABCDEF01234567 "
            "$686F6C65696E746865626F74746F6D6F66746865 "
            "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
  expect_no_log_entry();
  CLEAR();

  // Nickname lookup will fail, so a nickname will appear verbatim.
  config_line_append(&options->MyFamily, "MyFamily",
                     "BAGEL");
  sl = get_my_declared_family(options);
  tt_ptr_op(sl, OP_NE, NULL);
  tt_int_op(smartlist_len(sl), OP_EQ, 4);
  join = smartlist_join_strings(sl, " ", 0, NULL);
  tt_str_op(join, OP_EQ,
            "$0123456789ABCDEF0123456789ABCDEF01234567 "
            "$686F6C65696E746865626F74746F6D6F66746865 "
            "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA "
            "bagel");
  expect_single_log_msg_containing(
           "There is a router named \"BAGEL\" in my declared family, but "
           "I have no descriptor for it.");
  CLEAR();

  // A bogus digest should fail entirely.
  config_line_append(&options->MyFamily, "MyFamily",
                     "$painauchocolat");
  sl = get_my_declared_family(options);
  tt_ptr_op(sl, OP_NE, NULL);
  tt_int_op(smartlist_len(sl), OP_EQ, 4);
  join = smartlist_join_strings(sl, " ", 0, NULL);
  tt_str_op(join, OP_EQ,
            "$0123456789ABCDEF0123456789ABCDEF01234567 "
            "$686F6C65696E746865626F74746F6D6F66746865 "
            "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA "
            "bagel");
  // "BAGEL" is still there, but it won't make a warning, because we already
  // warned about it.
  expect_single_log_msg_containing(
           "There is a router named \"$painauchocolat\" in my declared "
           "family, but that isn't a legal digest or nickname. Skipping it.");
  CLEAR();

  // Let's introduce a node we can look up by nickname
  memset(&fake_node, 0, sizeof(fake_node));
  memcpy(fake_node.identity, "whydoyouasknonononon", DIGEST_LEN);
  MOCK(node_get_by_nickname, mock_node_get_by_nickname);

  config_line_append(&options->MyFamily, "MyFamily",
                     "CRUmpeT");
  sl = get_my_declared_family(options);
  tt_ptr_op(sl, OP_NE, NULL);
  tt_int_op(smartlist_len(sl), OP_EQ, 5);
  join = smartlist_join_strings(sl, " ", 0, NULL);
  tt_str_op(join, OP_EQ,
            "$0123456789ABCDEF0123456789ABCDEF01234567 "
            "$686F6C65696E746865626F74746F6D6F66746865 "
            "$776879646F796F7561736B6E6F6E6F6E6F6E6F6E "
            "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA "
            "bagel");
  // "BAGEL" is still there, but it won't make a warning, because we already
  // warned about it.  Some with "$painauchocolat".
  expect_single_log_msg_containing(
           "There is a router named \"CRUmpeT\" in my declared "
           "family, but it wasn't listed by digest. Please consider saying "
           "$776879646F796F7561736B6E6F6E6F6E6F6E6F6E instead, if that's "
           "what you meant.");
  CLEAR();
  UNMOCK(node_get_by_nickname);

  // Try a singleton list containing only us: It should give us NULL.
  config_free_lines(options->MyFamily);
  config_line_append(&options->MyFamily, "MyFamily",
                     "$686F6C65696E746865626F74746F6D6F66746865");
  sl = get_my_declared_family(options);
  tt_ptr_op(sl, OP_EQ, NULL);
  expect_no_log_entry();

 done:
  or_options_free(options);
  teardown_capture_of_logs();
  CLEAR();
  UNMOCK(node_get_by_nickname);

#undef CLEAR
}
Exemple #9
0
static void
test_config_addressmap(void *arg)
{
  char buf[1024];
  char address[256];
  time_t expires = TIME_MAX;
  (void)arg;

  strlcpy(buf, "MapAddress .invalidwildcard.com *.torserver.exit\n" // invalid
          "MapAddress *invalidasterisk.com *.torserver.exit\n" // invalid
          "MapAddress *.google.com *.torserver.exit\n"
          "MapAddress *.yahoo.com *.google.com.torserver.exit\n"
          "MapAddress *.cn.com www.cnn.com\n"
          "MapAddress *.cnn.com www.cnn.com\n"
          "MapAddress ex.com www.cnn.com\n"
          "MapAddress ey.com *.cnn.com\n"
          "MapAddress www.torproject.org 1.1.1.1\n"
          "MapAddress other.torproject.org "
            "this.torproject.org.otherserver.exit\n"
          "MapAddress test.torproject.org 2.2.2.2\n"
          "MapAddress www.google.com 3.3.3.3\n"
          "MapAddress www.example.org 4.4.4.4\n"
          "MapAddress 4.4.4.4 7.7.7.7\n"
          "MapAddress 4.4.4.4 5.5.5.5\n"
          "MapAddress www.infiniteloop.org 6.6.6.6\n"
          "MapAddress 6.6.6.6 www.infiniteloop.org\n"
          , sizeof(buf));

  config_get_lines(buf, &(get_options_mutable()->AddressMap), 0);
  config_register_addressmaps(get_options());

/* Use old interface for now, so we don't need to rewrite the unit tests */
#define addressmap_rewrite(a,s,eo,ao)                                   \
  addressmap_rewrite((a),(s),AMR_FLAG_USE_IPV4_DNS|AMR_FLAG_USE_IPV6_DNS, \
                     (eo),(ao))

  /* MapAddress .invalidwildcard.com .torserver.exit  - no match */
  strlcpy(address, "www.invalidwildcard.com", sizeof(address));
  test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));

  /* MapAddress *invalidasterisk.com .torserver.exit  - no match */
  strlcpy(address, "www.invalidasterisk.com", sizeof(address));
  test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));

  /* Where no mapping for FQDN match on top-level domain */
  /* MapAddress .google.com .torserver.exit */
  strlcpy(address, "reader.google.com", sizeof(address));
  test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
  test_streq(address, "reader.torserver.exit");

  /* MapAddress *.yahoo.com *.google.com.torserver.exit */
  strlcpy(address, "reader.yahoo.com", sizeof(address));
  test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
  test_streq(address, "reader.google.com.torserver.exit");

  /*MapAddress *.cnn.com www.cnn.com */
  strlcpy(address, "cnn.com", sizeof(address));
  test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
  test_streq(address, "www.cnn.com");

  /* MapAddress .cn.com www.cnn.com */
  strlcpy(address, "www.cn.com", sizeof(address));
  test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
  test_streq(address, "www.cnn.com");

  /* MapAddress ex.com www.cnn.com  - no match */
  strlcpy(address, "www.ex.com", sizeof(address));
  test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));

  /* MapAddress ey.com *.cnn.com - invalid expression */
  strlcpy(address, "ey.com", sizeof(address));
  test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));

  /* Where mapping for FQDN match on FQDN */
  strlcpy(address, "www.google.com", sizeof(address));
  test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
  test_streq(address, "3.3.3.3");

  strlcpy(address, "www.torproject.org", sizeof(address));
  test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
  test_streq(address, "1.1.1.1");

  strlcpy(address, "other.torproject.org", sizeof(address));
  test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
  test_streq(address, "this.torproject.org.otherserver.exit");

  strlcpy(address, "test.torproject.org", sizeof(address));
  test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
  test_streq(address, "2.2.2.2");

  /* Test a chain of address mappings and the order in which they were added:
          "MapAddress www.example.org 4.4.4.4"
          "MapAddress 4.4.4.4 7.7.7.7"
          "MapAddress 4.4.4.4 5.5.5.5"
  */
  strlcpy(address, "www.example.org", sizeof(address));
  test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
  test_streq(address, "5.5.5.5");

  /* Test infinite address mapping results in no change */
  strlcpy(address, "www.infiniteloop.org", sizeof(address));
  test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
  test_streq(address, "www.infiniteloop.org");

  /* Test we don't find false positives */
  strlcpy(address, "www.example.com", sizeof(address));
  test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));

  /* Test top-level-domain matching a bit harder */
  config_free_lines(get_options_mutable()->AddressMap);
  addressmap_clear_configured();
  strlcpy(buf, "MapAddress *.com *.torserver.exit\n"
          "MapAddress *.torproject.org 1.1.1.1\n"
          "MapAddress *.net 2.2.2.2\n"
          , sizeof(buf));
  config_get_lines(buf, &(get_options_mutable()->AddressMap), 0);
  config_register_addressmaps(get_options());

  strlcpy(address, "www.abc.com", sizeof(address));
  test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
  test_streq(address, "www.abc.torserver.exit");

  strlcpy(address, "www.def.com", sizeof(address));
  test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
  test_streq(address, "www.def.torserver.exit");

  strlcpy(address, "www.torproject.org", sizeof(address));
  test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
  test_streq(address, "1.1.1.1");

  strlcpy(address, "test.torproject.org", sizeof(address));
  test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
  test_streq(address, "1.1.1.1");

  strlcpy(address, "torproject.net", sizeof(address));
  test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
  test_streq(address, "2.2.2.2");

  /* We don't support '*' as a mapping directive */
  config_free_lines(get_options_mutable()->AddressMap);
  addressmap_clear_configured();
  strlcpy(buf, "MapAddress * *.torserver.exit\n", sizeof(buf));
  config_get_lines(buf, &(get_options_mutable()->AddressMap), 0);
  config_register_addressmaps(get_options());

  strlcpy(address, "www.abc.com", sizeof(address));
  test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));

  strlcpy(address, "www.def.net", sizeof(address));
  test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));

  strlcpy(address, "www.torproject.org", sizeof(address));
  test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));

#undef addressmap_rewrite

 done:
  config_free_lines(get_options_mutable()->AddressMap);
  get_options_mutable()->AddressMap = NULL;
}
Exemple #10
0
/**
 * Decode a <b>line</b> containing a series of space-separated 'Key=Value'
 * pairs, using the provided <b>flags</b> to decode it.  Return a newly
 * allocated list of pairs on success, or NULL on failure.
 *
 * If KV_QUOTED is set in <b>flags</b>, then (double-)quoted values are
 * allowed. Otherwise, such values are not allowed.
 *
 * If KV_OMIT_KEYS is set in <b>flags</b>, then values without keys are
 * allowed.  Otherwise, such values are not allowed.
 */
config_line_t *
kvline_parse(const char *line, unsigned flags)
{
  const char *cp = line, *cplast = NULL;
  bool omit_keys = (flags & KV_OMIT_KEYS) != 0;
  bool quoted = (flags & KV_QUOTED) != 0;

  config_line_t *result = NULL;
  config_line_t **next_line = &result;

  char *key = NULL;
  char *val = NULL;

  while (*cp) {
    key = val = NULL;
    {
      size_t idx = strspn(cp, " \t\r\v\n");
      cp += idx;
    }
    if (BUG(cp == cplast)) {
      /* If we didn't parse anything, this code is broken. */
      goto err; // LCOV_EXCL_LINE
    }
    cplast = cp;
    if (! *cp)
      break; /* End of string; we're done. */

    /* Possible formats are K=V, K="V", V, and "V", depending on flags. */

    /* Find the key. */
    if (*cp != '\"') {
      size_t idx = strcspn(cp, " \t\r\v\n=");

      if (cp[idx] == '=') {
        key = tor_memdup_nulterm(cp, idx);
        cp += idx + 1;
      } else {
        if (!omit_keys)
          goto err;
      }
    }

    if (*cp == '\"') {
      /* The type is "V". */
      if (!quoted)
        goto err;
      size_t len=0;
      cp = unescape_string(cp, &val, &len);
      if (cp == NULL || len != strlen(val)) {
        // The string contains a NUL or is badly coded.
        goto err;
      }
    } else {
      size_t idx = strcspn(cp, " \t\r\v\n");
      val = tor_memdup_nulterm(cp, idx);
      cp += idx;
    }

    if (key && strlen(key) == 0) {
      /* We don't allow empty keys. */
      goto err;
    }

    *next_line = tor_malloc_zero(sizeof(config_line_t));
    (*next_line)->key = key ? key : tor_strdup("");
    (*next_line)->value = val;
    next_line = &(*next_line)->next;
    key = val = NULL;
  }

  if (!kvline_can_encode_lines(result, flags)) {
    goto err;
  }
  return result;

 err:
  tor_free(key);
  tor_free(val);
  config_free_lines(result);
  return NULL;
}
Exemple #11
0
static void
test_storagedir_read_labeled(void *arg)
{
  (void)arg;
  char *dirname = tor_strdup(get_fname_rnd("store_dir"));
  storage_dir_t *d = NULL;
  uint8_t *inp = tor_malloc_zero(8192);
  config_line_t *labels = NULL, *labels2 = NULL;
  char *fname = NULL;
  tor_mmap_t *map = NULL;
  uint8_t *as_read = NULL;

  d = storage_dir_new(dirname, 10);
  tt_assert(d);

  tor_snprintf((char*)inp, 8192,
               "Hello world\n"
               "This is a test\n"
               "Yadda yadda.\n");
  size_t bodylen = 8192 - strlen((char*)inp) - 1;
  crypto_rand((char *)inp+strlen((char*)inp)+1, bodylen);

  int r = storage_dir_save_bytes_to_file(d, inp, 8192, 1, &fname);
  tt_int_op(r, OP_EQ, 0);

  /* Try mapping */
  const uint8_t *datap = NULL;
  size_t sz = 0;
  map = storage_dir_map_labeled(d, fname, &labels, &datap, &sz);
  tt_assert(map);
  tt_assert(datap);
  tt_u64_op(sz, OP_EQ, bodylen);
  tt_mem_op(datap, OP_EQ, inp+strlen((char*)inp)+1, bodylen);
  tt_assert(labels);
  tt_str_op(labels->key, OP_EQ, "Hello");
  tt_str_op(labels->value, OP_EQ, "world");
  tt_assert(labels->next);
  tt_str_op(labels->next->key, OP_EQ, "This");
  tt_str_op(labels->next->value, OP_EQ, "is a test");
  tt_assert(labels->next->next);
  tt_str_op(labels->next->next->key, OP_EQ, "Yadda");
  tt_str_op(labels->next->next->value, OP_EQ, "yadda.");
  tt_ptr_op(labels->next->next->next, OP_EQ, NULL);

  /* Try reading this time. */
  sz = 0;
  as_read = storage_dir_read_labeled(d, fname, &labels2, &sz);
  tt_assert(as_read);
  tt_u64_op(sz, OP_EQ, bodylen);
  tt_mem_op(as_read, OP_EQ, inp+strlen((char*)inp)+1, bodylen);
  tt_assert(config_lines_eq(labels, labels2));

 done:
  storage_dir_free(d);
  tor_free(dirname);
  tor_free(inp);
  tor_free(fname);
  config_free_lines(labels);
  config_free_lines(labels2);
  tor_munmap_file(map);
  tor_free(as_read);
}