Example #1
0
static void
test_routerlist_launch_descriptor_downloads(void *arg)
{
  smartlist_t *downloadable = smartlist_new();
  time_t now = time(NULL);
  char *cp;
  (void)arg;

  for (int i = 0; i < 100; i++) {
    cp = tor_malloc(DIGEST256_LEN);
    tt_assert(cp);
    crypto_rand(cp, DIGEST256_LEN);
    smartlist_add(downloadable, cp);
  }

  MOCK(initiate_descriptor_downloads, mock_initiate_descriptor_downloads);
  launch_descriptor_downloads(DIR_PURPOSE_FETCH_MICRODESC, downloadable,
                              NULL, now);
  tt_int_op(3, OP_EQ, count);
  UNMOCK(initiate_descriptor_downloads);

 done:
  SMARTLIST_FOREACH(downloadable, char *, cp1, tor_free(cp1));
  smartlist_free(downloadable);
}
Example #2
0
static void
test_address_get_if_addrs_ifaddrs(void *arg)
{

  smartlist_t *results = NULL;

  (void)arg;

  results = get_interface_addresses_ifaddrs(LOG_ERR, AF_UNSPEC);

  tt_assert(results);
  /* Some FreeBSD jails don't have localhost IP address. Instead, they only
   * have the address assigned to the jail (whatever that may be).
   * And a jail without a network connection might not have any addresses at
   * all. */
  tt_assert(!smartlist_contains_null_tor_addr(results));

  /* If there are addresses, they must be IPv4 or IPv6 */
  if (smartlist_len(results) > 0) {
    tt_assert(smartlist_contains_ipv4_tor_addr(results)
              || smartlist_contains_ipv6_tor_addr(results));
  }

  done:
  if (results) {
    SMARTLIST_FOREACH(results, tor_addr_t *, t, tor_free(t));
  }
  smartlist_free(results);
  return;
}
Example #3
0
static void
test_routerlist_initiate_descriptor_downloads(void *arg)
{
  const char *prose = "unhurried and wise, we perceive.";
  smartlist_t *digests = smartlist_new();
  (void)arg;

  for (int i = 0; i < 20; i++) {
    smartlist_add(digests, (char*)prose);
  }

  MOCK(directory_get_from_dirserver, mock_get_from_dirserver);
  initiate_descriptor_downloads(NULL, DIR_PURPOSE_FETCH_MICRODESC,
                                digests, 3, 7, 0);
  UNMOCK(directory_get_from_dirserver);

  tt_str_op(output, OP_EQ, "d/"
            "dW5odXJyaWVkIGFuZCB3aXNlLCB3ZSBwZXJjZWl2ZS4-"
            "dW5odXJyaWVkIGFuZCB3aXNlLCB3ZSBwZXJjZWl2ZS4-"
            "dW5odXJyaWVkIGFuZCB3aXNlLCB3ZSBwZXJjZWl2ZS4-"
            "dW5odXJyaWVkIGFuZCB3aXNlLCB3ZSBwZXJjZWl2ZS4"
            ".z");

 done:
  smartlist_free(digests);
}
Example #4
0
/* Given the previous SRV and the current SRV, return a heap allocated
 * string with their data that could be put in a vote or a consensus. Caller
 * must free the returned string.  Return NULL if no SRVs were provided. */
static char *
get_ns_str_from_sr_values(const sr_srv_t *prev_srv, const sr_srv_t *cur_srv)
{
  smartlist_t *chunks = NULL;
  char *srv_str;

  if (!prev_srv && !cur_srv) {
    return NULL;
  }

  chunks = smartlist_new();

  if (prev_srv) {
    char *srv_line = srv_to_ns_string(prev_srv, previous_srv_str);
    smartlist_add(chunks, srv_line);
  }

  if (cur_srv) {
    char *srv_line = srv_to_ns_string(cur_srv, current_srv_str);
    smartlist_add(chunks, srv_line);
  }

  /* Join the line(s) here in one string to return. */
  srv_str = smartlist_join_strings(chunks, "", 0, NULL);
  SMARTLIST_FOREACH(chunks, char *, s, tor_free(s));
  smartlist_free(chunks);

  return srv_str;
}
Example #5
0
static void
test_pt_get_extrainfo_string(void *arg)
{
  managed_proxy_t *mp1 = NULL, *mp2 = NULL;
  char **argv1, **argv2;
  smartlist_t *t1 = smartlist_new(), *t2 = smartlist_new();
  int r;
  char *s = NULL;
  (void) arg;

  argv1 = tor_malloc_zero(sizeof(char*)*3);
  argv1[0] = tor_strdup("ewige");
  argv1[1] = tor_strdup("Blumenkraft");
  argv1[2] = NULL;
  argv2 = tor_malloc_zero(sizeof(char*)*4);
  argv2[0] = tor_strdup("und");
  argv2[1] = tor_strdup("ewige");
  argv2[2] = tor_strdup("Schlangenkraft");
  argv2[3] = NULL;

  mp1 = managed_proxy_create(t1, argv1, 1);
  mp2 = managed_proxy_create(t2, argv2, 1);

  r = parse_smethod_line("SMETHOD hagbard 127.0.0.1:5555", mp1);
  tt_int_op(r, OP_EQ, 0);
  r = parse_smethod_line("SMETHOD celine 127.0.0.1:1723 ARGS:card=no-enemy",
                         mp2);
  tt_int_op(r, OP_EQ, 0);

  /* Force these proxies to look "completed" or they won't generate output. */
  mp1->conf_state = mp2->conf_state = PT_PROTO_COMPLETED;

  s = pt_get_extra_info_descriptor_string();
  tt_assert(s);
  tt_str_op(s, OP_EQ,
            "transport hagbard 127.0.0.1:5555\n"
            "transport celine 127.0.0.1:1723 card=no-enemy\n");

 done:
  /* XXXX clean up better */
  smartlist_free(t1);
  smartlist_free(t2);
  tor_free(s);
}
Example #6
0
void
tor_end_capture_bugs_(void)
{
  n_bugs_to_capture = 0;
  if (!bug_messages)
    return;
  SMARTLIST_FOREACH(bug_messages, char *, cp, tor_free(cp));
  smartlist_free(bug_messages);
  bug_messages = NULL;
}
Example #7
0
/** Free memory occupied by <b>entry_guard_lines</b>. */
static void
state_lines_free(smartlist_t *entry_guard_lines)
{
  SMARTLIST_FOREACH_BEGIN(entry_guard_lines, smartlist_t *, state_lines) {
    char *state_key = smartlist_get(state_lines, 0);
    char *state_value = smartlist_get(state_lines, 1);

    tor_free(state_key);
    tor_free(state_value);
    smartlist_free(state_lines);
  } SMARTLIST_FOREACH_END(state_lines);
/** Free the bridge <b>bridge</b>. */
static void
bridge_free(bridge_info_t *bridge)
{
  if (!bridge)
    return;

  tor_free(bridge->transport_name);
  if (bridge->socks_args) {
    SMARTLIST_FOREACH(bridge->socks_args, char*, s, tor_free(s));
    smartlist_free(bridge->socks_args);
  }
Example #9
0
/** Free whatever memory is needed for predicting which ports will
 * be used.
 */
void
predicted_ports_free_all(void)
{
  if (!predicted_ports_list)
    return;
  predicted_ports_total_alloc -=
    smartlist_len(predicted_ports_list)*sizeof(predicted_port_t);
  SMARTLIST_FOREACH(predicted_ports_list, predicted_port_t *,
                    pp, tor_free(pp));
  smartlist_free(predicted_ports_list);
}
Example #10
0
/**
 * Helper: clear all entries from <b>cache</b> (but do not delete
 * any that aren't marked for removal
 */
static void
consensus_cache_clear(consensus_cache_t *cache)
{
  consensus_cache_delete_pending(cache, 0);

  SMARTLIST_FOREACH_BEGIN(cache->entries, consensus_cache_entry_t *, ent) {
    ent->in_cache = NULL;
    consensus_cache_entry_decref(ent);
  } SMARTLIST_FOREACH_END(ent);
  smartlist_free(cache->entries);
  cache->entries = NULL;
}
Example #11
0
/** Return the number of circuits in state OR_WAIT, waiting for the given
 * connection. */
int
circuit_count_pending_on_or_conn(or_connection_t *or_conn)
{
  int cnt;
  smartlist_t *sl = smartlist_create();
  circuit_get_all_pending_on_or_conn(sl, or_conn);
  cnt = smartlist_len(sl);
  smartlist_free(sl);
  log_debug(LD_CIRC,"or_conn to %s, %d pending circs",
            or_conn->nickname ? or_conn->nickname : "NULL", cnt);
  return cnt;
}
static void
test_cntev_append_cell_stats(void *arg)
{
    smartlist_t *event_parts;
    char *cp = NULL;
    const char *key = "Z";
    uint64_t include_if_non_zero[CELL_COMMAND_MAX_ + 1],
             number_to_include[CELL_COMMAND_MAX_ + 1];
    (void)arg;

    event_parts = smartlist_new();
    memset(include_if_non_zero, 0,
           (CELL_COMMAND_MAX_ + 1) * sizeof(uint64_t));
    memset(number_to_include, 0,
           (CELL_COMMAND_MAX_ + 1) * sizeof(uint64_t));

    /* All array entries empty. */
    append_cell_stats_by_command(event_parts, key,
                                 include_if_non_zero,
                                 number_to_include);
    tt_int_op(0, OP_EQ, smartlist_len(event_parts));

    /* There's a RELAY cell to include, but the corresponding field in
     * include_if_non_zero is still zero. */
    number_to_include[CELL_RELAY] = 1;
    append_cell_stats_by_command(event_parts, key,
                                 include_if_non_zero,
                                 number_to_include);
    tt_int_op(0, OP_EQ, smartlist_len(event_parts));

    /* Now include single RELAY cell. */
    include_if_non_zero[CELL_RELAY] = 2;
    append_cell_stats_by_command(event_parts, key,
                                 include_if_non_zero,
                                 number_to_include);
    cp = smartlist_pop_last(event_parts);
    tt_str_op("Z=relay:1", OP_EQ, cp);
    tor_free(cp);

    /* Add four CREATE cells. */
    include_if_non_zero[CELL_CREATE] = 3;
    number_to_include[CELL_CREATE] = 4;
    append_cell_stats_by_command(event_parts, key,
                                 include_if_non_zero,
                                 number_to_include);
    cp = smartlist_pop_last(event_parts);
    tt_str_op("Z=create:4,relay:1", OP_EQ, cp);

done:
    tor_free(cp);
    smartlist_free(event_parts);
}
Example #13
0
/**
 * Given a <b>cache</b>, return some entry for which <b>key</b>=<b>value</b>.
 * Return NULL if no such entry exists.
 *
 * Does not adjust reference counts.
 */
consensus_cache_entry_t *
consensus_cache_find_first(consensus_cache_t *cache,
                           const char *key,
                           const char *value)
{
  smartlist_t *tmp = smartlist_new();
  consensus_cache_find_all(tmp, cache, key, value);
  consensus_cache_entry_t *ent = NULL;
  if (smartlist_len(tmp))
    ent = smartlist_get(tmp, 0);
  smartlist_free(tmp);
  return ent;
}
Example #14
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);
}
Example #15
0
static void
test_pt_protocol(void *arg)
{
  char line[200];

  managed_proxy_t *mp = tor_malloc_zero(sizeof(managed_proxy_t));
  (void)arg;
  mp->conf_state = PT_PROTO_LAUNCHED;
  mp->transports = smartlist_new();
  mp->argv = tor_calloc(2, sizeof(char *));
  mp->argv[0] = tor_strdup("<testcase>");

  /* various wrong protocol runs: */

  strlcpy(line,"VERSION 1",sizeof(line));
  handle_proxy_line(line, mp);
  tt_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS);

  strlcpy(line,"VERSION 1",sizeof(line));
  handle_proxy_line(line, mp);
  tt_assert(mp->conf_state == PT_PROTO_BROKEN);

  reset_mp(mp);

  strlcpy(line,"CMETHOD trebuchet socks5 127.0.0.1:1999",sizeof(line));
  handle_proxy_line(line, mp);
  tt_assert(mp->conf_state == PT_PROTO_BROKEN);

  reset_mp(mp);

  /* correct protocol run: */
  strlcpy(line,"VERSION 1",sizeof(line));
  handle_proxy_line(line, mp);
  tt_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS);

  strlcpy(line,"CMETHOD trebuchet socks5 127.0.0.1:1999",sizeof(line));
  handle_proxy_line(line, mp);
  tt_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS);

  strlcpy(line,"CMETHODS DONE",sizeof(line));
  handle_proxy_line(line, mp);
  tt_assert(mp->conf_state == PT_PROTO_CONFIGURED);

 done:
  reset_mp(mp);
  smartlist_free(mp->transports);
  tor_free(mp->argv[0]);
  tor_free(mp->argv);
  tor_free(mp);
}
Example #16
0
static void
test_sigsafe_err(void *arg)
{
  const char *fn=get_fname("sigsafe_err_log");
  char *content=NULL;
  log_severity_list_t include_bug;
  smartlist_t *lines = smartlist_new();
  (void)arg;

  set_log_severity_config(LOG_WARN, LOG_ERR, &include_bug);

  init_logging(1);
  mark_logs_temp();
  add_file_log(&include_bug, fn, 0);
  tor_log_update_sigsafe_err_fds();
  close_temp_logs();

  close(STDERR_FILENO);
  log_err(LD_BUG, "Say, this isn't too cool.");
  tor_log_err_sigsafe("Minimal.\n", NULL);

  set_log_time_granularity(100*1000);
  tor_log_err_sigsafe("Testing any ",
                      "attempt to manually log ",
                      "from a signal.\n",
                      NULL);
  mark_logs_temp();
  close_temp_logs();
  close(STDERR_FILENO);
  content = read_file_to_str(fn, 0, NULL);

  tt_assert(content != NULL);
  tor_split_lines(lines, content, (int)strlen(content));
  tt_int_op(smartlist_len(lines), >=, 5);

  if (strstr(smartlist_get(lines, 0), "opening new log file"))
    smartlist_del_keeporder(lines, 0);
  tt_assert(strstr(smartlist_get(lines, 0), "Say, this isn't too cool"));
  /* Next line is blank. */
  tt_assert(!strcmpstart(smartlist_get(lines, 1), "=============="));
  tt_assert(!strcmpstart(smartlist_get(lines, 2), "Minimal."));
  /* Next line is blank. */
  tt_assert(!strcmpstart(smartlist_get(lines, 3), "=============="));
  tt_str_op(smartlist_get(lines, 4), ==,
            "Testing any attempt to manually log from a signal.");

 done:
  tor_free(content);
  smartlist_free(lines);
}
Example #17
0
/** Build a formatted command line used for the NT service. Return a
 * pointer to the formatted string on success, or NULL on failure.  Set
 * *<b>using_default_torrc</b> to true if we're going to use the default
 * location to torrc, or 1 if an option was specified on the command line.
 */
