Commit e033d5e9 authored by teor (Tim Wilson-Brown)'s avatar teor (Tim Wilson-Brown)
Browse files

Ignore accept6/reject6 IPv4, warn about unexpected rule outcomes

When parsing torrc ExitPolicies, we now warn if:
  * an IPv4 address is used on an accept6 or reject6 line. The line is
    ignored, but the rest of the policy items in the list are used.
    (accept/reject continue to allow both IPv4 and IPv6 addresses in torrcs.)
  * a "private" address alias is used on an accept6 or reject6 line.
    The line filters both IPv4 and IPv6 private addresses, disregarding
    the 6 in accept6/reject6.

When parsing torrc ExitPolicies, we now issue an info-level message:
  * when expanding an accept/reject * line to include both IPv4 and IPv6
    wildcard addresses.

In each instance, usage advice is provided to avoid the message.

Partial fix for ticket 16069. Patch by "teor".
Patch on 2eb7eafc and a96c0aff (25 Oct 2012),
released in 0.2.4.7-alpha.
parent 60312dc0
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
  o Minor bug fixes (torrc exit policies):
    - When parsing torrc ExitPolicies, we now warn if:
      * an IPv4 address is used on an accept6 or reject6 line. The line is
        ignored, but the rest of the policy items in the list are used.
        (accept/reject continue to allow both IPv4 and IPv6 addresses in
        torrcs.)
      * a "private" address alias is used on an accept6 or reject6 line.
        The line filters both IPv4 and IPv6 private addresses, disregarding
        the 6 in accept6/reject6.
    - When parsing torrc ExitPolicies, we now issue an info-level message:
      * when expanding an accept/reject * line to include both IPv4 and IPv6
        wildcard addresses.
    - In each instance, usage advice is provided to avoid the message.
      Partial fix for ticket 16069. Patch by "teor".
      Patch on 2eb7eafc9d78 and a96c0affcb4c (25 Oct 2012),
      released in 0.2.4.7-alpha.
