Exemple #1
0
static void
NS(test_main)(void *arg)
{
  const routerset_t *set;
  int needs_geoip;
  (void)arg;

  set = NULL;
  needs_geoip = routerset_needs_geoip(set);
  tt_int_op(needs_geoip, ==, 0);

  set = routerset_new();
  needs_geoip = routerset_needs_geoip(set);
  routerset_free((routerset_t *)set);
  tt_int_op(needs_geoip, ==, 0);
  set = NULL;

  set = routerset_new();
  smartlist_add(set->country_names, tor_strndup("xx", 2));
  needs_geoip = routerset_needs_geoip(set);
  routerset_free((routerset_t *)set);
  set = NULL;
  tt_int_op(needs_geoip, !=, 0);

  done:
    ;
}
Exemple #2
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 {
Exemple #3
0
static void
NS(test_main)(void *arg)
{
  routerset_t *set = routerset_new();
  (void)arg;

  NS_MOCK(geoip_is_loaded);
  NS_MOCK(geoip_get_n_countries);
  NS_MOCK(geoip_get_country);
  smartlist_add(set->country_names, tor_strndup("foo", 3));

  routerset_refresh_countries(set);

  tt_ptr_op(set->countries, !=, NULL);
  tt_int_op(set->n_countries, ==, 2);
  tt_int_op(CALLED(geoip_is_loaded), ==, 1);
  tt_int_op(CALLED(geoip_get_n_countries), ==, 1);
  tt_int_op(CALLED(geoip_get_country), ==, 1);
  tt_int_op((unsigned int)(*set->countries), ==, 0);

  done:
    NS_UNMOCK(geoip_is_loaded);
    NS_UNMOCK(geoip_get_n_countries);
    NS_UNMOCK(geoip_get_country);
    routerset_free(set);
}
Exemple #4
0
static void
NS(test_main)(void *arg)
{
  routerset_t *set;
  addr_policy_t *policy;
  int is_list;
  (void)arg;

  /* len(set->country_names) == 0, len(set->policies) == 0 */
  set = routerset_new();
  is_list = routerset_is_list(set);
  routerset_free(set);
  set = NULL;
  tt_int_op(is_list, !=, 0);

  /* len(set->country_names) != 0, len(set->policies) == 0 */
  set = routerset_new();
  smartlist_add(set->country_names, tor_strndup("foo", 3));
  is_list = routerset_is_list(set);
  routerset_free(set);
  set = NULL;
  tt_int_op(is_list, ==, 0);

  /* len(set->country_names) == 0, len(set->policies) != 0 */
  set = routerset_new();
  policy = tor_malloc_zero(sizeof(addr_policy_t));
  smartlist_add(set->policies, (void *)policy);
  is_list = routerset_is_list(set);
  routerset_free(set);
  set = NULL;
  tt_int_op(is_list, ==, 0);

  /* len(set->country_names) != 0, len(set->policies) != 0 */
  set = routerset_new();
  smartlist_add(set->country_names, tor_strndup("foo", 3));
  policy = tor_malloc_zero(sizeof(addr_policy_t));
  smartlist_add(set->policies, (void *)policy);
  is_list = routerset_is_list(set);
  routerset_free(set);
  set = NULL;
  tt_int_op(is_list, ==, 0);

  done:
    ;
}
Exemple #5
0
/**
 * Split a string <b>str</b> along all occurrences of <b>sep</b>,
 * adding the split strings, in order, to <b>sl</b>.
 *
 * If <b>flags</b>&amp;SPLIT_SKIP_SPACE is true, remove initial and
 * trailing space from each entry.
 * If <b>flags</b>&amp;SPLIT_IGNORE_BLANK is true, remove any entries
 * of length 0.
 * If <b>flags</b>&amp;SPLIT_STRIP_SPACE is true, strip spaces from each
 * split string.
 *
 * If max>0, divide the string into no more than <b>max</b> pieces. If
 * <b>sep</b> is NULL, split on any sequence of horizontal space.
 */
int
smartlist_split_string(smartlist_t *sl, const char *str, const char *sep,
                       int flags, int max)
{
  const char *cp, *end, *next;
  int n = 0;

  tor_assert(sl);
  tor_assert(str);

  cp = str;
  while (1) {
    if (flags&SPLIT_SKIP_SPACE) {
      while (TOR_ISSPACE(*cp)) ++cp;
    }

    if (max>0 && n == max-1) {
      end = strchr(cp,'\0');
    } else if (sep) {
      end = strstr(cp,sep);
      if (!end)
        end = strchr(cp,'\0');
    } else {
      for (end = cp; *end && *end != '\t' && *end != ' '; ++end)
        ;
    }

    tor_assert(end);

    if (!*end) {
      next = NULL;
    } else if (sep) {
      next = end+strlen(sep);
    } else {
      next = end+1;
      while (*next == '\t' || *next == ' ')
        ++next;
    }

    if (flags&SPLIT_SKIP_SPACE) {
      while (end > cp && TOR_ISSPACE(*(end-1)))
        --end;
    }
    if (end != cp || !(flags&SPLIT_IGNORE_BLANK)) {
      char *string = tor_strndup(cp, end-cp);
      if (flags&SPLIT_STRIP_SPACE)
        tor_strstrip(string, " ");
      smartlist_add(sl, string);
      ++n;
    }
    if (!next)
      break;
    cp = next;
  }

  return n;
}
Exemple #6
0
/** Read a tagged-data file from <b>fname</b> into the
 * <b>data_out_len</b>-byte buffer in <b>data_out</b>. Check that the
 * typestring matches <b>typestring</b>; store the tag into a newly allocated
 * string in <b>tag_out</b>. Return -1 on failure, and the number of bytes of
 * data on success.  Preserves the errno from reading the file. */
ssize_t
crypto_read_tagged_contents_from_file(const char *fname,
                                      const char *typestring,
                                      char **tag_out,
                                      uint8_t *data_out,
                                      ssize_t data_out_len)
{
  char prefix[33];
  char *content = NULL;
  struct stat st;
  ssize_t r = -1;
  size_t st_size = 0;
  int saved_errno = 0;

  *tag_out = NULL;
  st.st_size = 0;
  content = read_file_to_str(fname, RFTS_BIN|RFTS_IGNORE_MISSING, &st);
  if (! content) {
    saved_errno = errno;
    goto end;
  }
  if (st.st_size < 32 || st.st_size > 32 + data_out_len) {
    saved_errno = EINVAL;
    goto end;
  }
  st_size = (size_t)st.st_size;

  memcpy(prefix, content, 32);
  prefix[32] = 0;
  /* Check type, extract tag. */
  if (strcmpstart(prefix, "== ") || strcmpend(prefix, " ==") ||
      ! tor_mem_is_zero(prefix+strlen(prefix), 32-strlen(prefix))) {
    saved_errno = EINVAL;
    goto end;
  }

  if (strcmpstart(prefix+3, typestring) ||
      3+strlen(typestring) >= 32 ||
      strcmpstart(prefix+3+strlen(typestring), ": ")) {
    saved_errno = EINVAL;
    goto end;
  }

  *tag_out = tor_strndup(prefix+5+strlen(typestring),
                         strlen(prefix)-8-strlen(typestring));

  memcpy(data_out, content+32, st_size-32);
  r = st_size - 32;

 end:
  if (content)
    memwipe(content, 0, st_size);
  tor_free(content);
  if (saved_errno)
    errno = saved_errno;
  return r;
}
Exemple #7
0
/** If <b>c</b> is a country code in the form {cc}, return a newly allocated
 * string holding the "cc" part.  Else, return NULL. */
static char *
routerset_get_countryname(const char *c)
{
  char *country;

  if (strlen(c) < 4 || c[0] !='{' || c[3] !='}')
    return NULL;

  country = tor_strndup(c+1, 2);
  tor_strlower(country);
  return country;
}
Exemple #8
0
/** Parse a string of the form "host[:port]" from <b>addrport</b>.  If
 * <b>address</b> is provided, set *<b>address</b> to a copy of the
 * host portion of the string.  If <b>addr</b> is provided, try to
 * resolve the host portion of the string and store it into
 * *<b>addr</b> (in host byte order).  If <b>port_out</b> is provided,
 * store the port number into *<b>port_out</b>, or 0 if no port is given.
 * If <b>port_out</b> is NULL, then there must be no port number in
 * <b>addrport</b>.
 * Return 0 on success, -1 on failure.
 */
int
parse_addr_port(int severity, const char *addrport, char **address,
                uint32_t *addr, uint16_t *port_out)
{
  const char *colon;
  char *_address = NULL;
  int _port;
  int ok = 1;

  assert(addrport);

  colon = strchr(addrport, ':');
  if (colon) {
    _address = tor_strndup(addrport, colon-addrport);
    _port = (int) parse_long(colon+1,10,1,65535,NULL,NULL);
    if (!_port) {
      fprintf(stderr, "Port %s out of range\n", colon+1);
      ok = 0;
    }
    if (!port_out) {
      fprintf(stderr, "Port %s given on %s when not required\n",
	      colon+1, addrport);
      ok = 0;
    }
  } else {
    _address = strdup(addrport);
    _port = 0;
  }

  if (addr) {
    /* There's an addr pointer, so we need to resolve the hostname. */
    if (lookup_hostname(_address,addr)) {
      fprintf(stderr, "Couldn't look up %s\n", _address);
      ok = 0;
      *addr = 0;
    }
  }

  if (address && ok) {
    *address = _address;
  } else {
    if (address)
      *address = NULL;
    free(_address);
  }
  if (port_out)
    *port_out = ok ? ((uint16_t) _port) : 0;

  return ok ? 0 : -1;
}
Exemple #9
0
static void
NS(test_main)(void *arg)
{
  routerset_t *set = NULL;
  char *s = NULL;
  (void)arg;

  set = NULL;
  s = routerset_to_string(set);
  tt_str_op(s, ==, "");
  tor_free(s);

  set = routerset_new();
  s = routerset_to_string(set);
  tt_str_op(s, ==, "");
  tor_free(s);
  routerset_free(set); set = NULL;

  set = routerset_new();
  smartlist_add(set->list, tor_strndup("a", 1));
  s = routerset_to_string(set);
  tt_str_op(s, ==, "a");
  tor_free(s);
  routerset_free(set); set = NULL;

  set = routerset_new();
  smartlist_add(set->list, tor_strndup("a", 1));
  smartlist_add(set->list, tor_strndup("b", 1));
  s = routerset_to_string(set);
  tt_str_op(s, ==, "a,b");
  tor_free(s);
  routerset_free(set); set = NULL;

 done:
  tor_free(s);
  routerset_free((routerset_t *)set);
}
Exemple #10
0
/** Tell the dns request waiting for an answer on <b>conn</b> that we have an
 * answer of type <b>answer_type</b> (RESOLVE_TYPE_IPV4/IPV6/ERR), of length
 * <b>answer_len</b>, in <b>answer</b>, with TTL <b>ttl</b>.  Doesn't do
 * any caching; that's handled elsewhere. */
void
dnsserv_resolved(entry_connection_t *conn,
                 int answer_type,
                 size_t answer_len,
                 const char *answer,
                 int ttl)
{
  struct evdns_server_request *req = conn->dns_server_request;
  const char *name;
  int err = DNS_ERR_NONE;
  if (!req)
    return;
  name = evdns_get_orig_address(req, answer_type,
                                conn->socks_request->address);

  /* XXXX Re-do; this is dumb. */
  if (ttl < 60)
    ttl = 60;

  /* The evdns interface is: add a bunch of reply items (corresponding to one
   * or more of the questions in the request); then, call
   * evdns_server_request_respond. */
  if (answer_type == RESOLVED_TYPE_IPV6) {
    evdns_server_request_add_aaaa_reply(req,
                                        name,
                                        1, answer, ttl);
  } else if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4 &&
             conn->socks_request->command == SOCKS_COMMAND_RESOLVE) {
    evdns_server_request_add_a_reply(req,
                                     name,
                                     1, answer, ttl);
  } else if (answer_type == RESOLVED_TYPE_HOSTNAME &&
             answer_len < 256 &&
             conn->socks_request->command == SOCKS_COMMAND_RESOLVE_PTR) {
    char *ans = tor_strndup(answer, answer_len);
    evdns_server_request_add_ptr_reply(req, NULL,
                                       name,
                                       ans, ttl);
    tor_free(ans);
  } else if (answer_type == RESOLVED_TYPE_ERROR) {
    err = DNS_ERR_NOTEXIST;
  } else { /* answer_type == RESOLVED_TYPE_ERROR_TRANSIENT */
    err = DNS_ERR_SERVERFAILED;
  }

  evdns_server_request_respond(req, err);

  conn->dns_server_request = NULL;
}
Exemple #11
0
/** Remove all TRACKEXIT mappings from the addressmap for which the target
 * host is unknown or no longer allowed, or for which the source address
 * is no longer in trackexithosts. */