static char *
nt_service_command_line(int *using_default_torrc)
{
  TCHAR tor_exe[MAX_PATH+1];
  char *command, *options=NULL;
  smartlist_t *sl;
  int i, cmdlen;
  *using_default_torrc = 1;

  /* Get the location of tor.exe */
  if (0 == GetModuleFileName(NULL, tor_exe, MAX_PATH))
    return NULL;

  /* Get the service arguments */
  sl = smartlist_create();
  for (i = 1; i < backup_argc; ++i) {
    if (!strcmp(backup_argv[i], "--options") ||
        !strcmp(backup_argv[i], "-options")) {
      while (++i < backup_argc) {
        if (!strcmp(backup_argv[i], "-f"))
          *using_default_torrc = 0;
        smartlist_add(sl, backup_argv[i]);
      }
    }
  }
  if (smartlist_len(sl))
    options = smartlist_join_strings(sl,"\" \"",0,NULL);
  smartlist_free(sl);

  /* Allocate a string for the NT service command line */
  cmdlen = strlen(tor_exe) + (options?strlen(options):0) + 32;
  command = tor_malloc(cmdlen);

  /* Format the service command */
  if (options) {
    if (tor_snprintf(command, cmdlen, "\"%s\" --nt-service \"%s\"",
                     tor_exe, options)<0) {
      tor_free(command); /* sets command to NULL. */
    }
  } else { /* ! options */
    if (tor_snprintf(command, cmdlen, "\"%s\" --nt-service", tor_exe)<0) {
      tor_free(command); /* sets command to NULL. */
    }
  }

  tor_free(options);
  return command;
}
Example #18
0
/* Remove a directory and all of its subdirectories */
static void
rm_rf(const char *dir)
{
  struct stat st;
  smartlist_t *elements;

  elements = tor_listdir(dir);
  if (elements) {
    SMARTLIST_FOREACH_BEGIN(elements, const char *, cp) {
         char *tmp = NULL;
         tor_asprintf(&tmp, "%s"PATH_SEPARATOR"%s", dir, cp);
         if (0 == stat(tmp,&st) && (st.st_mode & S_IFDIR)) {
           rm_rf(tmp);
         } else {
           if (unlink(tmp)) {
             fprintf(stderr, "Error removing %s: %s\n", tmp, strerror(errno));
           }
         }
         tor_free(tmp);
    } SMARTLIST_FOREACH_END(cp);
    SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp));
    smartlist_free(elements);
  }
Example #19
0
/** Release all storage held by circuits. */
void
circuit_free_all(void)
{
  circuit_t *next;
  while (global_circuitlist) {
    next = global_circuitlist->next;
    if (! CIRCUIT_IS_ORIGIN(global_circuitlist)) {
      or_circuit_t *or_circ = TO_OR_CIRCUIT(global_circuitlist);
      while (or_circ->resolving_streams) {
        edge_connection_t *next_conn;
        next_conn = or_circ->resolving_streams->next_stream;
        connection_free(TO_CONN(or_circ->resolving_streams));
        or_circ->resolving_streams = next_conn;
      }
    }
    circuit_free(global_circuitlist);
    global_circuitlist = next;
  }
  if (circuits_pending_or_conns) {
    smartlist_free(circuits_pending_or_conns);
    circuits_pending_or_conns = NULL;
  }
  HT_CLEAR(orconn_circid_map, &orconn_circid_circuit_map);
}
Example #20
0
static void
test_address_get_if_addrs_ioctl(void *arg)
{

  smartlist_t *result = NULL;

  (void)arg;

  result = get_interface_addresses_ioctl(LOG_ERR, AF_INET);

  /* On an IPv6-only system, this will fail and return NULL
  tt_assert(result);
  */

  /* Some FreeBSD jails don't have localhost IP address. Instead, they only
   * have the address assigned to the jail (whatever that may be).
   * And a jail without a network connection might not have any addresses at
   * all. */
  if (result) {
    tt_assert(!smartlist_contains_null_tor_addr(result));

    /* If there are addresses, they must be IPv4 or IPv6.
     * (AIX supports IPv6 from SIOCGIFCONF.) */
    if (smartlist_len(result) > 0) {
      tt_assert(smartlist_contains_ipv4_tor_addr(result)
                || smartlist_contains_ipv6_tor_addr(result));
    }
  }

 done:
  if (result) {
    SMARTLIST_FOREACH(result, tor_addr_t *, t, tor_free(t));
    smartlist_free(result);
  }
  return;
}
Example #21
0
/** Helper: write the router-status information in <b>rs</b> into a newly
 * allocated character buffer.  Use the same format as in network-status
 * documents.  If <b>version</b> is non-NULL, add a "v" line for the platform.
 *
 * consensus_method is the current consensus method when format is
 * NS_V3_CONSENSUS or NS_V3_CONSENSUS_MICRODESC. It is ignored for other
 * formats: pass ROUTERSTATUS_FORMAT_NO_CONSENSUS_METHOD.
 *
 * Return 0 on success, -1 on failure.
 *
 * The format argument has one of the following values:
 *   NS_V2 - Output an entry suitable for a V2 NS opinion document
 *   NS_V3_CONSENSUS - Output the first portion of a V3 NS consensus entry
 *        for consensus_method.
 *   NS_V3_CONSENSUS_MICRODESC - Output the first portion of a V3 microdesc
 *        consensus entry for consensus_method.
 *   NS_V3_VOTE - Output a complete V3 NS vote. If <b>vrs</b> is present,
 *        it contains additional information for the vote.
 *   NS_CONTROL_PORT - Output a NS document for the control port.
 */