+4 −0
Original line number Diff line number Diff line
@@ -690,6 +690,10 @@ tor_addr_parse_mask_ports(const char *s,
    if (flags & TAPMP_EXTENDED_STAR) {
      family = AF_UNSPEC;
      tor_addr_make_unspec(addr_out);
      log_info(LD_GENERAL,
               "'%s' expands into rules which apply to all IPv4 and IPv6 "
               "addresses. (Use accept/reject *4:* for IPv4 or "
               "accept[6]/reject[6] *6:* for IPv6.)", s);
    } else {
      family = AF_INET;
      tor_addr_from_ipv4h(addr_out, 0);
+16 −3
Original line number Diff line number Diff line
@@ -167,6 +167,7 @@ parse_addr_policy(config_line_t *cfg, smartlist_t **dest,
  smartlist_t *result;
  smartlist_t *entries;
  addr_policy_t *item;
  int malformed_list;
  int r = 0;

  if (!cfg)
@@ -179,12 +180,22 @@ parse_addr_policy(config_line_t *cfg, smartlist_t **dest,
                           SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
    SMARTLIST_FOREACH_BEGIN(entries, const char *, ent) {
      log_debug(LD_CONFIG,"Adding new entry '%s'",ent);
      item = router_parse_addr_policy_item_from_string(ent, assume_action);
      malformed_list = 0;
      item = router_parse_addr_policy_item_from_string(ent, assume_action,
                                                       &malformed_list);
      if (item) {
        smartlist_add(result, item);
      } else {
        log_warn(LD_CONFIG,"Malformed policy '%s'.", ent);
      } else if (malformed_list) {
        /* the error is so severe the entire list should be discarded */
        log_warn(LD_CONFIG, "Malformed policy '%s'. Discarding entire policy "
                 "list.", ent);
        r = -1;
      } else {
        /* the error is minor: don't add the item, but keep processing the
         * rest of the policies in the list */
        log_debug(LD_CONFIG, "Ignored policy '%s' due to non-fatal error. "
                  "The remainder of the policy list will be used.",
                  ent);
      }
    } SMARTLIST_FOREACH_END(ent);
    SMARTLIST_FOREACH(entries, char *, ent, tor_free(ent));
@@ -568,6 +579,8 @@ cmp_single_addr_policy(addr_policy_t *a, addr_policy_t *b)
    return r;
  if ((r=((int)a->is_private - (int)b->is_private)))
    return r;
  /* refcnt and is_canonical are irrelevant to equality,
   * they are hash table implementation details */
  if ((r=tor_addr_compare(&a->addr, &b->addr, CMP_EXACT)))
    return r;
  if ((r=((int)a->maskbits - (int)b->maskbits)))
+49 −2
Original line number Diff line number Diff line
@@ -3666,12 +3666,20 @@ networkstatus_parse_detached_signatures(const char *s, const char *eos)
 * assume_action is nonnegative, then insert its action (ADDR_POLICY_ACCEPT or
 * ADDR_POLICY_REJECT) for items that specify no action.
 *
 * Returns NULL on policy errors.
 *
 * If there is a policy error, malformed_list is set to true if the entire
 * policy list should be discarded. Otherwise, it is set to false, and only
 * this item should be ignored - the rest of the policy list can continue to
 * be processed and used.
 *
 * The addr_policy_t returned by this function can have its address set to
 * AF_UNSPEC for '*'.  Use policy_expand_unspec() to turn this into a pair
 * of AF_INET and AF_INET6 items.
 */
MOCK_IMPL(addr_policy_t *,
router_parse_addr_policy_item_from_string,(const char *s, int assume_action))
router_parse_addr_policy_item_from_string,(const char *s, int assume_action,
                                           int *malformed_list))
{
  directory_token_t *tok = NULL;
  const char *cp, *eos;
@@ -3688,6 +3696,8 @@ router_parse_addr_policy_item_from_string,(const char *s, int assume_action))
  addr_policy_t *r;
  memarea_t *area = NULL;

  tor_assert(malformed_list);

  s = eat_whitespace(s);
  if ((*s == '*' || TOR_ISDIGIT(*s)) && assume_action >= 0) {
    if (tor_snprintf(line, sizeof(line), "%s %s",
@@ -3714,9 +3724,32 @@ router_parse_addr_policy_item_from_string,(const char *s, int assume_action))
    goto err;
  }

  /* Use the extended interpretation of accept/reject *,
   * expanding it into an IPv4 wildcard and an IPv6 wildcard.
   * Also permit *4 and *6 for IPv4 and IPv6 only wildcards. */
  r = router_parse_addr_policy(tok, TAPMP_EXTENDED_STAR);
  if (!r) {
    goto err;
  }

  /* Ensure that accept6/reject6 fields are followed by IPv6 addresses.
   * AF_UNSPEC addresses are only permitted on the accept/reject field type.
   * Unlike descriptors, torrcs exit policy accept/reject can be followed by
   * either an IPv4 or IPv6 address. */
  if ((tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) &&
       tor_addr_family(&r->addr) != AF_INET6) {
    /* This is a non-fatal error, just ignore this one entry. */
    *malformed_list = 0;
    log_warn(LD_DIR, "IPv4 address '%s' with accept6/reject6 field type in "
             "exit policy. Ignoring, but continuing to parse rules. (Use "
             "accept/reject with IPv4 addresses.)",
             tok->n_args == 1 ? tok->args[0] : "");
    return NULL;
  }

  goto done;
 err:
  *malformed_list = 1;
  r = NULL;
 done:
  token_clear(tok);
@@ -3733,19 +3766,26 @@ static int
router_add_exit_policy(routerinfo_t *router, directory_token_t *tok)
{
  addr_policy_t *newe;
  /* Use the standard interpretation of accept/reject *, an IPv4 wildcard. */
  newe = router_parse_addr_policy(tok, 0);
  if (!newe)
    return -1;
  if (! router->exit_policy)
    router->exit_policy = smartlist_new();

  /* Ensure that in descriptors, accept/reject fields are followed by
   * IPv4 addresses, and accept6/reject6 fields are followed by
   * IPv6 addresses. Unlike torrcs, descriptor exit policies do not permit
   * accept/reject followed by IPv6. */
  if (((tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) &&
       tor_addr_family(&newe->addr) == AF_INET)
      ||
      ((tok->tp == K_ACCEPT || tok->tp == K_REJECT) &&
       tor_addr_family(&newe->addr) == AF_INET6)) {
    /* There's nothing the user can do about other relays' descriptors,
     * so we don't provide usage advice here. */
    log_warn(LD_DIR, "Mismatch between field type and address type in exit "
             "policy");
             "policy '%s'. Ignoring.", tok->n_args == 1 ? tok->args[0] : "");
    addr_policy_free(newe);
    return -1;
  }
@@ -3821,6 +3861,13 @@ router_parse_addr_policy_private(directory_token_t *tok)
  result.prt_min = port_min;
  result.prt_max = port_max;

  if (tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) {
    log_warn(LD_GENERAL,
             "'%s' expands into rules which apply to all private IPv4 and "
             "IPv6 addresses. (Use accept/reject private:* for IPv4 and "
             "IPv6.)", tok->n_args == 1 ? tok->args[0] : "");
  }

  return addr_policy_get_canonical_entry(&result);
}

+1 −1
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ extrainfo_t *extrainfo_parse_entry_from_string(const char *s, const char *end,
                             int cache_copy, struct digest_ri_map_t *routermap,
                             int *can_dl_again_out);
MOCK_DECL(addr_policy_t *, router_parse_addr_policy_item_from_string,
    (const char *s, int assume_action));
         (const char *s, int assume_action, int *malformed_list));
version_status_t tor_version_is_obsolete(const char *myversion,
                                         const char *versionlist);
int tor_version_as_new_as(const char *platform, const char *cutoff);
Loading