Beispiel #1
0
/** Run unit tests for concatenate-a-smartlist-of-strings functions. */
static void
test_container_smartlist_join(void)
{
  smartlist_t *sl = smartlist_new();
  smartlist_t *sl2 = smartlist_new(), *sl3 = smartlist_new(),
    *sl4 = smartlist_new();
  char *joined=NULL;
  /* unique, sorted. */
  smartlist_split_string(sl,
                         "Abashments Ambush Anchorman Bacon Banks Borscht "
                         "Bunks Inhumane Insurance Knish Know Manners "
                         "Maraschinos Stamina Sunbonnets Unicorns Wombats",
                         " ", 0, 0);
  /* non-unique, sorted. */
  smartlist_split_string(sl2,
                         "Ambush Anchorman Anchorman Anemias Anemias Bacon "
                         "Crossbowmen Inhumane Insurance Knish Know Manners "
                         "Manners Maraschinos Wombats Wombats Work",
                         " ", 0, 0);
  SMARTLIST_FOREACH_JOIN(sl, char *, cp1,
                         sl2, char *, cp2,
                         strcmp(cp1,cp2),
                         smartlist_add(sl3, cp2)) {
    test_streq(cp1, cp2);
    smartlist_add(sl4, cp1);
  } SMARTLIST_FOREACH_JOIN_END(cp1, cp2);
Beispiel #2
0
/**
   Launch all server listeners that tor wants us to launch.
*/
static int
launch_server_listeners(const managed_proxy_t *proxy)
{
  int ret=-1;
  int i, n_transports;
  const char *transport = NULL;
  const char *bindaddr_temp = NULL;
  const char *bindaddr = NULL;
  config_t *cfg = NULL;

  /* list of transports */
  smartlist_t *transports = smartlist_create();
  /* a list of "<transport>-<bindaddr>" strings */
  smartlist_t *bindaddrs = smartlist_create();

  /* split the comma-separated transports/bindaddrs to their smartlists */
  smartlist_split_string(transports, proxy->vars.transports, ",",
                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
  smartlist_split_string(bindaddrs, proxy->vars.bindaddrs, ",",
                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);

  n_transports = smartlist_len(transports);

  /* Iterate transports; match them with their bindaddr; create their
     config_t. */
  for (i=0;i<n_transports;i++) {
    transport = smartlist_get(transports, i);
    bindaddr_temp = smartlist_get(bindaddrs, i);

    obfs_assert(strlen(bindaddr_temp) > strlen(transport)+1);

    bindaddr = bindaddr_temp+strlen(transport)+1; /* +1 for the dash */

    cfg = config_create_managed(proxy->is_server,
                                transport, bindaddr, proxy->vars.or_port);
    if (cfg) /* if a config was created; put it in the config smartlist */
      smartlist_add(proxy->configs, cfg);
    else /* otherwise, spit a method error line */
      print_method_error_line(transport, proxy, ST_LAUNCH_FAIL_SETUP);
  }

  /* open listeners */
  ret = open_listeners_managed(proxy);

  SMARTLIST_FOREACH(bindaddrs, char *, cp, free(cp));
  smartlist_free(bindaddrs);
  SMARTLIST_FOREACH(transports, char *, cp, free(cp));
  smartlist_free(transports);

  print_method_done_line(proxy); /* print {C,S}METHODS DONE */

  return ret;
}
Beispiel #3
0
/** Return the config line for transport <b>transport</b> in the current state.
 *  Return NULL if there is no config line for <b>transport</b>. */
static config_line_t *
get_transport_in_state_by_name(const char *transport)
{
  or_state_t *or_state = get_or_state();
  config_line_t *line;
  config_line_t *ret = NULL;
  smartlist_t *items = NULL;

  for (line = or_state->TransportProxies ; line ; line = line->next) {
    tor_assert(!strcmp(line->key, "TransportProxy"));

    items = smartlist_new();
    smartlist_split_string(items, line->value, NULL,
                           SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
    if (smartlist_len(items) != 2) /* broken state */
      goto done;

    if (!strcmp(smartlist_get(items, 0), transport)) {
      ret = line;
      goto done;
    }

    SMARTLIST_FOREACH(items, char*, s, tor_free(s));
    smartlist_free(items);
    items = NULL;
  }

 done:
  if (items) {
    SMARTLIST_FOREACH(items, char*, s, tor_free(s));
    smartlist_free(items);
  }
  return ret;
}
Beispiel #4
0
/** Parse a log severity pattern in *<b>cfg_ptr</b>.  Advance cfg_ptr after
 * the end of the severityPattern.  Set the value of <b>severity_out</b> to
 * the parsed pattern.  Return 0 on success, -1 on failure.
 *
 * The syntax for a SeverityPattern is:
 * <pre>
 *   SeverityPattern = *(DomainSeverity SP)* DomainSeverity
 *   DomainSeverity = (DomainList SP)? SeverityRange
 *   SeverityRange = MinSeverity ("-" MaxSeverity )?
 *   DomainList = "[" (SP? DomainSpec SP? ",") SP? DomainSpec "]"
 *   DomainSpec = "*" | Domain | "~" Domain
 * </pre>
 * A missing MaxSeverity defaults to ERR.  Severities and domains are
 * case-insensitive.  "~" indicates negation for a domain; negation happens
 * last inside a DomainList.  Only one SeverityRange without a DomainList is
 * allowed per line.
 */
int
parse_log_severity_config(const char **cfg_ptr,
                          log_severity_list_t *severity_out)
{
  const char *cfg = *cfg_ptr;
  int got_anything = 0;
  int got_an_unqualified_range = 0;
  memset(severity_out, 0, sizeof(*severity_out));

  cfg = eat_whitespace(cfg);
  while (*cfg) {
    const char *dash, *space;
    char *sev_lo, *sev_hi;
    int low, high, i;
    log_domain_mask_t domains = ~0u;

    if (*cfg == '[') {
      int err = 0;
      char *domains_str;
      smartlist_t *domains_list;
      log_domain_mask_t neg_domains = 0;
      const char *closebracket = strchr(cfg, ']');
      if (!closebracket)
        return -1;
      domains = 0;
      domains_str = tor_strndup(cfg+1, closebracket-cfg-1);
      domains_list = smartlist_create();
      smartlist_split_string(domains_list, domains_str, ",", SPLIT_SKIP_SPACE,
                             -1);
      tor_free(domains_str);
      SMARTLIST_FOREACH(domains_list, const char *, domain,
          {
            if (!strcmp(domain, "*")) {
              domains = ~0u;
            } else {
              int d;
              int negate=0;
              if (*domain == '~') {
                negate = 1;
                ++domain;
              }
              d = parse_log_domain(domain);
              if (!d) {
                log_warn(LD_CONFIG, "No such logging domain as %s", domain);
                err = 1;
              } else {
                if (negate)
                  neg_domains |= d;
                else
                  domains |= d;
              }
            }
          });
      SMARTLIST_FOREACH(domains_list, char *, d, tor_free(d));
      smartlist_free(domains_list);
      if (err)
        return -1;
      domains &= ~neg_domains;
      cfg = eat_whitespace(closebracket+1);
    } else {
Beispiel #5
0
/* Parse a share random value line from the disk state and save it to dst
 * which is an allocated srv object. Return 0 on success else -1. */
static int
disk_state_parse_srv(const char *value, sr_srv_t *dst)
{
  int ret = -1;
  smartlist_t *args;
  sr_srv_t *srv;

  tor_assert(value);
  tor_assert(dst);

  args = smartlist_new();
  smartlist_split_string(args, value, " ",
                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
  if (smartlist_len(args) < 2) {
    log_warn(LD_BUG, "SR: Too few arguments in shared random value. "
             "Line: %s", escaped(value));
    goto error;
  }
  srv = sr_parse_srv(args);
  if (srv == NULL) {
    goto error;
  }
  dst->num_reveals = srv->num_reveals;
  memcpy(dst->value, srv->value, sizeof(dst->value));
  tor_free(srv);
  ret = 0;

 error:
  SMARTLIST_FOREACH(args, char *, s, tor_free(s));
  smartlist_free(args);
  return ret;
}
Beispiel #6
0
/**
   Finish the configuration protocol version negotiation by printing
   whether we support any of the suggested configuration protocols in
   stdout, according to the 180 spec.

   Return:
   * 0: if we actually found and selected a protocol.
   * -1: if we couldn't find a common supported protocol or if we
     couldn't even parse tor's supported protocol list.

   XXX: in the future we should return the protocol version we
   selected. let's keep it simple for now since we have just one
   protocol version.
*/
static int
conf_proto_version_negotiation(const managed_proxy_t *proxy)
{
  int r=-1;

  smartlist_t *versions = smartlist_create();
  smartlist_split_string(versions, proxy->vars.conf_proto_version, ",",
                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);

  SMARTLIST_FOREACH_BEGIN(versions, char *, version) {
    if (is_supported_conf_protocol(version)) {
      print_protocol_line("%s %s\n", PROTO_NEG_SUCCESS, version);
      r=0;
      goto done;
    }
  } SMARTLIST_FOREACH_END(version);

  /* we get here if we couldn't find a supported protocol */
  print_protocol_line("%s", PROTO_NEG_FAIL);

 done:
  SMARTLIST_FOREACH(versions, char *, cp, free(cp));
  smartlist_free(versions);

  return r;
}
Beispiel #7
0
/** See dir_common_construct_vote_1.
 * Produces a vote with slightly different values.
 */
int
dir_common_construct_vote_2(networkstatus_t **vote, authority_cert_t *cert,
                        crypto_pk_t *sign_skey,
                        vote_routerstatus_t * (*vrs_gen)(int idx, time_t now),
                        networkstatus_t **vote_out, int *n_vrs,
                        time_t now, int clear_rl)
{
  networkstatus_voter_info_t *voter;

  dir_common_setup_vote(vote, now);
  (*vote)->type = NS_TYPE_VOTE;
  (*vote)->published += 1;
  (*vote)->valid_after = now+1000;
  (*vote)->fresh_until = now+3005;
  (*vote)->valid_until = now+3000;
  (*vote)->vote_seconds = 100;
  (*vote)->dist_seconds = 300;
  smartlist_split_string((*vote)->supported_methods, "1 2 3", NULL, 0, -1);
  smartlist_split_string((*vote)->known_flags,
                         "Authority Exit Fast Guard MadeOfCheese MadeOfTin "
                         "Running Stable V2Dir Valid", 0,
                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
  voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
  voter->nickname = tor_strdup("Voter2");
  voter->address = tor_strdup("2.3.4.5");
  voter->addr = 0x02030405;
  voter->dir_port = 80;
  voter->or_port = 9000;
  voter->contact = tor_strdup("*****@*****.**");
  crypto_pk_get_digest(cert->identity_key, voter->identity_digest);
  /*
   * Set up a vote; generate it; try to parse it.
   */
  smartlist_add((*vote)->voters, voter);
  (*vote)->cert = authority_cert_dup(cert);
  if (! (*vote)->net_params)
    (*vote)->net_params = smartlist_new();
  smartlist_split_string((*vote)->net_params,
                         "bar=2000000000 circuitwindow=20",
                         NULL, 0, 0);
  /* add routerstatuses */
  /* dump the vote and try to parse it. */
  dir_common_add_rs_and_parse(*vote, vote_out, vrs_gen, sign_skey,
                              n_vrs, now, clear_rl);

  return 0;
}
Beispiel #8
0
int
fuzz_init(void)
{
  disable_signature_checking();
  MOCK(dump_desc, mock_dump_desc__nodump);
  ed25519_init();
  area = memarea_new();
  dummy_vote = tor_malloc_zero(sizeof(*dummy_vote));
  dummy_vote->known_flags = smartlist_new();
  smartlist_split_string(dummy_vote->known_flags,
                         DIRVOTE_UNIVERSAL_FLAGS,
                         " ", 0, 0);
  smartlist_split_string(dummy_vote->known_flags,
                         DIRVOTE_OPTIONAL_FLAGS,
                         " ", 0, 0);
  smartlist_sort_strings(dummy_vote->known_flags);
  return 0;
}
Beispiel #9
0
/** See dir_common_construct_vote_1.
 * Produces a vote with slightly different values. Adds a legacy key.
 */
int
dir_common_construct_vote_3(networkstatus_t **vote, authority_cert_t *cert,
                        crypto_pk_t *sign_skey,
                        vote_routerstatus_t * (*vrs_gen)(int idx, time_t now),
                        networkstatus_t **vote_out, int *n_vrs,
                        time_t now, int clear_rl)
{
  networkstatus_voter_info_t *voter;

  dir_common_setup_vote(vote, now);
  (*vote)->valid_after = now+1000;
  (*vote)->fresh_until = now+2003;
  (*vote)->valid_until = now+3000;
  (*vote)->vote_seconds = 100;
  (*vote)->dist_seconds = 250;
  smartlist_split_string((*vote)->supported_methods, "1 2 3 4", NULL, 0, -1);
  (*vote)->client_versions = tor_strdup("0.1.2.14,0.1.2.17");
  (*vote)->server_versions = tor_strdup("0.1.2.10,0.1.2.15,0.1.2.16");
  smartlist_split_string((*vote)->known_flags,
                     "Authority Exit Fast Guard Running Stable V2Dir Valid",
                     0, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
  voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
  voter->nickname = tor_strdup("Voter2");
  voter->address = tor_strdup("3.4.5.6");
  voter->addr = 0x03040506;
  voter->dir_port = 80;
  voter->or_port = 9000;
  voter->contact = tor_strdup("*****@*****.**");
  crypto_pk_get_digest(cert->identity_key, voter->identity_digest);
  memset(voter->legacy_id_digest, (int)'A', DIGEST_LEN);
  /*
   * Set up a vote; generate it; try to parse it.
   */
  smartlist_add((*vote)->voters, voter);
  (*vote)->cert = authority_cert_dup(cert);
  smartlist_split_string((*vote)->net_params, "circuitwindow=80 foo=660",
                         NULL, 0, 0);
  /* add routerstatuses */
  /* dump the vote and try to parse it. */
  dir_common_add_rs_and_parse(*vote, vote_out, vrs_gen, sign_skey,
                              n_vrs, now, clear_rl);

  return 0;
}
Beispiel #10
0
static void
test_container_smartlist_most_frequent(void *arg)
{
  (void) arg;
  smartlist_t *sl = smartlist_new();

  int count = -1;
  const char *cp;

  cp = smartlist_get_most_frequent_string_(sl, &count);
  tt_int_op(count, ==, 0);
  tt_ptr_op(cp, ==, NULL);

  /* String must be sorted before we call get_most_frequent */
  smartlist_split_string(sl, "abc:def:ghi", ":", 0, 0);

  cp = smartlist_get_most_frequent_string_(sl, &count);
  tt_int_op(count, ==, 1);
  tt_str_op(cp, ==, "ghi"); /* Ties broken in favor of later element */

  smartlist_split_string(sl, "def:ghi", ":", 0, 0);
  smartlist_sort_strings(sl);

  cp = smartlist_get_most_frequent_string_(sl, &count);
  tt_int_op(count, ==, 2);
  tt_ptr_op(cp, !=, NULL);
  tt_str_op(cp, ==, "ghi"); /* Ties broken in favor of later element */

  smartlist_split_string(sl, "def:abc:qwop", ":", 0, 0);
  smartlist_sort_strings(sl);

  cp = smartlist_get_most_frequent_string_(sl, &count);
  tt_int_op(count, ==, 3);
  tt_ptr_op(cp, !=, NULL);
  tt_str_op(cp, ==, "def"); /* No tie */

 done:
  SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
  smartlist_free(sl);
}
Beispiel #11
0
/* Parse the Commit line(s) in the disk state and translate them to the
 * the memory state. Return 0 on success else -1 on error. */
static int
disk_state_parse_commits(sr_state_t *state,
                         const sr_disk_state_t *disk_state)
{
  config_line_t *line;
  smartlist_t *args = NULL;

  tor_assert(state);
  tor_assert(disk_state);

  for (line = disk_state->Commit; line; line = line->next) {
    sr_commit_t *commit = NULL;

    /* Extra safety. */
    if (strcasecmp(line->key, dstate_commit_key) ||
        line->value == NULL) {
      /* Ignore any lines that are not commits. */
      tor_fragile_assert();
      continue;
    }
    args = smartlist_new();
    smartlist_split_string(args, line->value, " ",
                           SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
    if (smartlist_len(args) < 3) {
      log_warn(LD_BUG, "SR: Too few arguments in Commit Line: %s",
               escaped(line->value));
      goto error;
    }
    commit = sr_parse_commit(args);
    if (commit == NULL) {
      /* Ignore badly formed commit. It could also be a authority
       * fingerprint that we don't know about so it shouldn't be used. */
      smartlist_free(args);
      continue;
    }
    /* We consider parseable commit from our disk state to be valid because
     * they need to be in the first place to get in there. */
    commit->valid = 1;
    /* Add commit to our state pointer. */
    commit_add_to_state(commit, state);

    SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
    smartlist_free(args);
  }

  return 0;

 error:
  SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
  smartlist_free(args);
  return -1;
}
Beispiel #12
0
/** Parse the string <b>s</b> to create a set of routerset entries, and add
 * them to <b>target</b>.  In log messages, refer to the string as
 * <b>description</b>.  Return 0 on success, -1 on failure.
 *
 * Three kinds of elements are allowed in routersets: nicknames, IP address
 * patterns, and fingerprints.  They may be surrounded by optional space, and
 * must be separated by commas.
 */
int
routerset_parse(routerset_t *target, const char *s, const char *description)
{
  int r = 0;
  int added_countries = 0;
  char *countryname;
  smartlist_t *list = smartlist_new();
  int malformed_list;
  smartlist_split_string(list, s, ",",
                         SPLIT_SKIP_SPACE | SPLIT_IGNORE_BLANK, 0);
  SMARTLIST_FOREACH_BEGIN(list, char *, nick) {
      addr_policy_t *p;
      /* if it doesn't pass our validation, assume it's malformed */
      malformed_list = 1;
      if (is_legal_hexdigest(nick)) {
        char d[DIGEST_LEN];
        if (*nick == '$')
          ++nick;
        log_debug(LD_CONFIG, "Adding identity %s to %s", nick, description);
        base16_decode(d, sizeof(d), nick, HEX_DIGEST_LEN);
        digestmap_set(target->digests, d, (void*)1);
      } else if (is_legal_nickname(nick)) {
        log_debug(LD_CONFIG, "Adding nickname %s to %s", nick, description);
        strmap_set_lc(target->names, nick, (void*)1);
      } else if ((countryname = routerset_get_countryname(nick)) != NULL) {
        log_debug(LD_CONFIG, "Adding country %s to %s", nick,
                  description);
        smartlist_add(target->country_names, countryname);
        added_countries = 1;
      } else if ((strchr(nick,'.') || strchr(nick, ':') ||  strchr(nick, '*'))
                 && (p = router_parse_addr_policy_item_from_string(
                                     nick, ADDR_POLICY_REJECT,
                                     &malformed_list))) {
        /* IPv4 addresses contain '.', IPv6 addresses contain ':',
         * and wildcard addresses contain '*'. */
        log_debug(LD_CONFIG, "Adding address %s to %s", nick, description);
        smartlist_add(target->policies, p);
      } else if (malformed_list) {
        log_warn(LD_CONFIG, "Entry '%s' in %s is malformed. Discarding entire"
                 " list.", nick, description);
        r = -1;
        tor_free(nick);
        SMARTLIST_DEL_CURRENT(list, nick);
      } else {
        log_notice(LD_CONFIG, "Entry '%s' in %s is ignored. Using the"
                   " remainder of the list.", nick, description);
        tor_free(nick);
        SMARTLIST_DEL_CURRENT(list, nick);
      }
  } SMARTLIST_FOREACH_END(nick);
Beispiel #13
0
/**
   Launch all client listeners that tor wants us to launch.
*/
static int
launch_client_listeners(const managed_proxy_t *proxy)
{
  int ret=-1;
  config_t *cfg = NULL;

  /* list of transports */
  smartlist_t *transports = smartlist_create();

  smartlist_split_string(transports, proxy->vars.transports, ",",
                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);

  SMARTLIST_FOREACH_BEGIN(transports, char *, transport) {
    /* clients should find their own listen port */
    cfg = config_create_managed(proxy->is_server,
                                transport, "127.0.0.1:0", proxy->vars.or_port);
    if (cfg) /* if config was created; put it in the config smartlist */
      smartlist_add(proxy->configs, cfg);
    else
        print_method_error_line(transport, proxy, ST_LAUNCH_FAIL_SETUP);
  } SMARTLIST_FOREACH_END(transport);
Beispiel #14
0
/** Parse the '-p' argument of tor-fw-helper. Its format is
 *  [<external port>]:<internal port>, and <external port> is optional.
 *  Return NULL if <b>arg</b> was c0rrupted. */
static port_to_forward_t *
parse_port(const char *arg)
{
    smartlist_t *sl = smartlist_new();
    port_to_forward_t *port_to_forward = NULL;
    char *port_str = NULL;
    int ok;
    int port;

    smartlist_split_string(sl, arg, ":", 0, 0);
    if (smartlist_len(sl) != 2)
        goto err;

    port_to_forward = tor_malloc(sizeof(port_to_forward_t));
    if (!port_to_forward)
        goto err;

    port_str = smartlist_get(sl, 0); /* macroify ? */
    port = (int)tor_parse_long(port_str, 10, 1, 65535, &ok, NULL);
    if (!ok && strlen(port_str)) /* ":1555" is valid */
        goto err;
    port_to_forward->external_port = port;

    port_str = smartlist_get(sl, 1);
    port = (int)tor_parse_long(port_str, 10, 1, 65535, &ok, NULL);
    if (!ok)
        goto err;
    port_to_forward->internal_port = port;

    goto done;

err:
    tor_free(port_to_forward);

done:
    SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
    smartlist_free(sl);

    return port_to_forward;
}
Beispiel #15
0
/** Return true if <b>line</b> is a valid state TransportProxy line.
 *  Return false otherwise. */
static int
state_transport_line_is_valid(const char *line)
{
  smartlist_t *items = NULL;
  char *addrport=NULL;
  tor_addr_t addr;
  uint16_t port = 0;
  int r;

  items = smartlist_new();
  smartlist_split_string(items, line, NULL,
                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);

  if (smartlist_len(items) != 2) {
    log_warn(LD_CONFIG, "state: Not enough arguments in TransportProxy line.");
    goto err;
  }

  addrport = smartlist_get(items, 1);
  if (tor_addr_port_lookup(addrport, &addr, &port) < 0) {
    log_warn(LD_CONFIG, "state: Could not parse addrport.");
    goto err;
  }

  if (!port) {
    log_warn(LD_CONFIG, "state: Transport line did not contain port.");
    goto err;
  }

  r = 1;
  goto done;

 err:
  r = 0;

 done:
  SMARTLIST_FOREACH(items, char*, s, tor_free(s));
  smartlist_free(items);
  return r;
}
Beispiel #16
0
/** Parse the string <b>s</b> to create a set of routerset entries, and add
 * them to <b>target</b>.  In log messages, refer to the string as
 * <b>description</b>.  Return 0 on success, -1 on failure.
 *
 * Three kinds of elements are allowed in routersets: nicknames, IP address
 * patterns, and fingerprints.  They may be surrounded by optional space, and
 * must be separated by commas.
 */
int
routerset_parse(routerset_t *target, const char *s, const char *description)
{
  int r = 0;
  int added_countries = 0;
  char *countryname;
  smartlist_t *list = smartlist_new();
  smartlist_split_string(list, s, ",",
                         SPLIT_SKIP_SPACE | SPLIT_IGNORE_BLANK, 0);
  SMARTLIST_FOREACH_BEGIN(list, char *, nick) {
      addr_policy_t *p;
      if (is_legal_hexdigest(nick)) {
        char d[DIGEST_LEN];
        if (*nick == '$')
          ++nick;
        log_debug(LD_CONFIG, "Adding identity %s to %s", nick, description);
        base16_decode(d, sizeof(d), nick, HEX_DIGEST_LEN);
        digestmap_set(target->digests, d, (void*)1);
      } else if (is_legal_nickname(nick)) {
        log_debug(LD_CONFIG, "Adding nickname %s to %s", nick, description);
        strmap_set_lc(target->names, nick, (void*)1);
      } else if ((countryname = routerset_get_countryname(nick)) != NULL) {
        log_debug(LD_CONFIG, "Adding country %s to %s", nick,
                  description);
        smartlist_add(target->country_names, countryname);
        added_countries = 1;
      } else if ((strchr(nick,'.') || strchr(nick, '*')) &&
                 (p = router_parse_addr_policy_item_from_string(
                                     nick, ADDR_POLICY_REJECT))) {
        log_debug(LD_CONFIG, "Adding address %s to %s", nick, description);
        smartlist_add(target->policies, p);
      } else {
        log_warn(LD_CONFIG, "Entry '%s' in %s is malformed.", nick,
                 description);
        r = -1;
        tor_free(nick);
        SMARTLIST_DEL_CURRENT(list, nick);
      }
  } SMARTLIST_FOREACH_END(nick);
Beispiel #17
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;
}
Beispiel #18
0
/** Parse and validate the ASCII-encoded v2 descriptor in <b>desc</b>,
 * write the parsed descriptor to the newly allocated *<b>parsed_out</b>, the
 * binary descriptor ID of length DIGEST_LEN to <b>desc_id_out</b>, the
 * encrypted introduction points to the newly allocated
 * *<b>intro_points_encrypted_out</b>, their encrypted size to
 * *<b>intro_points_encrypted_size_out</b>, the size of the encoded descriptor
 * to *<b>encoded_size_out</b>, and a pointer to the possibly next
 * descriptor to *<b>next_out</b>; return 0 for success (including validation)
 * and -1 for failure.
 *
 * If <b>as_hsdir</b> is 1, we're parsing this as an HSDir, and we should
 * be strict about time formats.
 */
int
rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed_out,
                                 char *desc_id_out,
                                 char **intro_points_encrypted_out,
                                 size_t *intro_points_encrypted_size_out,
                                 size_t *encoded_size_out,
                                 const char **next_out, const char *desc,
                                 int as_hsdir)
{
  rend_service_descriptor_t *result =
                            tor_malloc_zero(sizeof(rend_service_descriptor_t));
  char desc_hash[DIGEST_LEN];
  const char *eos;
  smartlist_t *tokens = smartlist_new();
  directory_token_t *tok;
  char secret_id_part[DIGEST_LEN];
  int i, version, num_ok=1;
  smartlist_t *versions;
  char public_key_hash[DIGEST_LEN];
  char test_desc_id[DIGEST_LEN];
  memarea_t *area = NULL;
  const int strict_time_fmt = as_hsdir;

  tor_assert(desc);
  /* Check if desc starts correctly. */
  if (strcmpstart(desc, "rendezvous-service-descriptor ")) {
    log_info(LD_REND, "Descriptor does not start correctly.");
    goto err;
  }
  /* Compute descriptor hash for later validation. */
  if (router_get_hash_impl(desc, strlen(desc), desc_hash,
                           "rendezvous-service-descriptor ",
                           "\nsignature", '\n', DIGEST_SHA1) < 0) {
    log_warn(LD_REND, "Couldn't compute descriptor hash.");
    goto err;
  }
  /* Determine end of string. */
  eos = strstr(desc, "\nrendezvous-service-descriptor ");
  if (!eos)
    eos = desc + strlen(desc);
  else
    eos = eos + 1;
  /* Check length. */
  if (eos-desc > REND_DESC_MAX_SIZE) {
    /* XXXX+ If we are parsing this descriptor as a server, this
     * should be a protocol warning. */
    log_warn(LD_REND, "Descriptor length is %d which exceeds "
             "maximum rendezvous descriptor size of %d bytes.",
             (int)(eos-desc), REND_DESC_MAX_SIZE);
    goto err;
  }
  /* Tokenize descriptor. */
  area = memarea_new();
  if (tokenize_string(area, desc, eos, tokens, desc_token_table, 0)) {
    log_warn(LD_REND, "Error tokenizing descriptor.");
    goto err;
  }
  /* Set next to next descriptor, if available. */
  *next_out = eos;
  /* Set length of encoded descriptor. */
  *encoded_size_out = eos - desc;
  /* Check min allowed length of token list. */
  if (smartlist_len(tokens) < 7) {
    log_warn(LD_REND, "Impossibly short descriptor.");
    goto err;
  }
  /* Parse base32-encoded descriptor ID. */
  tok = find_by_keyword(tokens, R_RENDEZVOUS_SERVICE_DESCRIPTOR);
  tor_assert(tok == smartlist_get(tokens, 0));
  tor_assert(tok->n_args == 1);
  if (!rend_valid_descriptor_id(tok->args[0])) {
    log_warn(LD_REND, "Invalid descriptor ID: '%s'", tok->args[0]);
    goto err;
  }
  if (base32_decode(desc_id_out, DIGEST_LEN,
                    tok->args[0], REND_DESC_ID_V2_LEN_BASE32) < 0) {
    log_warn(LD_REND, "Descriptor ID contains illegal characters: %s",
             tok->args[0]);
    goto err;
  }
  /* Parse descriptor version. */
  tok = find_by_keyword(tokens, R_VERSION);
  tor_assert(tok->n_args == 1);
  result->version =
    (int) tor_parse_long(tok->args[0], 10, 0, INT_MAX, &num_ok, NULL);
  if (result->version != 2 || !num_ok) {
    /* If it's <2, it shouldn't be under this format.  If the number
     * is greater than 2, we bumped it because we broke backward
     * compatibility.  See how version numbers in our other formats
     * work. */
    log_warn(LD_REND, "Unrecognized descriptor version: %s",
             escaped(tok->args[0]));
    goto err;
  }
  /* Parse public key. */
  tok = find_by_keyword(tokens, R_PERMANENT_KEY);
  result->pk = tok->key;
  tok->key = NULL; /* Prevent free */
  /* Parse secret ID part. */
  tok = find_by_keyword(tokens, R_SECRET_ID_PART);
  tor_assert(tok->n_args == 1);
  if (strlen(tok->args[0]) != REND_SECRET_ID_PART_LEN_BASE32 ||
      strspn(tok->args[0], BASE32_CHARS) != REND_SECRET_ID_PART_LEN_BASE32) {
    log_warn(LD_REND, "Invalid secret ID part: '%s'", tok->args[0]);
    goto err;
  }
  if (base32_decode(secret_id_part, DIGEST_LEN, tok->args[0], 32) < 0) {
    log_warn(LD_REND, "Secret ID part contains illegal characters: %s",
             tok->args[0]);
    goto err;
  }
  /* Parse publication time -- up-to-date check is done when storing the
   * descriptor. */
  tok = find_by_keyword(tokens, R_PUBLICATION_TIME);
  tor_assert(tok->n_args == 1);
  if (parse_iso_time_(tok->args[0], &result->timestamp,
                      strict_time_fmt, 0) < 0) {
    log_warn(LD_REND, "Invalid publication time: '%s'", tok->args[0]);
    goto err;
  }
  /* Parse protocol versions. */
  tok = find_by_keyword(tokens, R_PROTOCOL_VERSIONS);
  tor_assert(tok->n_args == 1);
  versions = smartlist_new();
  smartlist_split_string(versions, tok->args[0], ",",
                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
  for (i = 0; i < smartlist_len(versions); i++) {
    version = (int) tor_parse_long(smartlist_get(versions, i),
                                   10, 0, INT_MAX, &num_ok, NULL);
    if (!num_ok) /* It's a string; let's ignore it. */
      continue;
    if (version >= REND_PROTOCOL_VERSION_BITMASK_WIDTH)
      /* Avoid undefined left-shift behaviour. */
      continue;
    result->protocols |= 1 << version;
  }
  SMARTLIST_FOREACH(versions, char *, cp, tor_free(cp));
  smartlist_free(versions);
  /* Parse encrypted introduction points. Don't verify. */
  tok = find_opt_by_keyword(tokens, R_INTRODUCTION_POINTS);
  if (tok) {
    if (strcmp(tok->object_type, "MESSAGE")) {
      log_warn(LD_DIR, "Bad object type: introduction points should be of "
               "type MESSAGE");
      goto err;
    }
    *intro_points_encrypted_out = tor_memdup(tok->object_body,
                                             tok->object_size);
    *intro_points_encrypted_size_out = tok->object_size;
  } else {
    *intro_points_encrypted_out = NULL;
    *intro_points_encrypted_size_out = 0;
  }
  /* Parse and verify signature. */
  tok = find_by_keyword(tokens, R_SIGNATURE);
  if (check_signature_token(desc_hash, DIGEST_LEN, tok, result->pk, 0,
                            "v2 rendezvous service descriptor") < 0)
    goto err;
  /* Verify that descriptor ID belongs to public key and secret ID part. */
  if (crypto_pk_get_digest(result->pk, public_key_hash) < 0) {
    log_warn(LD_REND, "Unable to compute rend descriptor public key digest");
    goto err;
  }
  rend_get_descriptor_id_bytes(test_desc_id, public_key_hash,
                               secret_id_part);
  if (tor_memneq(desc_id_out, test_desc_id, DIGEST_LEN)) {
    log_warn(LD_REND, "Parsed descriptor ID does not match "
             "computed descriptor ID.");
    goto err;
  }
  goto done;
 err:
  rend_service_descriptor_free(result);
  result = NULL;
 done:
  if (tokens) {
    SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
    smartlist_free(tokens);
  }
  if (area)
    memarea_drop_all(area);
  *parsed_out = result;
  if (result)
    return 0;
  return -1;
}
Beispiel #19
0
/**
 * Load histogram from <b>state</b>, shuffling the resulting array
 * after we do so. Use this result to estimate parameters and
 * calculate the timeout.
 *
 * Return -1 on error.
 */
int
circuit_build_times_parse_state(circuit_build_times_t *cbt,
                                or_state_t *state)
{
  int tot_values = 0;
  uint32_t loaded_cnt = 0, N = 0;
  config_line_t *line;
  unsigned int i;
  build_time_t *loaded_times;
  int err = 0;
  circuit_build_times_init(cbt);

  if (circuit_build_times_disabled()) {
    return 0;
  }

  /* build_time_t 0 means uninitialized */
  loaded_times = tor_malloc_zero(sizeof(build_time_t)*state->TotalBuildTimes);

  for (line = state->BuildtimeHistogram; line; line = line->next) {
    smartlist_t *args = smartlist_new();
    smartlist_split_string(args, line->value, " ",
                           SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
    if (smartlist_len(args) < 2) {
      log_warn(LD_GENERAL, "Unable to parse circuit build times: "
                           "Too few arguments to CircuitBuildTime");
      err = 1;
      SMARTLIST_FOREACH(args, char*, cp, tor_free(cp));
      smartlist_free(args);
      break;
    } else {
      const char *ms_str = smartlist_get(args,0);
      const char *count_str = smartlist_get(args,1);
      uint32_t count, k;
      build_time_t ms;
      int ok;
      ms = (build_time_t)tor_parse_ulong(ms_str, 0, 0,
                                         CBT_BUILD_TIME_MAX, &ok, NULL);
      if (!ok) {
        log_warn(LD_GENERAL, "Unable to parse circuit build times: "
                             "Unparsable bin number");
        err = 1;
        SMARTLIST_FOREACH(args, char*, cp, tor_free(cp));
        smartlist_free(args);
        break;
      }
      count = (uint32_t)tor_parse_ulong(count_str, 0, 0,
                                        UINT32_MAX, &ok, NULL);
      if (!ok) {
        log_warn(LD_GENERAL, "Unable to parse circuit build times: "
                             "Unparsable bin count");
        err = 1;
        SMARTLIST_FOREACH(args, char*, cp, tor_free(cp));
        smartlist_free(args);
        break;
      }

      if (loaded_cnt+count+state->CircuitBuildAbandonedCount
            > state->TotalBuildTimes) {
        log_warn(LD_CIRC,
                 "Too many build times in state file. "
                 "Stopping short before %d",
                 loaded_cnt+count);
        SMARTLIST_FOREACH(args, char*, cp, tor_free(cp));
        smartlist_free(args);
        break;
      }

      for (k = 0; k < count; k++) {
        loaded_times[loaded_cnt++] = ms;
      }
      N++;
      SMARTLIST_FOREACH(args, char*, cp, tor_free(cp));
      smartlist_free(args);
    }
  }

  log_info(LD_CIRC,
           "Adding %d timeouts.", state->CircuitBuildAbandonedCount);
  for (i=0; i < state->CircuitBuildAbandonedCount; i++) {
    loaded_times[loaded_cnt++] = CBT_BUILD_ABANDONED;
  }

  if (loaded_cnt != state->TotalBuildTimes) {
    log_warn(LD_CIRC,
            "Corrupt state file? Build times count mismatch. "
            "Read %d times, but file says %d", loaded_cnt,
            state->TotalBuildTimes);
    err = 1;
    circuit_build_times_reset(cbt);
    goto done;
  }

  circuit_build_times_shuffle_and_store_array(cbt, loaded_times, loaded_cnt);

  /* Verify that we didn't overwrite any indexes */
  for (i=0; i < CBT_NCIRCUITS_TO_OBSERVE; i++) {
    if (!cbt->circuit_build_times[i])
      break;
    tot_values++;
  }
  log_info(LD_CIRC,
           "Loaded %d/%d values from %d lines in circuit time histogram",
           tot_values, cbt->total_build_times, N);

  if (cbt->total_build_times != tot_values
        || cbt->total_build_times > CBT_NCIRCUITS_TO_OBSERVE) {
    log_warn(LD_CIRC,
            "Corrupt state file? Shuffled build times mismatch. "
            "Read %d times, but file says %d", tot_values,
            state->TotalBuildTimes);
    err = 1;
    circuit_build_times_reset(cbt);
    goto done;
  }

  circuit_build_times_set_timeout(cbt);

  if (!state->CircuitBuildAbandonedCount && cbt->total_build_times) {
    circuit_build_times_filter_timeouts(cbt);
  }

 done:
  tor_free(loaded_times);
  return err ? -1 : 0;
}
Beispiel #20
0
/** Run unit tests for smartlist-of-strings functionality. */
static void
test_container_smartlist_strings(void)
{
  smartlist_t *sl = smartlist_new();
  char *cp=NULL, *cp_alloc=NULL;
  size_t sz;

  /* Test split and join */
  test_eq(0, smartlist_len(sl));
  smartlist_split_string(sl, "abc", ":", 0, 0);
  test_eq(1, smartlist_len(sl));
  test_streq("abc", smartlist_get(sl, 0));
  smartlist_split_string(sl, "a::bc::", "::", 0, 0);
  test_eq(4, smartlist_len(sl));
  test_streq("a", smartlist_get(sl, 1));
  test_streq("bc", smartlist_get(sl, 2));
  test_streq("", smartlist_get(sl, 3));
  cp_alloc = smartlist_join_strings(sl, "", 0, NULL);
  test_streq(cp_alloc, "abcabc");
  tor_free(cp_alloc);
  cp_alloc = smartlist_join_strings(sl, "!", 0, NULL);
  test_streq(cp_alloc, "abc!a!bc!");
  tor_free(cp_alloc);
  cp_alloc = smartlist_join_strings(sl, "XY", 0, NULL);
  test_streq(cp_alloc, "abcXYaXYbcXY");
  tor_free(cp_alloc);
  cp_alloc = smartlist_join_strings(sl, "XY", 1, NULL);
  test_streq(cp_alloc, "abcXYaXYbcXYXY");
  tor_free(cp_alloc);
  cp_alloc = smartlist_join_strings(sl, "", 1, NULL);
  test_streq(cp_alloc, "abcabc");
  tor_free(cp_alloc);

  smartlist_split_string(sl, "/def/  /ghijk", "/", 0, 0);
  test_eq(8, smartlist_len(sl));
  test_streq("", smartlist_get(sl, 4));
  test_streq("def", smartlist_get(sl, 5));
  test_streq("  ", smartlist_get(sl, 6));
  test_streq("ghijk", smartlist_get(sl, 7));
  SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
  smartlist_clear(sl);

  smartlist_split_string(sl, "a,bbd,cdef", ",", SPLIT_SKIP_SPACE, 0);
  test_eq(3, smartlist_len(sl));
  test_streq("a", smartlist_get(sl,0));
  test_streq("bbd", smartlist_get(sl,1));
  test_streq("cdef", smartlist_get(sl,2));
  smartlist_split_string(sl, " z <> zhasd <>  <> bnud<>   ", "<>",
                         SPLIT_SKIP_SPACE, 0);
  test_eq(8, smartlist_len(sl));
  test_streq("z", smartlist_get(sl,3));
  test_streq("zhasd", smartlist_get(sl,4));
  test_streq("", smartlist_get(sl,5));
  test_streq("bnud", smartlist_get(sl,6));
  test_streq("", smartlist_get(sl,7));

  SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
  smartlist_clear(sl);

  smartlist_split_string(sl, " ab\tc \td ef  ", NULL,
                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
  test_eq(4, smartlist_len(sl));
  test_streq("ab", smartlist_get(sl,0));
  test_streq("c", smartlist_get(sl,1));
  test_streq("d", smartlist_get(sl,2));
  test_streq("ef", smartlist_get(sl,3));
  smartlist_split_string(sl, "ghi\tj", NULL,
                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
  test_eq(6, smartlist_len(sl));
  test_streq("ghi", smartlist_get(sl,4));
  test_streq("j", smartlist_get(sl,5));

  SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
  smartlist_clear(sl);

  cp_alloc = smartlist_join_strings(sl, "XY", 0, NULL);
  test_streq(cp_alloc, "");
  tor_free(cp_alloc);
  cp_alloc = smartlist_join_strings(sl, "XY", 1, NULL);
  test_streq(cp_alloc, "XY");
  tor_free(cp_alloc);

  smartlist_split_string(sl, " z <> zhasd <>  <> bnud<>   ", "<>",
                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
  test_eq(3, smartlist_len(sl));
  test_streq("z", smartlist_get(sl, 0));
  test_streq("zhasd", smartlist_get(sl, 1));
  test_streq("bnud", smartlist_get(sl, 2));
  smartlist_split_string(sl, " z <> zhasd <>  <> bnud<>   ", "<>",
                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2);
  test_eq(5, smartlist_len(sl));
  test_streq("z", smartlist_get(sl, 3));
  test_streq("zhasd <>  <> bnud<>", smartlist_get(sl, 4));
  SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
  smartlist_clear(sl);

  smartlist_split_string(sl, "abcd\n", "\n",
                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
  test_eq(1, smartlist_len(sl));
  test_streq("abcd", smartlist_get(sl, 0));
  smartlist_split_string(sl, "efgh", "\n",
                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
  test_eq(2, smartlist_len(sl));
  test_streq("efgh", smartlist_get(sl, 1));

  SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
  smartlist_clear(sl);

  /* Test swapping, shuffling, and sorting. */
  smartlist_split_string(sl, "the,onion,router,by,arma,and,nickm", ",", 0, 0);
  test_eq(7, smartlist_len(sl));
  smartlist_sort(sl, compare_strs_);
  cp_alloc = smartlist_join_strings(sl, ",", 0, NULL);
  test_streq(cp_alloc,"and,arma,by,nickm,onion,router,the");
  tor_free(cp_alloc);
  smartlist_swap(sl, 1, 5);
  cp_alloc = smartlist_join_strings(sl, ",", 0, NULL);
  test_streq(cp_alloc,"and,router,by,nickm,onion,arma,the");
  tor_free(cp_alloc);
  smartlist_shuffle(sl);
  test_eq(7, smartlist_len(sl));
  test_assert(smartlist_contains_string(sl, "and"));
  test_assert(smartlist_contains_string(sl, "router"));
  test_assert(smartlist_contains_string(sl, "by"));
  test_assert(smartlist_contains_string(sl, "nickm"));
  test_assert(smartlist_contains_string(sl, "onion"));
  test_assert(smartlist_contains_string(sl, "arma"));
  test_assert(smartlist_contains_string(sl, "the"));

  /* Test bsearch. */
  smartlist_sort(sl, compare_strs_);
  test_streq("nickm", smartlist_bsearch(sl, "zNicKM",
                                        compare_without_first_ch_));
  test_streq("and", smartlist_bsearch(sl, " AND", compare_without_first_ch_));
  test_eq_ptr(NULL, smartlist_bsearch(sl, " ANz", compare_without_first_ch_));

  /* Test bsearch_idx */
  {
    int f;
    smartlist_t *tmp = NULL;

    test_eq(0, smartlist_bsearch_idx(sl," aaa",compare_without_first_ch_,&f));
    test_eq(f, 0);
    test_eq(0, smartlist_bsearch_idx(sl," and",compare_without_first_ch_,&f));
    test_eq(f, 1);
    test_eq(1, smartlist_bsearch_idx(sl," arm",compare_without_first_ch_,&f));
    test_eq(f, 0);
    test_eq(1, smartlist_bsearch_idx(sl," arma",compare_without_first_ch_,&f));
    test_eq(f, 1);
    test_eq(2, smartlist_bsearch_idx(sl," armb",compare_without_first_ch_,&f));
    test_eq(f, 0);
    test_eq(7, smartlist_bsearch_idx(sl," zzzz",compare_without_first_ch_,&f));
    test_eq(f, 0);

    /* Test trivial cases for list of length 0 or 1 */
    tmp = smartlist_new();
    test_eq(0, smartlist_bsearch_idx(tmp, "foo",
                                     compare_strs_for_bsearch_, &f));
    test_eq(f, 0);
    smartlist_insert(tmp, 0, (void *)("bar"));
    test_eq(1, smartlist_bsearch_idx(tmp, "foo",
                                     compare_strs_for_bsearch_, &f));
    test_eq(f, 0);
    test_eq(0, smartlist_bsearch_idx(tmp, "aaa",
                                     compare_strs_for_bsearch_, &f));
    test_eq(f, 0);
    test_eq(0, smartlist_bsearch_idx(tmp, "bar",
                                     compare_strs_for_bsearch_, &f));
    test_eq(f, 1);
    /* ... and one for length 2 */
    smartlist_insert(tmp, 1, (void *)("foo"));
    test_eq(1, smartlist_bsearch_idx(tmp, "foo",
                                     compare_strs_for_bsearch_, &f));
    test_eq(f, 1);
    test_eq(2, smartlist_bsearch_idx(tmp, "goo",
                                     compare_strs_for_bsearch_, &f));
    test_eq(f, 0);
    smartlist_free(tmp);
  }

  /* Test reverse() and pop_last() */
  smartlist_reverse(sl);
  cp_alloc = smartlist_join_strings(sl, ",", 0, NULL);
  test_streq(cp_alloc,"the,router,onion,nickm,by,arma,and");
  tor_free(cp_alloc);
  cp_alloc = smartlist_pop_last(sl);
  test_streq(cp_alloc, "and");
  tor_free(cp_alloc);
  test_eq(smartlist_len(sl), 6);
  SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
  smartlist_clear(sl);
  cp_alloc = smartlist_pop_last(sl);
  test_eq_ptr(cp_alloc, NULL);

  /* Test uniq() */
  smartlist_split_string(sl,
                     "50,noon,radar,a,man,a,plan,a,canal,panama,radar,noon,50",
                     ",", 0, 0);
  smartlist_sort(sl, compare_strs_);
  smartlist_uniq(sl, compare_strs_, tor_free_);
  cp_alloc = smartlist_join_strings(sl, ",", 0, NULL);
  test_streq(cp_alloc, "50,a,canal,man,noon,panama,plan,radar");
  tor_free(cp_alloc);

  /* Test contains_string, contains_string_case and contains_int_as_string */
  test_assert(smartlist_contains_string(sl, "noon"));
  test_assert(!smartlist_contains_string(sl, "noonoon"));
  test_assert(smartlist_contains_string_case(sl, "nOOn"));
  test_assert(!smartlist_contains_string_case(sl, "nooNooN"));
  test_assert(smartlist_contains_int_as_string(sl, 50));
  test_assert(!smartlist_contains_int_as_string(sl, 60));

  /* Test smartlist_choose */
  {
    int i;
    int allsame = 1;
    int allin = 1;
    void *first = smartlist_choose(sl);
    test_assert(smartlist_contains(sl, first));
    for (i = 0; i < 100; ++i) {
      void *second = smartlist_choose(sl);
      if (second != first)
        allsame = 0;
      if (!smartlist_contains(sl, second))
        allin = 0;
    }
    test_assert(!allsame);
    test_assert(allin);
  }
  SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
  smartlist_clear(sl);

  /* Test string_remove and remove and join_strings2 */
  smartlist_split_string(sl,
                    "Some say the Earth will end in ice and some in fire",
                    " ", 0, 0);
  cp = smartlist_get(sl, 4);
  test_streq(cp, "will");
  smartlist_add(sl, cp);
  smartlist_remove(sl, cp);
  tor_free(cp);
  cp_alloc = smartlist_join_strings(sl, ",", 0, NULL);
  test_streq(cp_alloc, "Some,say,the,Earth,fire,end,in,ice,and,some,in");
  tor_free(cp_alloc);
  smartlist_string_remove(sl, "in");
  cp_alloc = smartlist_join_strings2(sl, "+XX", 1, 0, &sz);
  test_streq(cp_alloc, "Some+say+the+Earth+fire+end+some+ice+and");
  test_eq((int)sz, 40);

 done:

  SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
  smartlist_free(sl);
  tor_free(cp_alloc);
}
Beispiel #21
0
/* Test the configure_proxy() function. */
static void
test_pt_configure_proxy(void *arg)
{
  int i, retval;
  managed_proxy_t *mp = NULL;
  (void) arg;

  dummy_state = tor_malloc_zero(sizeof(or_state_t));

  MOCK(process_read_stdout, process_read_stdout_replacement);
  MOCK(get_or_state,
       get_or_state_replacement);
  MOCK(queue_control_event_string,
       queue_control_event_string_replacement);

  control_testing_set_global_event_mask(EVENT_TRANSPORT_LAUNCHED);

  mp = tor_malloc_zero(sizeof(managed_proxy_t));
  mp->conf_state = PT_PROTO_ACCEPTING_METHODS;
  mp->transports = smartlist_new();
  mp->transports_to_launch = smartlist_new();
  mp->argv = tor_malloc_zero(sizeof(char*)*2);
  mp->argv[0] = tor_strdup("<testcase>");
  mp->is_server = 1;

  /* Configure the process. */
  mp->process = process_new("");
  process_set_stdout_read_callback(mp->process, managed_proxy_stdout_callback);
  process_set_data(mp->process, mp);

  /* Test the return value of configure_proxy() by calling it some
     times while it is uninitialized and then finally finalizing its
     configuration. */
  for (i = 0 ; i < 5 ; i++) {
    /* force a read from our mocked stdout reader. */
    process_notify_event_stdout(mp->process);
    /* try to configure our proxy. */
    retval = configure_proxy(mp);
    /* retval should be zero because proxy hasn't finished configuring yet */
    tt_int_op(retval, OP_EQ, 0);
    /* check the number of registered transports */
    tt_int_op(smartlist_len(mp->transports), OP_EQ, i+1);
    /* check that the mp is still waiting for transports */
    tt_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS);
  }

  /* Get the SMETHOD DONE written to the process. */
  process_notify_event_stdout(mp->process);

  /* this last configure_proxy() should finalize the proxy configuration. */
  retval = configure_proxy(mp);
  /* retval should be 1 since the proxy finished configuring */
  tt_int_op(retval, OP_EQ, 1);
  /* check the mp state */
  tt_assert(mp->conf_state == PT_PROTO_COMPLETED);

  tt_int_op(controlevent_n, OP_EQ, 5);
  tt_int_op(controlevent_event, OP_EQ, EVENT_TRANSPORT_LAUNCHED);
  tt_int_op(smartlist_len(controlevent_msgs), OP_EQ, 5);
  smartlist_sort_strings(controlevent_msgs);
  tt_str_op(smartlist_get(controlevent_msgs, 0), OP_EQ,
            "650 TRANSPORT_LAUNCHED server mock1 127.0.0.1 5551\r\n");
  tt_str_op(smartlist_get(controlevent_msgs, 1), OP_EQ,
            "650 TRANSPORT_LAUNCHED server mock2 127.0.0.1 5552\r\n");
  tt_str_op(smartlist_get(controlevent_msgs, 2), OP_EQ,
            "650 TRANSPORT_LAUNCHED server mock3 127.0.0.1 5553\r\n");
  tt_str_op(smartlist_get(controlevent_msgs, 3), OP_EQ,
            "650 TRANSPORT_LAUNCHED server mock4 127.0.0.1 5554\r\n");
  tt_str_op(smartlist_get(controlevent_msgs, 4), OP_EQ,
            "650 TRANSPORT_LAUNCHED server mock5 127.0.0.1 5555\r\n");

  /* Get the log message out. */
  process_notify_event_stdout(mp->process);

  tt_int_op(controlevent_n, OP_EQ, 10);
  tt_int_op(controlevent_event, OP_EQ, EVENT_PT_LOG);
  tt_int_op(smartlist_len(controlevent_msgs), OP_EQ, 10);
  tt_str_op(smartlist_get(controlevent_msgs, 5), OP_EQ,
            "650 PT_LOG PT=<testcase> SEVERITY=error "
            "MESSAGE=\"Oh noes, "
            "something bad happened. What do we do!?\"\r\n");
  tt_str_op(smartlist_get(controlevent_msgs, 6), OP_EQ,
            "650 PT_LOG PT=<testcase> SEVERITY=warning "
            "MESSAGE=\"warning msg\"\r\n");
  tt_str_op(smartlist_get(controlevent_msgs, 7), OP_EQ,
            "650 PT_LOG PT=<testcase> SEVERITY=notice "
            "MESSAGE=\"notice msg\"\r\n");
  tt_str_op(smartlist_get(controlevent_msgs, 8), OP_EQ,
            "650 PT_LOG PT=<testcase> SEVERITY=info "
            "MESSAGE=\"info msg\"\r\n");
  tt_str_op(smartlist_get(controlevent_msgs, 9), OP_EQ,
            "650 PT_LOG PT=<testcase> SEVERITY=debug "
            "MESSAGE=\"debug msg\"\r\n");

  /* Get the STATUS messages out. */
  process_notify_event_stdout(mp->process);

  tt_int_op(controlevent_n, OP_EQ, 13);
  tt_int_op(controlevent_event, OP_EQ, EVENT_PT_STATUS);
  tt_int_op(smartlist_len(controlevent_msgs), OP_EQ, 13);

  tt_str_op(smartlist_get(controlevent_msgs, 10), OP_EQ,
            "650 PT_STATUS "
            "PT=<testcase> TRANSPORT=a K_1=a K_2=b K_3=\"foo bar\"\r\n");
  tt_str_op(smartlist_get(controlevent_msgs, 11), OP_EQ,
            "650 PT_STATUS "
            "PT=<testcase> TRANSPORT=b K_1=a K_2=b K_3=\"foo bar\"\r\n");
  tt_str_op(smartlist_get(controlevent_msgs, 12), OP_EQ,
            "650 PT_STATUS "
            "PT=<testcase> TRANSPORT=c K_1=a K_2=b K_3=\"foo bar\"\r\n");

  { /* check that the transport info were saved properly in the tor state */
    config_line_t *transport_in_state = NULL;
    smartlist_t *transport_info_sl = smartlist_new();
    char *name_of_transport = NULL;
    char *bindaddr = NULL;

    /* Get the bindaddr for "mock1" and check it against the bindaddr
       that the mocked tor_get_lines_from_handle() generated. */
    transport_in_state = get_transport_in_state_by_name("mock1");
    tt_assert(transport_in_state);
    smartlist_split_string(transport_info_sl, transport_in_state->value,
                           NULL, 0, 0);
    name_of_transport = smartlist_get(transport_info_sl, 0);
    bindaddr = smartlist_get(transport_info_sl, 1);
    tt_str_op(name_of_transport, OP_EQ, "mock1");
    tt_str_op(bindaddr, OP_EQ, "127.0.0.1:5551");

    SMARTLIST_FOREACH(transport_info_sl, char *, cp, tor_free(cp));
    smartlist_free(transport_info_sl);
  }

 done:
  or_state_free(dummy_state);
  UNMOCK(process_read_stdout);
  UNMOCK(get_or_state);
  UNMOCK(queue_control_event_string);
  if (controlevent_msgs) {
    SMARTLIST_FOREACH(controlevent_msgs, char *, cp, tor_free(cp));
    smartlist_free(controlevent_msgs);
    controlevent_msgs = NULL;
  }
  if (mp->transports) {
    SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
    smartlist_free(mp->transports);
  }
Beispiel #22
0
/** Make sure that we use GuardFraction information when we should,
 * according to the torrc option and consensus parameter. */
static void
test_should_apply_guardfraction(void *arg)
{
  networkstatus_t vote_enabled, vote_disabled, vote_missing;
  or_options_t *options = get_options_mutable();

  (void) arg;

  { /* Fill the votes for later */
    /* This one suggests enabled GuardFraction. */
    memset(&vote_enabled, 0, sizeof(vote_enabled));
    vote_enabled.net_params = smartlist_new();
    smartlist_split_string(vote_enabled.net_params,
                           "UseGuardFraction=1", NULL, 0, 0);

    /* This one suggests disabled GuardFraction. */
    memset(&vote_disabled, 0, sizeof(vote_disabled));
    vote_disabled.net_params = smartlist_new();
    smartlist_split_string(vote_disabled.net_params,
                           "UseGuardFraction=0", NULL, 0, 0);

    /* This one doesn't have GuardFraction at all. */
    memset(&vote_missing, 0, sizeof(vote_missing));
    vote_missing.net_params = smartlist_new();
    smartlist_split_string(vote_missing.net_params,
                           "leon=trout", NULL, 0, 0);
  }

  /* If torrc option is set to yes, we should always use
   * guardfraction.*/
  options->UseGuardFraction = 1;
  tt_int_op(should_apply_guardfraction(&vote_disabled), ==, 1);

  /* If torrc option is set to no, we should never use
   * guardfraction.*/
  options->UseGuardFraction = 0;
  tt_int_op(should_apply_guardfraction(&vote_enabled), ==, 0);

  /* Now let's test torrc option set to auto. */
  options->UseGuardFraction = -1;

  /* If torrc option is set to auto, and consensus parameter is set to
   * yes, we should use guardfraction. */
  tt_int_op(should_apply_guardfraction(&vote_enabled), ==, 1);

  /* If torrc option is set to auto, and consensus parameter is set to
   * no, we should use guardfraction. */
  tt_int_op(should_apply_guardfraction(&vote_disabled), ==, 0);

  /* If torrc option is set to auto, and consensus parameter is not
   * set, we should fallback to "no". */
  tt_int_op(should_apply_guardfraction(&vote_missing), ==, 0);

 done:
  SMARTLIST_FOREACH(vote_enabled.net_params, char *, cp, tor_free(cp));
  SMARTLIST_FOREACH(vote_disabled.net_params, char *, cp, tor_free(cp));
  SMARTLIST_FOREACH(vote_missing.net_params, char *, cp, tor_free(cp));
  smartlist_free(vote_enabled.net_params);
  smartlist_free(vote_disabled.net_params);
  smartlist_free(vote_missing.net_params);
}
/** Run unit tests for smartlist-of-strings functionality. */
static void
test_container_smartlist_strings(void *unused)
{
  smartlist_t *sl = smartlist_create();
  char *cp=NULL, *cp_alloc=NULL;
  size_t sz;

  /* Test split and join */
  tt_int_op(smartlist_len(sl), ==, 0);
  smartlist_split_string(sl, "abc", ":", 0, 0);
  tt_int_op(smartlist_len(sl), ==, 1);
  tt_str_op(smartlist_get(sl, 0), ==, "abc");
  smartlist_split_string(sl, "a::bc::", "::", 0, 0);
  tt_int_op(smartlist_len(sl), ==, 4);
  tt_str_op(smartlist_get(sl, 1), ==, "a");
  tt_str_op(smartlist_get(sl, 2), ==, "bc");
  tt_str_op(smartlist_get(sl, 3), ==, "");
  cp_alloc = smartlist_join_strings(sl, "", 0, NULL);
  tt_str_op(cp_alloc, ==, "abcabc");
  free(cp_alloc);
  cp_alloc = smartlist_join_strings(sl, "!", 0, NULL);
  tt_str_op(cp_alloc, ==, "abc!a!bc!");
  free(cp_alloc);
  cp_alloc = smartlist_join_strings(sl, "XY", 0, NULL);
  tt_str_op(cp_alloc, ==, "abcXYaXYbcXY");
  free(cp_alloc);
  cp_alloc = smartlist_join_strings(sl, "XY", 1, NULL);
  tt_str_op(cp_alloc, ==, "abcXYaXYbcXYXY");
  free(cp_alloc);
  cp_alloc = smartlist_join_strings(sl, "", 1, NULL);
  tt_str_op(cp_alloc, ==, "abcabc");
  free(cp_alloc);

  smartlist_split_string(sl, "/def/  /ghijk", "/", 0, 0);
  tt_int_op(smartlist_len(sl), ==, 8);
  tt_str_op(smartlist_get(sl, 4), ==, "");
  tt_str_op(smartlist_get(sl, 5), ==, "def");
  tt_str_op(smartlist_get(sl, 6), ==, "  ");
  tt_str_op(smartlist_get(sl, 7), ==, "ghijk");
  SMARTLIST_FOREACH(sl, char *, cp, free(cp));
  smartlist_clear(sl);

  smartlist_split_string(sl, "a,bbd,cdef", ",", SPLIT_SKIP_SPACE, 0);
  tt_int_op(smartlist_len(sl), ==, 3);
  tt_str_op(smartlist_get(sl,0), ==, "a");
  tt_str_op(smartlist_get(sl,1), ==, "bbd");
  tt_str_op(smartlist_get(sl,2), ==, "cdef");
  smartlist_split_string(sl, " z <> zhasd <>  <> bnud<>   ", "<>",
                         SPLIT_SKIP_SPACE, 0);
  tt_int_op(smartlist_len(sl), ==, 8);
  tt_str_op(smartlist_get(sl,3), ==, "z");
  tt_str_op(smartlist_get(sl,4), ==, "zhasd");
  tt_str_op(smartlist_get(sl,5), ==, "");
  tt_str_op(smartlist_get(sl,6), ==, "bnud");
  tt_str_op(smartlist_get(sl,7), ==, "");

  SMARTLIST_FOREACH(sl, char *, cp, free(cp));
  smartlist_clear(sl);

  smartlist_split_string(sl, " ab\tc \td ef  ", NULL,
                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
  tt_int_op(smartlist_len(sl), ==, 4);
  tt_str_op(smartlist_get(sl,0), ==, "ab");
  tt_str_op(smartlist_get(sl,1), ==, "c");
  tt_str_op(smartlist_get(sl,2), ==, "d");
  tt_str_op(smartlist_get(sl,3), ==, "ef");
  smartlist_split_string(sl, "ghi\tj", NULL,
                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
  tt_int_op(smartlist_len(sl), ==, 6);
  tt_str_op(smartlist_get(sl,4), ==, "ghi");
  tt_str_op(smartlist_get(sl,5), ==, "j");

  SMARTLIST_FOREACH(sl, char *, cp, free(cp));
  smartlist_clear(sl);

  cp_alloc = smartlist_join_strings(sl, "XY", 0, NULL);
  tt_str_op(cp_alloc, ==, "");
  free(cp_alloc);
  cp_alloc = smartlist_join_strings(sl, "XY", 1, NULL);
  tt_str_op(cp_alloc, ==, "XY");
  free(cp_alloc);

  smartlist_split_string(sl, " z <> zhasd <>  <> bnud<>   ", "<>",
                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
  tt_int_op(smartlist_len(sl), ==, 3);
  tt_str_op(smartlist_get(sl, 0), ==, "z");
  tt_str_op(smartlist_get(sl, 1), ==, "zhasd");
  tt_str_op(smartlist_get(sl, 2), ==, "bnud");
  smartlist_split_string(sl, " z <> zhasd <>  <> bnud<>   ", "<>",
                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2);
  tt_int_op(smartlist_len(sl), ==, 5);
  tt_str_op(smartlist_get(sl, 3), ==, "z");
  tt_str_op(smartlist_get(sl, 4), ==, "zhasd <>  <> bnud<>");
  SMARTLIST_FOREACH(sl, char *, cp, free(cp));
  smartlist_clear(sl);

  smartlist_split_string(sl, "abcd\n", "\n",
                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
  tt_int_op(smartlist_len(sl), ==, 1);
  tt_str_op(smartlist_get(sl, 0), ==, "abcd");
  smartlist_split_string(sl, "efgh", "\n",
                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
  tt_int_op(smartlist_len(sl), ==, 2);
  tt_str_op(smartlist_get(sl, 1), ==, "efgh");

  SMARTLIST_FOREACH(sl, char *, cp, free(cp));
  smartlist_clear(sl);

  /* Test swapping, shuffling, and sorting. */
  smartlist_split_string(sl, "the,onion,router,by,arma,and,nickm", ",", 0, 0);
  tt_int_op(smartlist_len(sl), ==, 7);
  smartlist_sort(sl, _compare_strs);
  cp_alloc = smartlist_join_strings(sl, ",", 0, NULL);
  tt_str_op(cp_alloc, ==, "and,arma,by,nickm,onion,router,the");
  free(cp_alloc);
  smartlist_swap(sl, 1, 5);
  cp_alloc = smartlist_join_strings(sl, ",", 0, NULL);
  tt_str_op(cp_alloc, ==, "and,router,by,nickm,onion,arma,the");
  free(cp_alloc);
  smartlist_shuffle(sl);
  tt_int_op(smartlist_len(sl), ==, 7);
  tt_assert(smartlist_string_isin(sl, "and"));
  tt_assert(smartlist_string_isin(sl, "router"));
  tt_assert(smartlist_string_isin(sl, "by"));
  tt_assert(smartlist_string_isin(sl, "nickm"));
  tt_assert(smartlist_string_isin(sl, "onion"));
  tt_assert(smartlist_string_isin(sl, "arma"));
  tt_assert(smartlist_string_isin(sl, "the"));

  /* Test bsearch. */
  smartlist_sort(sl, _compare_strs);
  tt_str_op(smartlist_bsearch(sl, "zNicKM",
                              _compare_without_first_ch), ==, "nickm");
  tt_str_op(smartlist_bsearch(sl, " AND", _compare_without_first_ch), ==, "and");
  tt_ptr_op(smartlist_bsearch(sl, " ANz", _compare_without_first_ch), ==, NULL);

  /* Test bsearch_idx */
  {
    int f;
    tt_int_op(smartlist_bsearch_idx(sl," aaa",_compare_without_first_ch,&f),
              ==, 0);
    tt_int_op(f, ==, 0);
    tt_int_op(smartlist_bsearch_idx(sl," and",_compare_without_first_ch,&f),
              ==, 0);
    tt_int_op(f, ==, 1);
    tt_int_op(smartlist_bsearch_idx(sl," arm",_compare_without_first_ch,&f),
              ==, 1);
    tt_int_op(f, ==, 0);
    tt_int_op(smartlist_bsearch_idx(sl," arma",_compare_without_first_ch,&f),
              ==, 1);
    tt_int_op(f, ==, 1);
    tt_int_op(smartlist_bsearch_idx(sl," armb",_compare_without_first_ch,&f),
              ==, 2);
    tt_int_op(f, ==, 0);
    tt_int_op(smartlist_bsearch_idx(sl," zzzz",_compare_without_first_ch,&f),
              ==, 7);
    tt_int_op(f, ==, 0);
  }

  /* Test reverse() and pop_last() */
  smartlist_reverse(sl);
  cp_alloc = smartlist_join_strings(sl, ",", 0, NULL);
  tt_str_op(cp_alloc, ==, "the,router,onion,nickm,by,arma,and");
  free(cp_alloc);
  cp_alloc = smartlist_pop_last(sl);
  tt_str_op(cp_alloc, ==, "and");
  free(cp_alloc);
  tt_int_op(smartlist_len(sl), ==, 6);
  SMARTLIST_FOREACH(sl, char *, cp, free(cp));
  smartlist_clear(sl);
  cp_alloc = smartlist_pop_last(sl);
  tt_ptr_op(cp_alloc, ==, NULL);

  /* Test uniq() */
  smartlist_split_string(sl,
                     "50,noon,radar,a,man,a,plan,a,canal,panama,radar,noon,50",
                     ",", 0, 0);
  smartlist_sort(sl, _compare_strs);
  smartlist_uniq(sl, _compare_strs, free);
  cp_alloc = smartlist_join_strings(sl, ",", 0, NULL);
  tt_str_op(cp_alloc, ==, "50,a,canal,man,noon,panama,plan,radar");
  free(cp_alloc);

  /* Test string_isin and isin_case and num_isin */
  tt_assert(smartlist_string_isin(sl, "noon"));
  tt_assert(!smartlist_string_isin(sl, "noonoon"));
  tt_assert(smartlist_string_isin_case(sl, "nOOn"));
  tt_assert(!smartlist_string_isin_case(sl, "nooNooN"));
  tt_assert(smartlist_string_num_isin(sl, 50));
  tt_assert(!smartlist_string_num_isin(sl, 60));

  /* Test smartlist_choose */
  {
    int i;
    int allsame = 1;
    int allin = 1;
    void *first = smartlist_choose(sl);
    tt_assert(smartlist_isin(sl, first));
    for (i = 0; i < 100; ++i) {
      void *second = smartlist_choose(sl);
      if (second != first)
        allsame = 0;
      if (!smartlist_isin(sl, second))
        allin = 0;
    }
    tt_assert(!allsame);
    tt_assert(allin);
  }
  SMARTLIST_FOREACH(sl, char *, cp, free(cp));
  smartlist_clear(sl);

  /* Test string_remove and remove and join_strings2 */
  smartlist_split_string(sl,
                    "Some say the Earth will end in ice and some in fire",
                    " ", 0, 0);
  cp = smartlist_get(sl, 4);
  tt_str_op(cp, ==, "will");
  smartlist_add(sl, cp);
  smartlist_remove(sl, cp);
  free(cp);
  cp_alloc = smartlist_join_strings(sl, ",", 0, NULL);
  tt_str_op(cp_alloc, ==, "Some,say,the,Earth,fire,end,in,ice,and,some,in");
  free(cp_alloc);
  smartlist_string_remove(sl, "in");
  cp_alloc = smartlist_join_strings2(sl, "+XX", 1, 0, &sz);
  tt_str_op(cp_alloc, ==, "Some+say+the+Earth+fire+end+some+ice+and");
  tt_int_op((int)sz, ==, 40);

 end:

  SMARTLIST_FOREACH(sl, char *, cp, free(cp));
  smartlist_free(sl);
  free(cp_alloc);
}
Beispiel #24
0
/**
   Given:
   * comma-separated list of "<transport>-<bindaddr>" strings in 'all_bindaddrs'.
   * comma-separated list of "<transport>" strings in 'all_transports'.

   Return:
   * 0, if
   - all <transport> strings in 'all_bindaddrs' match with <transport>
     strings in 'all_transports' (order matters).
   AND
   - if all <bindaddr> strings in 'all_bindaddrs' are valid addrports.
   * -1, otherwise.
*/
int
validate_bindaddrs(const char *all_bindaddrs, const char *all_transports)
{
  int ret,i,n_bindaddrs,n_transports;
  struct evutil_addrinfo *bindaddr_test;
  char *bindaddr = NULL;
  char *transport = NULL;

  /* a list of "<proto>-<bindaddr>" strings */
  smartlist_t *bindaddrs = smartlist_create();
  /* a list holding (<proto>, <bindaddr>) for each 'bindaddrs' entry */
  smartlist_t *split_bindaddr = NULL;
  /* a list of "<proto>" strings */
  smartlist_t *transports = smartlist_create();

  smartlist_split_string(bindaddrs, all_bindaddrs, ",",
                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
  smartlist_split_string(transports, all_transports, ",",
                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);

  n_bindaddrs = smartlist_len(bindaddrs);
  n_transports = smartlist_len(transports);

  if (n_bindaddrs != n_transports)
    goto err;

  for (i=0;i<n_bindaddrs;i++) {
    bindaddr = smartlist_get(bindaddrs, i);
    transport = smartlist_get(transports, i);

    split_bindaddr = smartlist_create();
    smartlist_split_string(split_bindaddr, bindaddr, "-",
                           SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);

    /* (<proto>, <bindaddr>) */
    if (smartlist_len(split_bindaddr) != 2)
      goto err;

    /* "all <transport> strings in 'all_bindaddrs' match with <transport>
       strings in 'all_transports' (order matters)." */
    if (strcmp(smartlist_get(split_bindaddr,0), transport))
      goto err;

    /* "if all <bindaddr> strings in 'all_bindaddrs' are valid addrports." */
    bindaddr_test = resolve_address_port(smartlist_get(split_bindaddr, 1),
                                         1, 1, NULL);
    if (!bindaddr_test)
      goto err;

    evutil_freeaddrinfo(bindaddr_test);
    SMARTLIST_FOREACH(split_bindaddr, char *, cp, free(cp));
    smartlist_free(split_bindaddr);
    split_bindaddr = NULL;
  }

  ret = 0;
  goto done;

 err:
  ret = -1;

 done:
  SMARTLIST_FOREACH(bindaddrs, char *, cp, free(cp));
  smartlist_free(bindaddrs);
  SMARTLIST_FOREACH(transports, char *, cp, free(cp));
  smartlist_free(transports);
  if (split_bindaddr) {
    SMARTLIST_FOREACH(split_bindaddr, char *, cp, free(cp));
    smartlist_free(split_bindaddr);
  }

  return ret;
}
Beispiel #25
0
/* Test the configure_proxy() function. */
static void
test_pt_configure_proxy(void *arg)
{
  int i, retval;
  managed_proxy_t *mp = NULL;
  (void) arg;

  dummy_state = tor_malloc_zero(sizeof(or_state_t));

  MOCK(tor_get_lines_from_handle,
       tor_get_lines_from_handle_replacement);
  MOCK(tor_process_handle_destroy,
       tor_process_handle_destroy_replacement);
  MOCK(get_or_state,
       get_or_state_replacement);
  MOCK(queue_control_event_string,
       queue_control_event_string_replacement);

  control_testing_set_global_event_mask(EVENT_TRANSPORT_LAUNCHED);

  mp = tor_malloc_zero(sizeof(managed_proxy_t));
  mp->conf_state = PT_PROTO_ACCEPTING_METHODS;
  mp->transports = smartlist_new();
  mp->transports_to_launch = smartlist_new();
  mp->process_handle = tor_malloc_zero(sizeof(process_handle_t));
  mp->argv = tor_malloc_zero(sizeof(char*)*2);
  mp->argv[0] = tor_strdup("<testcase>");
  mp->is_server = 1;

  /* Test the return value of configure_proxy() by calling it some
     times while it is uninitialized and then finally finalizing its
     configuration. */
  for (i = 0 ; i < 5 ; i++) {
    retval = configure_proxy(mp);
    /* retval should be zero because proxy hasn't finished configuring yet */
    tt_int_op(retval, OP_EQ, 0);
    /* check the number of registered transports */
    tt_assert(smartlist_len(mp->transports) == i+1);
    /* check that the mp is still waiting for transports */
    tt_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS);
  }

  /* this last configure_proxy() should finalize the proxy configuration. */
  retval = configure_proxy(mp);
  /* retval should be 1 since the proxy finished configuring */
  tt_int_op(retval, OP_EQ, 1);
  /* check the mp state */
  tt_assert(mp->conf_state == PT_PROTO_COMPLETED);

  tt_int_op(controlevent_n, OP_EQ, 5);
  tt_int_op(controlevent_event, OP_EQ, EVENT_TRANSPORT_LAUNCHED);
  tt_int_op(smartlist_len(controlevent_msgs), OP_EQ, 5);
  smartlist_sort_strings(controlevent_msgs);
  tt_str_op(smartlist_get(controlevent_msgs, 0), OP_EQ,
            "650 TRANSPORT_LAUNCHED server mock1 127.0.0.1 5551\r\n");
  tt_str_op(smartlist_get(controlevent_msgs, 1), OP_EQ,
            "650 TRANSPORT_LAUNCHED server mock2 127.0.0.1 5552\r\n");
  tt_str_op(smartlist_get(controlevent_msgs, 2), OP_EQ,
            "650 TRANSPORT_LAUNCHED server mock3 127.0.0.1 5553\r\n");
  tt_str_op(smartlist_get(controlevent_msgs, 3), OP_EQ,
            "650 TRANSPORT_LAUNCHED server mock4 127.0.0.1 5554\r\n");
  tt_str_op(smartlist_get(controlevent_msgs, 4), OP_EQ,
            "650 TRANSPORT_LAUNCHED server mock5 127.0.0.1 5555\r\n");

  { /* check that the transport info were saved properly in the tor state */
    config_line_t *transport_in_state = NULL;
    smartlist_t *transport_info_sl = smartlist_new();
    char *name_of_transport = NULL;
    char *bindaddr = NULL;

    /* Get the bindaddr for "mock1" and check it against the bindaddr
       that the mocked tor_get_lines_from_handle() generated. */
    transport_in_state = get_transport_in_state_by_name("mock1");
    tt_assert(transport_in_state);
    smartlist_split_string(transport_info_sl, transport_in_state->value,
                           NULL, 0, 0);
    name_of_transport = smartlist_get(transport_info_sl, 0);
    bindaddr = smartlist_get(transport_info_sl, 1);
    tt_str_op(name_of_transport, OP_EQ, "mock1");
    tt_str_op(bindaddr, OP_EQ, "127.0.0.1:5551");

    SMARTLIST_FOREACH(transport_info_sl, char *, cp, tor_free(cp));
    smartlist_free(transport_info_sl);
  }

 done:
  or_state_free(dummy_state);
  UNMOCK(tor_get_lines_from_handle);
  UNMOCK(tor_process_handle_destroy);
  UNMOCK(get_or_state);
  UNMOCK(queue_control_event_string);
  if (controlevent_msgs) {
    SMARTLIST_FOREACH(controlevent_msgs, char *, cp, tor_free(cp));
    smartlist_free(controlevent_msgs);
    controlevent_msgs = NULL;
  }
  if (mp->transports) {
    SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
    smartlist_free(mp->transports);
  }