char *
routerstatus_format_entry(const routerstatus_t *rs, const char *version,
                          const char *protocols,
                          routerstatus_format_type_t format,
                          int consensus_method,
                          const vote_routerstatus_t *vrs)
{
  char *summary;
  char *result = NULL;

  char published[ISO_TIME_LEN+1];
  char identity64[BASE64_DIGEST_LEN+1];
  char digest64[BASE64_DIGEST_LEN+1];
  smartlist_t *chunks = smartlist_new();

  format_iso_time(published, rs->published_on);
  digest_to_base64(identity64, rs->identity_digest);
  digest_to_base64(digest64, rs->descriptor_digest);

  smartlist_add_asprintf(chunks,
                   "r %s %s %s%s%s %s %d %d\n",
                   rs->nickname,
                   identity64,
                   (format==NS_V3_CONSENSUS_MICRODESC)?"":digest64,
                   (format==NS_V3_CONSENSUS_MICRODESC)?"":" ",
                   published,
                   fmt_addr32(rs->addr),
                   (int)rs->or_port,
                   (int)rs->dir_port);

  /* TODO: Maybe we want to pass in what we need to build the rest of
   * this here, instead of in the caller. Then we could use the
   * networkstatus_type_t values, with an additional control port value
   * added -MP */

  /* V3 microdesc consensuses only have "a" lines in later consensus methods
   */
  if (format == NS_V3_CONSENSUS_MICRODESC &&
      consensus_method < MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS)
    goto done;

  /* Possible "a" line. At most one for now. */
  if (!tor_addr_is_null(&rs->ipv6_addr)) {
    smartlist_add_asprintf(chunks, "a %s\n",
                           fmt_addrport(&rs->ipv6_addr, rs->ipv6_orport));
  }

  if (format == NS_V3_CONSENSUS || format == NS_V3_CONSENSUS_MICRODESC)
    goto done;

  smartlist_add_asprintf(chunks,
                   "s%s%s%s%s%s%s%s%s%s%s%s\n",
                  /* These must stay in alphabetical order. */
                   rs->is_authority?" Authority":"",
                   rs->is_bad_exit?" BadExit":"",
                   rs->is_exit?" Exit":"",
                   rs->is_fast?" Fast":"",
                   rs->is_possible_guard?" Guard":"",
                   rs->is_hs_dir?" HSDir":"",
                   rs->is_flagged_running?" Running":"",
                   rs->is_stable?" Stable":"",
                   rs->is_staledesc?" StaleDesc":"",
                   rs->is_v2_dir?" V2Dir":"",
                   rs->is_valid?" Valid":"");

  /* length of "opt v \n" */
#define V_LINE_OVERHEAD 7
  if (version && strlen(version) < MAX_V_LINE_LEN - V_LINE_OVERHEAD) {
    smartlist_add_asprintf(chunks, "v %s\n", version);
  }
  if (protocols) {
    smartlist_add_asprintf(chunks, "pr %s\n", protocols);
  }

  if (format != NS_V2) {
    const routerinfo_t* desc = router_get_by_id_digest(rs->identity_digest);
    uint32_t bw_kb;

    if (format != NS_CONTROL_PORT) {
      /* Blow up more or less nicely if we didn't get anything or not the
       * thing we expected.
       */
      if (!desc) {
        char id[HEX_DIGEST_LEN+1];
        char dd[HEX_DIGEST_LEN+1];

        base16_encode(id, sizeof(id), rs->identity_digest, DIGEST_LEN);
        base16_encode(dd, sizeof(dd), rs->descriptor_digest, DIGEST_LEN);
        log_warn(LD_BUG, "Cannot get any descriptor for %s "
            "(wanted descriptor %s).",
            id, dd);
        goto err;
      }

      /* This assert could fire for the control port, because
       * it can request NS documents before all descriptors
       * have been fetched. Therefore, we only do this test when
       * format != NS_CONTROL_PORT. */
      if (tor_memneq(desc->cache_info.signed_descriptor_digest,
            rs->descriptor_digest,
            DIGEST_LEN)) {
        char rl_d[HEX_DIGEST_LEN+1];
        char rs_d[HEX_DIGEST_LEN+1];
        char id[HEX_DIGEST_LEN+1];

        base16_encode(rl_d, sizeof(rl_d),
            desc->cache_info.signed_descriptor_digest, DIGEST_LEN);
        base16_encode(rs_d, sizeof(rs_d), rs->descriptor_digest, DIGEST_LEN);
        base16_encode(id, sizeof(id), rs->identity_digest, DIGEST_LEN);
        log_err(LD_BUG, "descriptor digest in routerlist does not match "
            "the one in routerstatus: %s vs %s "
            "(router %s)\n",
            rl_d, rs_d, id);

        tor_assert(tor_memeq(desc->cache_info.signed_descriptor_digest,
              rs->descriptor_digest,
              DIGEST_LEN));
      }
    }

    if (format == NS_CONTROL_PORT && rs->has_bandwidth) {
      bw_kb = rs->bandwidth_kb;
    } else {
      tor_assert(desc);
      bw_kb = router_get_advertised_bandwidth_capped(desc) / 1000;
    }
    smartlist_add_asprintf(chunks,
                     "w Bandwidth=%d", bw_kb);

    if (format == NS_V3_VOTE && vrs && vrs->has_measured_bw) {
      smartlist_add_asprintf(chunks,
                       " Measured=%d", vrs->measured_bw_kb);
    }
    /* Write down guardfraction information if we have it. */
    if (format == NS_V3_VOTE && vrs && vrs->status.has_guardfraction) {
      smartlist_add_asprintf(chunks,
                             " GuardFraction=%d",
                             vrs->status.guardfraction_percentage);
    }

    smartlist_add_strdup(chunks, "\n");

    if (desc) {
      summary = policy_summarize(desc->exit_policy, AF_INET);
      smartlist_add_asprintf(chunks, "p %s\n", summary);
      tor_free(summary);
    }

    if (format == NS_V3_VOTE && vrs) {
      if (tor_mem_is_zero((char*)vrs->ed25519_id, ED25519_PUBKEY_LEN)) {
        smartlist_add_strdup(chunks, "id ed25519 none\n");
      } else {
        char ed_b64[BASE64_DIGEST256_LEN+1];
        digest256_to_base64(ed_b64, (const char*)vrs->ed25519_id);
        smartlist_add_asprintf(chunks, "id ed25519 %s\n", ed_b64);
      }
    }
  }

 done:
  result = smartlist_join_strings(chunks, "", 0, NULL);

 err:
  SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
  smartlist_free(chunks);

  return result;
}
Example #22
0
File: test_hs.c Project: ageis/tor
/* Test that single onion poisoning works. */
static void
test_single_onion_poisoning(void *arg)
{
  or_options_t opt;
  mock_options = &opt;
  reset_options(mock_options, &mock_get_options_calls);
  MOCK(get_options, mock_get_options);

  int ret = -1;
  intptr_t create_dir_mask = (intptr_t)arg;
  /* Get directories with a random suffix so we can repeat the tests */
  mock_options->DataDirectory = tor_strdup(get_fname_rnd("test_data_dir"));
  rend_service_t *service_1 = tor_malloc_zero(sizeof(rend_service_t));
  char *dir1 = tor_strdup(get_fname_rnd("test_hs_dir1"));
  rend_service_t *service_2 = tor_malloc_zero(sizeof(rend_service_t));
  char *dir2 = tor_strdup(get_fname_rnd("test_hs_dir2"));
  smartlist_t *services = smartlist_new();
  char *poison_path = NULL;
  char *err_msg = NULL;

  mock_options->HiddenServiceSingleHopMode = 1;
  mock_options->HiddenServiceNonAnonymousMode = 1;

  /* Create the data directory, and, if the correct bit in arg is set,
   * create a directory for that service.
   * The data directory is required for the lockfile, which is used when
   * loading keys. */
  ret = check_private_dir(mock_options->DataDirectory, CPD_CREATE, NULL);
  tt_int_op(ret, OP_EQ, 0);
  if (create_dir_mask & CREATE_HS_DIR1) {
    ret = check_private_dir(dir1, CPD_CREATE, NULL);
    tt_int_op(ret, OP_EQ, 0);
  }
  if (create_dir_mask & CREATE_HS_DIR2) {
    ret = check_private_dir(dir2, CPD_CREATE, NULL);
    tt_int_op(ret, OP_EQ, 0);
  }

  service_1->directory = dir1;
  service_2->directory = dir2;
  /* The services own the directory pointers now */
  dir1 = dir2 = NULL;
  /* Add port to service 1 */
  service_1->ports = smartlist_new();
  service_2->ports = smartlist_new();
  rend_service_port_config_t *port1 = rend_service_parse_port_config("80", " ",
                                                                     &err_msg);
  tt_assert(port1);
  tt_ptr_op(err_msg, OP_EQ, NULL);
  smartlist_add(service_1->ports, port1);

  rend_service_port_config_t *port2 = rend_service_parse_port_config("90", " ",
                                                                     &err_msg);
  /* Add port to service 2 */
  tt_assert(port2);
  tt_ptr_op(err_msg, OP_EQ, NULL);
  smartlist_add(service_2->ports, port2);

  /* No services, a service to verify, no problem! */
  mock_options->HiddenServiceSingleHopMode = 0;
  mock_options->HiddenServiceNonAnonymousMode = 0;
  ret = rend_service_verify_single_onion_poison(service_1, mock_options);
  tt_int_op(ret, OP_EQ, 0);
  ret = rend_service_verify_single_onion_poison(service_2, mock_options);
  tt_int_op(ret, OP_EQ, 0);

  /* Either way, no problem. */
  mock_options->HiddenServiceSingleHopMode = 1;
  mock_options->HiddenServiceNonAnonymousMode = 1;
  ret = rend_service_verify_single_onion_poison(service_1, mock_options);
  tt_int_op(ret, OP_EQ, 0);
  ret = rend_service_verify_single_onion_poison(service_2, mock_options);
  tt_int_op(ret, OP_EQ, 0);

  /* Add the first service */
  ret = hs_check_service_private_dir(mock_options->User, service_1->directory,
                                     service_1->dir_group_readable, 1);
  tt_int_op(ret, OP_EQ, 0);
  smartlist_add(services, service_1);
  /* But don't add the second service yet. */

  /* Service directories, but no previous keys, no problem! */
  mock_options->HiddenServiceSingleHopMode = 0;
  mock_options->HiddenServiceNonAnonymousMode = 0;
  ret = rend_service_verify_single_onion_poison(service_1, mock_options);
  tt_int_op(ret, OP_EQ, 0);
  ret = rend_service_verify_single_onion_poison(service_2, mock_options);
  tt_int_op(ret, OP_EQ, 0);

  /* Either way, no problem. */
  mock_options->HiddenServiceSingleHopMode = 1;
  mock_options->HiddenServiceNonAnonymousMode = 1;
  ret = rend_service_verify_single_onion_poison(service_1, mock_options);
  tt_int_op(ret, OP_EQ, 0);
  ret = rend_service_verify_single_onion_poison(service_2, mock_options);
  tt_int_op(ret, OP_EQ, 0);

  /* Poison! Poison! Poison!
   * This can only be done in HiddenServiceSingleHopMode. */
  mock_options->HiddenServiceSingleHopMode = 1;
  mock_options->HiddenServiceNonAnonymousMode = 1;
  ret = rend_service_poison_new_single_onion_dir(service_1, mock_options);
  tt_int_op(ret, OP_EQ, 0);
  /* Poisoning twice is a no-op. */
  ret = rend_service_poison_new_single_onion_dir(service_1, mock_options);
  tt_int_op(ret, OP_EQ, 0);

  /* Poisoned service directories, but no previous keys, no problem! */
  mock_options->HiddenServiceSingleHopMode = 0;
  mock_options->HiddenServiceNonAnonymousMode = 0;
  ret = rend_service_verify_single_onion_poison(service_1, mock_options);
  tt_int_op(ret, OP_EQ, 0);
  ret = rend_service_verify_single_onion_poison(service_2, mock_options);
  tt_int_op(ret, OP_EQ, 0);

  /* Either way, no problem. */
  mock_options->HiddenServiceSingleHopMode = 1;
  mock_options->HiddenServiceNonAnonymousMode = 1;
  ret = rend_service_verify_single_onion_poison(service_1, mock_options);
  tt_int_op(ret, OP_EQ, 0);
  ret = rend_service_verify_single_onion_poison(service_2, mock_options);
  tt_int_op(ret, OP_EQ, 0);

  /* Now add some keys, and we'll have a problem. */
  ret = rend_service_load_all_keys(services);
  tt_int_op(ret, OP_EQ, 0);

  /* Poisoned service directories with previous keys are not allowed. */
  mock_options->HiddenServiceSingleHopMode = 0;
  mock_options->HiddenServiceNonAnonymousMode = 0;
  ret = rend_service_verify_single_onion_poison(service_1, mock_options);
  tt_int_op(ret, OP_LT, 0);
  ret = rend_service_verify_single_onion_poison(service_2, mock_options);
  tt_int_op(ret, OP_EQ, 0);

  /* But they are allowed if we're in non-anonymous mode. */
  mock_options->HiddenServiceSingleHopMode = 1;
  mock_options->HiddenServiceNonAnonymousMode = 1;
  ret = rend_service_verify_single_onion_poison(service_1, mock_options);
  tt_int_op(ret, OP_EQ, 0);
  ret = rend_service_verify_single_onion_poison(service_2, mock_options);
  tt_int_op(ret, OP_EQ, 0);

  /* Re-poisoning directories with existing keys is a no-op, because
   * directories with existing keys are ignored. */
  mock_options->HiddenServiceSingleHopMode = 1;
  mock_options->HiddenServiceNonAnonymousMode = 1;
  ret = rend_service_poison_new_single_onion_dir(service_1, mock_options);
  tt_int_op(ret, OP_EQ, 0);
  /* And it keeps the poison. */
  ret = rend_service_verify_single_onion_poison(service_1, mock_options);
  tt_int_op(ret, OP_EQ, 0);
  ret = rend_service_verify_single_onion_poison(service_2, mock_options);
  tt_int_op(ret, OP_EQ, 0);

  /* Now add the second service: it has no key and no poison file */
  ret = hs_check_service_private_dir(mock_options->User, service_2->directory,
                                     service_2->dir_group_readable, 1);
  tt_int_op(ret, OP_EQ, 0);
  smartlist_add(services, service_2);

  /* A new service, and an existing poisoned service. Not ok. */
  mock_options->HiddenServiceSingleHopMode = 0;
  mock_options->HiddenServiceNonAnonymousMode = 0;
  ret = rend_service_verify_single_onion_poison(service_1, mock_options);
  tt_int_op(ret, OP_LT, 0);
  ret = rend_service_verify_single_onion_poison(service_2, mock_options);
  tt_int_op(ret, OP_EQ, 0);

  /* But ok to add in non-anonymous mode. */
  mock_options->HiddenServiceSingleHopMode = 1;
  mock_options->HiddenServiceNonAnonymousMode = 1;
  ret = rend_service_verify_single_onion_poison(service_1, mock_options);
  tt_int_op(ret, OP_EQ, 0);
  ret = rend_service_verify_single_onion_poison(service_2, mock_options);
  tt_int_op(ret, OP_EQ, 0);

  /* Now remove the poisoning from the first service, and we have the opposite
   * problem. */
  poison_path = rend_service_sos_poison_path(service_1);
  tt_assert(poison_path);
  ret = unlink(poison_path);
  tt_int_op(ret, OP_EQ, 0);

  /* Unpoisoned service directories with previous keys are ok, as are empty
   * directories. */
  mock_options->HiddenServiceSingleHopMode = 0;
  mock_options->HiddenServiceNonAnonymousMode = 0;
  ret = rend_service_verify_single_onion_poison(service_1, mock_options);
  tt_int_op(ret, OP_EQ, 0);
  ret = rend_service_verify_single_onion_poison(service_2, mock_options);
  tt_int_op(ret, OP_EQ, 0);

  /* But the existing unpoisoned key is not ok in non-anonymous mode, even if
   * there is an empty service. */
  mock_options->HiddenServiceSingleHopMode = 1;
  mock_options->HiddenServiceNonAnonymousMode = 1;
  ret = rend_service_verify_single_onion_poison(service_1, mock_options);
  tt_int_op(ret, OP_LT, 0);
  ret = rend_service_verify_single_onion_poison(service_2, mock_options);
  tt_int_op(ret, OP_EQ, 0);

  /* Poisoning directories with existing keys is a no-op, because directories
   * with existing keys are ignored. But the new directory should poison. */
  mock_options->HiddenServiceSingleHopMode = 1;
  mock_options->HiddenServiceNonAnonymousMode = 1;
  ret = rend_service_poison_new_single_onion_dir(service_1, mock_options);
  tt_int_op(ret, OP_EQ, 0);
  ret = rend_service_poison_new_single_onion_dir(service_2, mock_options);
  tt_int_op(ret, OP_EQ, 0);
  /* And the old directory remains unpoisoned. */
  ret = rend_service_verify_single_onion_poison(service_1, mock_options);
  tt_int_op(ret, OP_LT, 0);
  ret = rend_service_verify_single_onion_poison(service_2, mock_options);
  tt_int_op(ret, OP_EQ, 0);

  /* And the new directory should be ignored, because it has no key. */
  mock_options->HiddenServiceSingleHopMode = 0;
  mock_options->HiddenServiceNonAnonymousMode = 0;
  ret = rend_service_verify_single_onion_poison(service_1, mock_options);
  tt_int_op(ret, OP_EQ, 0);
  ret = rend_service_verify_single_onion_poison(service_2, mock_options);
  tt_int_op(ret, OP_EQ, 0);

  /* Re-poisoning directories without existing keys is a no-op. */
  mock_options->HiddenServiceSingleHopMode = 1;
  mock_options->HiddenServiceNonAnonymousMode = 1;
  ret = rend_service_poison_new_single_onion_dir(service_1, mock_options);
  tt_int_op(ret, OP_EQ, 0);
  ret = rend_service_poison_new_single_onion_dir(service_2, mock_options);
  tt_int_op(ret, OP_EQ, 0);
  /* And the old directory remains unpoisoned. */
  ret = rend_service_verify_single_onion_poison(service_1, mock_options);
  tt_int_op(ret, OP_LT, 0);
  ret = rend_service_verify_single_onion_poison(service_2, mock_options);
  tt_int_op(ret, OP_EQ, 0);

 done:
  /* The test harness deletes the directories at exit */
  tor_free(poison_path);
  tor_free(dir1);
  tor_free(dir2);
  smartlist_free(services);
  rend_service_free(service_1);
  rend_service_free(service_2);
  UNMOCK(get_options);
  tor_free(mock_options->DataDirectory);
  tor_free(err_msg);
}
Example #23
0
File: test_hs.c Project: ageis/tor
/** Make sure each hidden service descriptor async event generation
 *
 * function generates the message in expected format.
 */