void
addressmap_clear_excluded_trackexithosts(const or_options_t *options)
{
  const routerset_t *allow_nodes = options->ExitNodes;
  const routerset_t *exclude_nodes = options->ExcludeExitNodesUnion_;

  if (!addressmap)
    return;
  if (routerset_is_empty(allow_nodes))
    allow_nodes = NULL;
  if (allow_nodes == NULL && routerset_is_empty(exclude_nodes))
    return;

  STRMAP_FOREACH_MODIFY(addressmap, address, addressmap_entry_t *, ent) {
    size_t len;
    const char *target = ent->new_address, *dot;
    char *nodename;
    const node_t *node;

    if (!target) {
      /* DNS resolving in progress */
      continue;
    } else if (strcmpend(target, ".exit")) {
      /* Not a .exit mapping */
      continue;
    } else if (ent->source != ADDRMAPSRC_TRACKEXIT) {
      /* Not a trackexit mapping. */
      continue;
    }
    len = strlen(target);
    if (len < 6)
      continue; /* malformed. */
    dot = target + len - 6; /* dot now points to just before .exit */
    while (dot > target && *dot != '.')
      dot--;
    if (*dot == '.') dot++;
    nodename = tor_strndup(dot, len-5-(dot-target));;
    node = node_get_by_nickname(nodename, 0);
    tor_free(nodename);
    if (!node ||
        (allow_nodes && !routerset_contains_node(allow_nodes, node)) ||
        routerset_contains_node(exclude_nodes, node) ||
        !hostname_in_track_host_exits(options, address)) {
      /* We don't know this one, or we want to be rid of it. */
      addressmap_ent_remove(address, ent);
      MAP_DEL_CURRENT(address);
    }
  } STRMAP_FOREACH_END;
Exemple #12
0
/** Read the passphrase from the passphrase fd. */
static int
load_passphrase(void)
{
  char *cp;
  char buf[1024]; /* "Ought to be enough for anybody." */
  ssize_t n = read_all(passphrase_fd, buf, sizeof(buf), 0);
  if (n < 0) {
    log_err(LD_GENERAL, "Couldn't read from passphrase fd: %s",
            strerror(errno));
    return -1;
  }
  cp = memchr(buf, '\n', n);
  passphrase_len = cp-buf;
  passphrase = tor_strndup(buf, passphrase_len);
  memset(buf, 0, sizeof(buf));
  return 0;
}
Exemple #13
0
/** Read the passphrase from the passphrase fd. */
static int
load_passphrase(void)
{
  char *cp;
  char buf[1024]; /* "Ought to be enough for anybody." */
  memset(buf, 0, sizeof(buf)); /* should be needless */
  ssize_t n = read_all(passphrase_fd, buf, sizeof(buf), 0);
  if (n < 0) {
    log_err(LD_GENERAL, "Couldn't read from passphrase fd: %s",
            strerror(errno));
    return -1;
  }
  /* We'll take everything from the buffer except for optional terminating
   * newline. */
  cp = memchr(buf, '\n', n);
  if (cp == NULL) {
    passphrase_len = n;
  } else {
    passphrase_len = cp-buf;
  }
  passphrase = tor_strndup(buf, passphrase_len);
  memwipe(buf, 0, sizeof(buf));
  return 0;
}
Exemple #14
0
/** Helper: sends a message to the appropriate logfiles, at loglevel
 * <b>severity</b>.  If provided, <b>funcname</b> is prepended to the
 * message.  The actual message is derived as from tor_snprintf(format,ap).
 */
static void
logv(int severity, log_domain_mask_t domain, const char *funcname,
     const char *format, va_list ap)
{
  char buf[10024];
  size_t msg_len = 0;
  int formatted = 0;
  logfile_t *lf;
  char *end_of_prefix=NULL;

  /* Call assert, not tor_assert, since tor_assert calls log on failure. */
  assert(format);
  /* check that severity is sane.  Overrunning the masks array leads to
   * interesting and hard to diagnose effects */
  assert(severity >= LOG_ERR && severity <= LOG_DEBUG);
  LOCK_LOGS();
  lf = logfiles;
  while (lf) {
    if (! (lf->severities->masks[SEVERITY_MASK_IDX(severity)] & domain)) {
      lf = lf->next;
      continue;
    }
    if (! (lf->fd >= 0 || lf->is_syslog || lf->callback)) {
      lf = lf->next;
      continue;
    }
    if (lf->callback && (domain & LD_NOCB)) {
      lf = lf->next;
      continue;
    }
    if (lf->seems_dead) {
      lf = lf->next;
      continue;
    }

    if (!formatted) {
      end_of_prefix =
        format_msg(buf, sizeof(buf), domain, severity, funcname, format, ap,
                   &msg_len);
      formatted = 1;
    }
    if (lf->is_syslog) {
#ifdef HAVE_SYSLOG_H
      char *m = end_of_prefix;
#ifdef MAXLINE
      /* Some syslog implementations have limits on the length of what you can
       * pass them, and some very old ones do not detect overflow so well.
       * Regrettably, they call their maximum line length MAXLINE. */
#if MAXLINE < 64
#warn "MAXLINE is a very low number; it might not be from syslog.h after all"
#endif
      if (msg_len >= MAXLINE)
        m = tor_strndup(end_of_prefix, MAXLINE-1);
#endif
      syslog(severity, "%s", m);
#ifdef MAXLINE
      if (m != end_of_prefix) {
        tor_free(m);
      }
#endif
#endif
      lf = lf->next;
      continue;
    } else if (lf->callback) {
      lf->callback(severity, domain, end_of_prefix);
      lf = lf->next;
      continue;
    }
    if (write_all(lf->fd, buf, msg_len, 0) < 0) { /* error */
      /* don't log the error! mark this log entry to be blown away, and
       * continue. */
      lf->seems_dead = 1;
    }
    lf = lf->next;
  }
  UNLOCK_LOGS();
}