static void
test_hs_desc_event(void *arg)
{
  #define STR_HS_ADDR "ajhb7kljbiru65qo"
  #define STR_HS_CONTENT_DESC_ID "g5ojobzupf275beh5ra72uyhb3dkpxwg"
  #define STR_DESC_ID_BASE32 "hba3gmcgpfivzfhx5rtfqkfdhv65yrj3"

  int ret;
  rend_data_v2_t rend_query;
  const char *expected_msg;
  char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];

  (void) arg;
  MOCK(queue_control_event_string,
       queue_control_event_string_replacement);
  MOCK(node_describe_longname_by_id,
       node_describe_longname_by_id_replacement);

  /* setup rend_query struct */
  memset(&rend_query, 0, sizeof(rend_query));
  rend_query.base_.version = 2;
  strncpy(rend_query.onion_address, STR_HS_ADDR,
          REND_SERVICE_ID_LEN_BASE32+1);
  rend_query.auth_type = REND_NO_AUTH;
  rend_query.base_.hsdirs_fp = smartlist_new();
  smartlist_add(rend_query.base_.hsdirs_fp, tor_memdup(HSDIR_EXIST_ID,
                                                       DIGEST_LEN));

  /* Compute descriptor ID for replica 0, should be STR_DESC_ID_BASE32. */
  ret = rend_compute_v2_desc_id(rend_query.descriptor_id[0],
                                rend_query.onion_address,
                                NULL, 0, 0);
  tt_int_op(ret, OP_EQ, 0);
  base32_encode(desc_id_base32, sizeof(desc_id_base32),
                rend_query.descriptor_id[0], DIGEST_LEN);
  /* Make sure rend_compute_v2_desc_id works properly. */
  tt_mem_op(desc_id_base32, OP_EQ, STR_DESC_ID_BASE32,
            sizeof(desc_id_base32));

  /* test request event */
  control_event_hs_descriptor_requested(rend_query.onion_address,
                                        rend_query.auth_type, HSDIR_EXIST_ID,
                                        STR_DESC_ID_BASE32, NULL);
  expected_msg = "650 HS_DESC REQUESTED "STR_HS_ADDR" NO_AUTH "\
                  STR_HSDIR_EXIST_LONGNAME " " STR_DESC_ID_BASE32 "\r\n";
  tt_assert(received_msg);
  tt_str_op(received_msg,OP_EQ, expected_msg);
  tor_free(received_msg);

  /* test received event */
  rend_query.auth_type = REND_BASIC_AUTH;
  control_event_hsv2_descriptor_received(rend_query.onion_address,
                                         &rend_query.base_, HSDIR_EXIST_ID);
  expected_msg = "650 HS_DESC RECEIVED "STR_HS_ADDR" BASIC_AUTH "\
                  STR_HSDIR_EXIST_LONGNAME " " STR_DESC_ID_BASE32"\r\n";
  tt_assert(received_msg);
  tt_str_op(received_msg,OP_EQ, expected_msg);
  tor_free(received_msg);

  /* test failed event */
  rend_query.auth_type = REND_STEALTH_AUTH;
  control_event_hsv2_descriptor_failed(&rend_query.base_,
                                     HSDIR_NONE_EXIST_ID,
                                     "QUERY_REJECTED");
  expected_msg = "650 HS_DESC FAILED "STR_HS_ADDR" STEALTH_AUTH "\
                  STR_HSDIR_NONE_EXIST_LONGNAME" REASON=QUERY_REJECTED\r\n";
  tt_assert(received_msg);
  tt_str_op(received_msg,OP_EQ, expected_msg);
  tor_free(received_msg);

  /* test invalid auth type */
  rend_query.auth_type = 999;
  control_event_hsv2_descriptor_failed(&rend_query.base_,
                                     HSDIR_EXIST_ID,
                                     "QUERY_REJECTED");
  expected_msg = "650 HS_DESC FAILED "STR_HS_ADDR" UNKNOWN "\
                  STR_HSDIR_EXIST_LONGNAME " " STR_DESC_ID_BASE32\
                  " REASON=QUERY_REJECTED\r\n";
  tt_assert(received_msg);
  tt_str_op(received_msg,OP_EQ, expected_msg);
  tor_free(received_msg);

  /* test no HSDir fingerprint type */
  rend_query.auth_type = REND_NO_AUTH;
  control_event_hsv2_descriptor_failed(&rend_query.base_, NULL,
                                     "QUERY_NO_HSDIR");
  expected_msg = "650 HS_DESC FAILED "STR_HS_ADDR" NO_AUTH " \
                 "UNKNOWN REASON=QUERY_NO_HSDIR\r\n";
  tt_assert(received_msg);
  tt_str_op(received_msg,OP_EQ, expected_msg);
  tor_free(received_msg);

  /* Test invalid content with no HSDir fingerprint. */
  char *exp_msg;
  control_event_hs_descriptor_content(rend_query.onion_address,
                                      STR_HS_CONTENT_DESC_ID, NULL, NULL);
  tor_asprintf(&exp_msg, "650+HS_DESC_CONTENT " STR_HS_ADDR " "\
               STR_HS_CONTENT_DESC_ID " UNKNOWN" \
               "\r\n\r\n.\r\n650 OK\r\n");
  tt_assert(received_msg);
  tt_str_op(received_msg, OP_EQ, exp_msg);
  tor_free(received_msg);
  tor_free(exp_msg);

  /* test valid content. */
  control_event_hs_descriptor_content(rend_query.onion_address,
                                      STR_HS_CONTENT_DESC_ID, HSDIR_EXIST_ID,
                                      hs_desc_content_control);
  tor_asprintf(&exp_msg, "650+HS_DESC_CONTENT " STR_HS_ADDR " "\
               STR_HS_CONTENT_DESC_ID " " STR_HSDIR_EXIST_LONGNAME\
               "\r\n%s\r\n.\r\n650 OK\r\n", hs_desc_content_control);

  tt_assert(received_msg);
  tt_str_op(received_msg, OP_EQ, exp_msg);
  tor_free(received_msg);
  tor_free(exp_msg);
  SMARTLIST_FOREACH(rend_query.base_.hsdirs_fp, char *, d, tor_free(d));
  smartlist_free(rend_query.base_.hsdirs_fp);

 done:
  UNMOCK(queue_control_event_string);
  UNMOCK(node_describe_longname_by_id);
  tor_free(received_msg);
}
Example #24
0
static void
test_md_reject_cache(void *arg)
{
  (void) arg;
  microdesc_cache_t *mc = NULL ;
  smartlist_t *added = NULL, *wanted = smartlist_new();
  or_options_t *options = get_options_mutable();
  char buf[DIGEST256_LEN];

  tor_free(options->DataDirectory);
  options->DataDirectory = tor_strdup(get_fname("md_datadir_test_rej"));
  mock_rgsbd_val_a = tor_malloc_zero(sizeof(routerstatus_t));
  mock_rgsbd_val_b = tor_malloc_zero(sizeof(routerstatus_t));
  mock_ns_val = tor_malloc_zero(sizeof(networkstatus_t));

  mock_ns_val->valid_after = time(NULL) - 86400;
  mock_ns_val->valid_until = time(NULL) + 86400;
  mock_ns_val->flavor = FLAV_MICRODESC;

#ifdef _WIN32
  tt_int_op(0, OP_EQ, mkdir(options->DataDirectory));
#else
  tt_int_op(0, OP_EQ, mkdir(options->DataDirectory, 0700));
#endif

  MOCK(router_get_mutable_consensus_status_by_descriptor_digest,
       mock_router_get_status_by_digest);
  MOCK(networkstatus_get_latest_consensus_by_flavor, mock_ns_get_by_flavor);

  mc = get_microdesc_cache();
#define ADD(hex)                                                        \
  do {                                                                  \
    tt_int_op(0,OP_EQ,base16_decode(buf,sizeof(buf),hex,strlen(hex)));     \
    smartlist_add(wanted, tor_memdup(buf, DIGEST256_LEN));              \
  } while (0)

  /* invalid,0 */
  ADD("5d76bf1c6614e885614a1e0ad074e1ab4ea14655ebeefb1736a71b5ed8a15a51");
  /* invalid,2 */
  ADD("20d1576c5ab11bbcff0dedb1db4a3cfcc8bc8dd839d8cbfef92d00a1a7d7b294");
  /* valid, 6 */
  ADD("53f740bd222ab37f19f604b1d3759aa65eff1fbce9ac254bd0fa50d4af9b1bae");
  /* valid, 8 */
  ADD("a0a155562d8093d8fd0feb7b93b7226e17f056c2142aab7a4ea8c5867a0376d5");

  added = microdescs_add_to_cache(mc, MD_PARSE_TEST_DATA, NULL,
                                  SAVED_NOWHERE, 0, time(NULL), wanted);

  tt_int_op(smartlist_len(added), OP_EQ, 2);
  tt_int_op(mock_rgsbd_called, OP_EQ, 2);
  tt_int_op(mock_rgsbd_val_a->dl_status.n_download_failures, OP_EQ, 255);
  tt_int_op(mock_rgsbd_val_b->dl_status.n_download_failures, OP_EQ, 255);

 done:
  UNMOCK(networkstatus_get_latest_consensus_by_flavor);
  UNMOCK(router_get_mutable_consensus_status_by_descriptor_digest);
  tor_free(options->DataDirectory);
  microdesc_free_all();
  smartlist_free(added);
  SMARTLIST_FOREACH(wanted, char *, cp, tor_free(cp));
  smartlist_free(wanted);
  tor_free(mock_rgsbd_val_a);
  tor_free(mock_rgsbd_val_b);
  tor_free(mock_ns_val);
}
Example #25
0
/** More tests for parsing different kinds of microdescriptors, and getting
 * invalid digests trackd from them. */
static void
test_md_parse(void *arg)
{
  (void) arg;
  char *mem_op_hex_tmp = NULL;
  smartlist_t *invalid = smartlist_new();

  smartlist_t *mds = microdescs_parse_from_string(MD_PARSE_TEST_DATA,
                                                  NULL, 1, SAVED_NOWHERE,
                                                  invalid);
  tt_int_op(smartlist_len(mds), OP_EQ, 11);
  tt_int_op(smartlist_len(invalid), OP_EQ, 4);

  test_memeq_hex(smartlist_get(invalid,0),
                 "5d76bf1c6614e885614a1e0ad074e1ab"
                 "4ea14655ebeefb1736a71b5ed8a15a51");
  test_memeq_hex(smartlist_get(invalid,1),
                 "2fde0ee3343669c2444cd9d53cbd39c6"
                 "a7d1fc0513513e840ca7f6e68864b36c");
  test_memeq_hex(smartlist_get(invalid,2),
                 "20d1576c5ab11bbcff0dedb1db4a3cfc"
                 "c8bc8dd839d8cbfef92d00a1a7d7b294");
  test_memeq_hex(smartlist_get(invalid,3),
                 "074770f394c73dbde7b44412e9692add"
                 "691a478d4727f9804b77646c95420a96");

  /* Spot-check the valid ones. */
  const microdesc_t *md = smartlist_get(mds, 5);
  test_memeq_hex(md->digest,
                 "54bb6d733ddeb375d2456c79ae103961"
                 "da0cae29620375ac4cf13d54da4d92b3");
  tt_int_op(md->last_listed, OP_EQ, 0);
  tt_int_op(md->saved_location, OP_EQ, SAVED_NOWHERE);
  tt_int_op(md->no_save, OP_EQ, 0);
  tt_uint_op(md->held_in_map, OP_EQ, 0);
  tt_uint_op(md->held_by_nodes, OP_EQ, 0);
  tt_assert(md->onion_curve25519_pkey);

  md = smartlist_get(mds, 6);
  test_memeq_hex(md->digest,
                 "53f740bd222ab37f19f604b1d3759aa6"
                 "5eff1fbce9ac254bd0fa50d4af9b1bae");
  tt_assert(! md->exit_policy);

  md = smartlist_get(mds, 8);
  test_memeq_hex(md->digest,
                 "a0a155562d8093d8fd0feb7b93b7226e"
                 "17f056c2142aab7a4ea8c5867a0376d5");
  tt_assert(md->onion_curve25519_pkey);

  md = smartlist_get(mds, 10);
  test_memeq_hex(md->digest,
                 "409ebd87d23925a2732bd467a92813c9"
                 "21ca378fcb9ca193d354c51550b6d5e9");
  tt_assert(tor_addr_family(&md->ipv6_addr) == AF_INET6);
  tt_int_op(md->ipv6_orport, OP_EQ, 9090);

 done:
  SMARTLIST_FOREACH(mds, microdesc_t *, md, microdesc_free(md));
  smartlist_free(mds);
  SMARTLIST_FOREACH(invalid, char *, cp, tor_free(cp));
  smartlist_free(invalid);
  tor_free(mem_op_hex_tmp);
}
Example #26
0
static void
test_md_cache(void *data)
{
  or_options_t *options = NULL;
  microdesc_cache_t *mc = NULL ;
  smartlist_t *added = NULL, *wanted = NULL;
  microdesc_t *md1, *md2, *md3;
  char d1[DIGEST256_LEN], d2[DIGEST256_LEN], d3[DIGEST256_LEN];
  const char *test_md3_noannotation = strchr(test_md3, '\n')+1;
  time_t time1, time2, time3;
  char *fn = NULL, *s = NULL;
  (void)data;

  options = get_options_mutable();
  tt_assert(options);

  time1 = time(NULL);
  time2 = time(NULL) - 2*24*60*60;
  time3 = time(NULL) - 15*24*60*60;

  /* Possibly, turn this into a test setup/cleanup pair */
  tor_free(options->DataDirectory);
  options->DataDirectory = tor_strdup(get_fname("md_datadir_test"));
#ifdef _WIN32
  tt_int_op(0, OP_EQ, mkdir(options->DataDirectory));
#else
  tt_int_op(0, OP_EQ, mkdir(options->DataDirectory, 0700));
#endif

  tt_assert(!strcmpstart(test_md3_noannotation, "onion-key"));

  crypto_digest256(d1, test_md1, strlen(test_md1), DIGEST_SHA256);
  crypto_digest256(d2, test_md2, strlen(test_md1), DIGEST_SHA256);
  crypto_digest256(d3, test_md3_noannotation, strlen(test_md3_noannotation),
                   DIGEST_SHA256);

  mc = get_microdesc_cache();

  added = microdescs_add_to_cache(mc, test_md1, NULL, SAVED_NOWHERE, 0,
                                  time1, NULL);
  tt_int_op(1, OP_EQ, smartlist_len(added));
  md1 = smartlist_get(added, 0);
  smartlist_free(added);
  added = NULL;

  wanted = smartlist_new();
  added = microdescs_add_to_cache(mc, test_md2, NULL, SAVED_NOWHERE, 0,
                                  time2, wanted);
  /* Should fail, since we didn't list test_md2's digest in wanted */
  tt_int_op(0, OP_EQ, smartlist_len(added));
  smartlist_free(added);
  added = NULL;

  smartlist_add(wanted, tor_memdup(d2, DIGEST256_LEN));
  smartlist_add(wanted, tor_memdup(d3, DIGEST256_LEN));
  added = microdescs_add_to_cache(mc, test_md2, NULL, SAVED_NOWHERE, 0,
                                  time2, wanted);
  /* Now it can work. md2 should have been added */
  tt_int_op(1, OP_EQ, smartlist_len(added));
  md2 = smartlist_get(added, 0);
  /* And it should have gotten removed from 'wanted' */
  tt_int_op(smartlist_len(wanted), OP_EQ, 1);
  tt_mem_op(smartlist_get(wanted, 0), OP_EQ, d3, DIGEST256_LEN);
  smartlist_free(added);
  added = NULL;

  added = microdescs_add_to_cache(mc, test_md3, NULL,
                                  SAVED_NOWHERE, 0, -1, NULL);
  /* Must fail, since SAVED_NOWHERE precludes annotations */
  tt_int_op(0, OP_EQ, smartlist_len(added));
  smartlist_free(added);
  added = NULL;

  added = microdescs_add_to_cache(mc, test_md3_noannotation, NULL,
                                  SAVED_NOWHERE, 0, time3, NULL);
  /* Now it can work */
  tt_int_op(1, OP_EQ, smartlist_len(added));
  md3 = smartlist_get(added, 0);
  smartlist_free(added);
  added = NULL;

  /* Okay.  We added 1...3.  Let's poke them to see how they look, and make
   * sure they're really in the journal. */
  tt_ptr_op(md1, OP_EQ, microdesc_cache_lookup_by_digest256(mc, d1));
  tt_ptr_op(md2, OP_EQ, microdesc_cache_lookup_by_digest256(mc, d2));
  tt_ptr_op(md3, OP_EQ, microdesc_cache_lookup_by_digest256(mc, d3));

  tt_int_op(md1->last_listed, OP_EQ, time1);
  tt_int_op(md2->last_listed, OP_EQ, time2);
  tt_int_op(md3->last_listed, OP_EQ, time3);

  tt_int_op(md1->saved_location, OP_EQ, SAVED_IN_JOURNAL);
  tt_int_op(md2->saved_location, OP_EQ, SAVED_IN_JOURNAL);
  tt_int_op(md3->saved_location, OP_EQ, SAVED_IN_JOURNAL);

  tt_int_op(md1->bodylen, OP_EQ, strlen(test_md1));
  tt_int_op(md2->bodylen, OP_EQ, strlen(test_md2));
  tt_int_op(md3->bodylen, OP_EQ, strlen(test_md3_noannotation));
  tt_mem_op(md1->body, OP_EQ, test_md1, strlen(test_md1));
  tt_mem_op(md2->body, OP_EQ, test_md2, strlen(test_md2));
  tt_mem_op(md3->body, OP_EQ, test_md3_noannotation,
              strlen(test_md3_noannotation));

  tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-microdescs.new",
               options->DataDirectory);
  s = read_file_to_str(fn, RFTS_BIN, NULL);
  tt_assert(s);
  tt_mem_op(md1->body, OP_EQ, s + md1->off, md1->bodylen);
  tt_mem_op(md2->body, OP_EQ, s + md2->off, md2->bodylen);
  tt_mem_op(md3->body, OP_EQ, s + md3->off, md3->bodylen);

  tt_ptr_op(md1->family, OP_EQ, NULL);
  tt_ptr_op(md3->family, OP_NE, NULL);
  tt_int_op(smartlist_len(md3->family), OP_EQ, 3);
  tt_str_op(smartlist_get(md3->family, 0), OP_EQ, "nodeX");

  /* Now rebuild the cache! */
  tt_int_op(microdesc_cache_rebuild(mc, 1), OP_EQ, 0);

  tt_int_op(md1->saved_location, OP_EQ, SAVED_IN_CACHE);
  tt_int_op(md2->saved_location, OP_EQ, SAVED_IN_CACHE);
  tt_int_op(md3->saved_location, OP_EQ, SAVED_IN_CACHE);

  /* The journal should be empty now */
  tor_free(s);
  s = read_file_to_str(fn, RFTS_BIN, NULL);
  tt_str_op(s, OP_EQ, "");
  tor_free(s);
  tor_free(fn);

  /* read the cache. */
  tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-microdescs",
               options->DataDirectory);
  s = read_file_to_str(fn, RFTS_BIN, NULL);
  tt_mem_op(md1->body, OP_EQ, s + md1->off, strlen(test_md1));
  tt_mem_op(md2->body, OP_EQ, s + md2->off, strlen(test_md2));
  tt_mem_op(md3->body, OP_EQ, s + md3->off, strlen(test_md3_noannotation));

  /* Okay, now we are going to forget about the cache entirely, and reload it
   * from the disk. */
  microdesc_free_all();
  mc = get_microdesc_cache();
  md1 = microdesc_cache_lookup_by_digest256(mc, d1);
  md2 = microdesc_cache_lookup_by_digest256(mc, d2);
  md3 = microdesc_cache_lookup_by_digest256(mc, d3);
  tt_assert(md1);
  tt_assert(md2);
  tt_assert(md3);
  tt_mem_op(md1->body, OP_EQ, s + md1->off, strlen(test_md1));
  tt_mem_op(md2->body, OP_EQ, s + md2->off, strlen(test_md2));
  tt_mem_op(md3->body, OP_EQ, s + md3->off, strlen(test_md3_noannotation));

  tt_int_op(md1->last_listed, OP_EQ, time1);
  tt_int_op(md2->last_listed, OP_EQ, time2);
  tt_int_op(md3->last_listed, OP_EQ, time3);

  /* Okay, now we are going to clear out everything older than a week old.
   * In practice, that means md3 */
  microdesc_cache_clean(mc, time(NULL)-7*24*60*60, 1/*force*/);
  tt_ptr_op(md1, OP_EQ, microdesc_cache_lookup_by_digest256(mc, d1));
  tt_ptr_op(md2, OP_EQ, microdesc_cache_lookup_by_digest256(mc, d2));
  tt_ptr_op(NULL, OP_EQ, microdesc_cache_lookup_by_digest256(mc, d3));
  md3 = NULL; /* it's history now! */

  /* rebuild again, make sure it stays gone. */
  tt_int_op(microdesc_cache_rebuild(mc, 1), OP_EQ, 0);
  tt_ptr_op(md1, OP_EQ, microdesc_cache_lookup_by_digest256(mc, d1));
  tt_ptr_op(md2, OP_EQ, microdesc_cache_lookup_by_digest256(mc, d2));
  tt_ptr_op(NULL, OP_EQ, microdesc_cache_lookup_by_digest256(mc, d3));

  /* Re-add md3, and make sure we can rebuild the cache. */
  added = microdescs_add_to_cache(mc, test_md3_noannotation, NULL,
                                  SAVED_NOWHERE, 0, time3, NULL);
  tt_int_op(1, OP_EQ, smartlist_len(added));
  md3 = smartlist_get(added, 0);
  smartlist_free(added);
  added = NULL;
  tt_int_op(md1->saved_location, OP_EQ, SAVED_IN_CACHE);
  tt_int_op(md2->saved_location, OP_EQ, SAVED_IN_CACHE);
  tt_int_op(md3->saved_location, OP_EQ, SAVED_IN_JOURNAL);

  tt_int_op(microdesc_cache_rebuild(mc, 1), OP_EQ, 0);
  tt_int_op(md3->saved_location, OP_EQ, SAVED_IN_CACHE);

 done:
  if (options)
    tor_free(options->DataDirectory);
  microdesc_free_all();

  smartlist_free(added);
  if (wanted)
    SMARTLIST_FOREACH(wanted, char *, cp, tor_free(cp));
  smartlist_free(wanted);
  tor_free(s);
  tor_free(fn);
}
Example #27
0
static void
test_address_ip_adapter_addresses_to_smartlist(void *arg)
{

  IP_ADAPTER_ADDRESSES *addrs1;
  IP_ADAPTER_ADDRESSES *addrs2;

  IP_ADAPTER_UNICAST_ADDRESS *unicast11;
  IP_ADAPTER_UNICAST_ADDRESS *unicast12;
  IP_ADAPTER_UNICAST_ADDRESS *unicast21;

  smartlist_t *result = NULL;

  struct sockaddr_in *sockaddr_test1;
  struct sockaddr_in *sockaddr_test2;
  struct sockaddr_in *sockaddr_localhost;
  struct sockaddr_in *sockaddr_to_check;

  tor_addr_t *tor_addr;

  (void)arg;
  (void)sockaddr_in6_are_equal;

  sockaddr_to_check = tor_malloc_zero(sizeof(struct sockaddr_in));

  addrs1 =
  tor_malloc_zero(sizeof(IP_ADAPTER_ADDRESSES));

  addrs1->FirstUnicastAddress =
  unicast11 = tor_malloc_zero(sizeof(IP_ADAPTER_UNICAST_ADDRESS));
  sockaddr_test1 = sockaddr_in_from_string("86.59.30.40",NULL);
  unicast11->Address.lpSockaddr = (LPSOCKADDR)sockaddr_test1;

  unicast11->Next = unicast12 =
  tor_malloc_zero(sizeof(IP_ADAPTER_UNICAST_ADDRESS));
  sockaddr_test2 = sockaddr_in_from_string("93.95.227.222", NULL);
  unicast12->Address.lpSockaddr = (LPSOCKADDR)sockaddr_test2;

  addrs1->Next = addrs2 =
  tor_malloc_zero(sizeof(IP_ADAPTER_ADDRESSES));

  addrs2->FirstUnicastAddress =
  unicast21 = tor_malloc_zero(sizeof(IP_ADAPTER_UNICAST_ADDRESS));
  sockaddr_localhost = sockaddr_in_from_string("127.0.0.1", NULL);
  unicast21->Address.lpSockaddr = (LPSOCKADDR)sockaddr_localhost;

  result = ip_adapter_addresses_to_smartlist(addrs1);

  tt_assert(result);
  tt_int_op(smartlist_len(result), OP_EQ, 3);

  tor_addr = smartlist_get(result,0);

  tor_addr_to_sockaddr(tor_addr,0,(struct sockaddr *)sockaddr_to_check,
                       sizeof(struct sockaddr_in));

  tt_assert(sockaddr_in_are_equal(sockaddr_test1,sockaddr_to_check));

  tor_addr = smartlist_get(result,1);

  tor_addr_to_sockaddr(tor_addr,0,(struct sockaddr *)sockaddr_to_check,
                       sizeof(struct sockaddr_in));

  tt_assert(sockaddr_in_are_equal(sockaddr_test2,sockaddr_to_check));

  tor_addr = smartlist_get(result,2);

  tor_addr_to_sockaddr(tor_addr,0,(struct sockaddr *)sockaddr_to_check,
                       sizeof(struct sockaddr_in));

  tt_assert(sockaddr_in_are_equal(sockaddr_localhost,sockaddr_to_check));

  done:
  SMARTLIST_FOREACH(result, tor_addr_t *, t, tor_free(t));
  smartlist_free(result);
  tor_free(addrs1);
  tor_free(addrs2);
  tor_free(unicast11->Address.lpSockaddr);
  tor_free(unicast11);
  tor_free(unicast12->Address.lpSockaddr);
  tor_free(unicast12);
  tor_free(unicast21->Address.lpSockaddr);
  tor_free(unicast21);
  tor_free(sockaddr_to_check);
  return;
}
Example #28
0
/** Configure accounting start/end time settings based on
 * options->AccountingStart.  Return 0 on success, -1 on failure. If
 * <b>validate_only</b> is true, do not change the current settings. */
int
accounting_parse_options(const or_options_t *options, int validate_only)
{
  time_unit_t unit;
  int ok, idx;
  long d,h,m;
  smartlist_t *items;
  const char *v = options->AccountingStart;
  const char *s;
  char *cp;

  if (!v) {
    if (!validate_only) {
      cfg_unit = UNIT_MONTH;
      cfg_start_day = 1;
      cfg_start_hour = 0;
      cfg_start_min = 0;
    }
    return 0;
  }

  items = smartlist_new();
  smartlist_split_string(items, v, NULL,
                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK,0);
  if (smartlist_len(items)<2) {
    log_warn(LD_CONFIG, "Too few arguments to AccountingStart");
    goto err;
  }
  s = smartlist_get(items,0);
  if (0==strcasecmp(s, "month")) {
    unit = UNIT_MONTH;
  } else if (0==strcasecmp(s, "week")) {
    unit = UNIT_WEEK;
  } else if (0==strcasecmp(s, "day")) {
    unit = UNIT_DAY;
  } else {
    log_warn(LD_CONFIG,
             "Unrecognized accounting unit '%s': only 'month', 'week',"
             " and 'day' are supported.", s);
    goto err;
  }

  switch (unit) {
  case UNIT_WEEK:
    d = tor_parse_long(smartlist_get(items,1), 10, 1, 7, &ok, NULL);
    if (!ok) {
      log_warn(LD_CONFIG, "Weekly accounting must begin on a day between "
               "1 (Monday) and 7 (Sunday)");
      goto err;
    }
    break;
  case UNIT_MONTH:
    d = tor_parse_long(smartlist_get(items,1), 10, 1, 28, &ok, NULL);
    if (!ok) {
      log_warn(LD_CONFIG, "Monthly accounting must begin on a day between "
               "1 and 28");
      goto err;
    }
    break;
  case UNIT_DAY:
    d = 0;
    break;
    /* Coverity dislikes unreachable default cases; some compilers warn on
     * switch statements missing a case.  Tell Coverity not to worry. */
    /* coverity[dead_error_begin] */
  default:
    tor_assert(0);
  }

  idx = unit==UNIT_DAY?1:2;
  if (smartlist_len(items) != (idx+1)) {
    log_warn(LD_CONFIG,"Accounting unit '%s' requires %d argument%s.",
             s, idx, (idx>1)?"s":"");
    goto err;
  }
  s = smartlist_get(items, idx);
  h = tor_parse_long(s, 10, 0, 23, &ok, &cp);
  if (!ok) {
    log_warn(LD_CONFIG,"Accounting start time not parseable: bad hour.");
    goto err;
  }
  if (!cp || *cp!=':') {
    log_warn(LD_CONFIG,
             "Accounting start time not parseable: not in HH:MM format");
    goto err;
  }
  m = tor_parse_long(cp+1, 10, 0, 59, &ok, &cp);
  if (!ok) {
    log_warn(LD_CONFIG, "Accounting start time not parseable: bad minute");
    goto err;
  }
  if (!cp || *cp!='\0') {
    log_warn(LD_CONFIG,
             "Accounting start time not parseable: not in HH:MM format");
    goto err;
  }

  if (!validate_only) {
    cfg_unit = unit;
    cfg_start_day = (int)d;
    cfg_start_hour = (int)h;
    cfg_start_min = (int)m;
  }
  SMARTLIST_FOREACH(items, char *, item, tor_free(item));
  smartlist_free(items);
  return 0;
 err:
  SMARTLIST_FOREACH(items, char *, item, tor_free(item));
  smartlist_free(items);
  return -1;
}
Example #29
0
static void
test_address_ifreq_to_smartlist(void *arg)
{
  smartlist_t *results = NULL;
  const tor_addr_t *tor_addr = NULL;
  struct sockaddr_in *sockaddr = NULL;
  struct sockaddr_in *sockaddr_eth1 = NULL;
  struct sockaddr_in *sockaddr_to_check = NULL;

  struct ifconf *ifc;
  struct ifreq *ifr;
  struct ifreq *ifr_next;

  socklen_t addr_len;

  (void)arg;

  sockaddr_to_check = tor_malloc(sizeof(struct sockaddr_in));

  ifr = tor_malloc(sizeof(struct ifreq));
  memset(ifr,0,sizeof(struct ifreq));
  strlcpy(ifr->ifr_name,"lo",3);
  sockaddr = (struct sockaddr_in *) &(ifr->ifr_ifru.ifru_addr);
  sockaddr_in_from_string("127.0.0.1",sockaddr);

  ifc = tor_malloc(sizeof(struct ifconf));
  memset(ifc,0,sizeof(struct ifconf));
  ifc->ifc_len = sizeof(struct ifreq);
  ifc->ifc_ifcu.ifcu_req = ifr;

  results = ifreq_to_smartlist(ifc->ifc_buf,ifc->ifc_len);
  tt_int_op(smartlist_len(results),OP_EQ,1);

  tor_addr = smartlist_get(results, 0);
  addr_len =
  tor_addr_to_sockaddr(tor_addr,0,(struct sockaddr *)sockaddr_to_check,
                       sizeof(struct sockaddr_in));

  tt_int_op(addr_len,OP_EQ,sizeof(struct sockaddr_in));
  tt_assert(sockaddr_in_are_equal(sockaddr,sockaddr_to_check));

  ifr = tor_realloc(ifr,2*sizeof(struct ifreq));
  ifr_next = ifr+1;
  strlcpy(ifr_next->ifr_name,"eth1",5);
  ifc->ifc_len = 2*sizeof(struct ifreq);
  ifc->ifc_ifcu.ifcu_req = ifr;
  sockaddr = (struct sockaddr_in *) &(ifr->ifr_ifru.ifru_addr);

  sockaddr_eth1 = (struct sockaddr_in *) &(ifr_next->ifr_ifru.ifru_addr);
  sockaddr_in_from_string("192.168.10.55",sockaddr_eth1);
  SMARTLIST_FOREACH(results, tor_addr_t *, t, tor_free(t));
  smartlist_free(results);

  results = ifreq_to_smartlist(ifc->ifc_buf,ifc->ifc_len);
  tt_int_op(smartlist_len(results),OP_EQ,2);

  tor_addr = smartlist_get(results, 0);
  addr_len =
  tor_addr_to_sockaddr(tor_addr,0,(struct sockaddr *)sockaddr_to_check,
                       sizeof(struct sockaddr_in));

  tt_int_op(addr_len,OP_EQ,sizeof(struct sockaddr_in));
  tt_assert(sockaddr_in_are_equal(sockaddr,sockaddr_to_check));

  tor_addr = smartlist_get(results, 1);
  addr_len =
  tor_addr_to_sockaddr(tor_addr,0,(struct sockaddr *)sockaddr_to_check,
                       sizeof(struct sockaddr_in));

  tt_int_op(addr_len,OP_EQ,sizeof(struct sockaddr_in));
  tt_assert(sockaddr_in_are_equal(sockaddr_eth1,sockaddr_to_check));

  done:
  tor_free(sockaddr_to_check);
  SMARTLIST_FOREACH(results, tor_addr_t *, t, tor_free(t));
  smartlist_free(results);
  tor_free(ifc);
  tor_free(ifr);
  return;
}
Example #30
0
File: geoip.c Project: majek/tor
/** Clear appropriate GeoIP database, based on <b>family</b>, and
 * reload it from the file <b>filename</b>. Return 0 on success, -1 on
 * failure.
 *
 * Recognized line formats for IPv4 are:
 *   INTIPLOW,INTIPHIGH,CC
 * and
 *   "INTIPLOW","INTIPHIGH","CC","CC3","COUNTRY NAME"
 * where INTIPLOW and INTIPHIGH are IPv4 addresses encoded as 4-byte unsigned
 * integers, and CC is a country code.
 *
 * Recognized line format for IPv6 is:
 *   IPV6LOW,IPV6HIGH,CC
 * where IPV6LOW and IPV6HIGH are IPv6 addresses and CC is a country code.
 *
 * It also recognizes, and skips over, blank lines and lines that start
 * with '#' (comments).
 */
int
geoip_load_file(sa_family_t family, const char *filename)
{
  FILE *f;
  const char *msg = "";
  const or_options_t *options = get_options();
  int severity = options_need_geoip_info(options, &msg) ? LOG_WARN : LOG_INFO;
  crypto_digest_t *geoip_digest_env = NULL;

  tor_assert(family == AF_INET || family == AF_INET6);

  if (!(f = tor_fopen_cloexec(filename, "r"))) {
    log_fn(severity, LD_GENERAL, "Failed to open GEOIP file %s.  %s",
           filename, msg);
    return -1;
  }
  if (!geoip_countries)
    init_geoip_countries();

  if (family == AF_INET) {
    if (geoip_ipv4_entries) {
      SMARTLIST_FOREACH(geoip_ipv4_entries, geoip_ipv4_entry_t *, e,
                        tor_free(e));
      smartlist_free(geoip_ipv4_entries);
    }
    geoip_ipv4_entries = smartlist_new();
  } else { /* AF_INET6 */
    if (geoip_ipv6_entries) {
      SMARTLIST_FOREACH(geoip_ipv6_entries, geoip_ipv6_entry_t *, e,
                        tor_free(e));
      smartlist_free(geoip_ipv6_entries);
    }
    geoip_ipv6_entries = smartlist_new();
  }
  geoip_digest_env = crypto_digest_new();

  log_notice(LD_GENERAL, "Parsing GEOIP %s file %s.",
             (family == AF_INET) ? "IPv4" : "IPv6", filename);
  while (!feof(f)) {
    char buf[512];
    if (fgets(buf, (int)sizeof(buf), f) == NULL)
      break;
    crypto_digest_add_bytes(geoip_digest_env, buf, strlen(buf));
    /* FFFF track full country name. */
    geoip_parse_entry(buf, family);
  }
  /*XXXX abort and return -1 if no entries/illformed?*/
  fclose(f);

  /* Sort list and remember file digests so that we can include it in
   * our extra-info descriptors. */
  if (family == AF_INET) {
    smartlist_sort(geoip_ipv4_entries, geoip_ipv4_compare_entries_);
    /* Okay, now we need to maybe change our mind about what is in
     * which country. We do this for IPv4 only since that's what we
     * store in node->country. */
    refresh_all_country_info();
    crypto_digest_get_digest(geoip_digest_env, geoip_digest, DIGEST_LEN);
  } else {
    /* AF_INET6 */
    smartlist_sort(geoip_ipv6_entries, geoip_ipv6_compare_entries_);
    crypto_digest_get_digest(geoip_digest_env, geoip6_digest, DIGEST_LEN);
  }
  crypto_digest_free(geoip_digest_env);

  return 0;
}