tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

policy_parse.c (7843B)


      1 /* Copyright (c) 2001 Matej Pfajfar.
      2 * Copyright (c) 2001-2004, Roger Dingledine.
      3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
      4 * Copyright (c) 2007-2021, The Tor Project, Inc. */
      5 /* See LICENSE for licensing information */
      6 
      7 /**
      8 * \file policy_parse.c
      9 * \brief Code to parse address policies.
     10 **/
     11 
     12 #define  ROUTERDESC_TOKEN_TABLE_PRIVATE
     13 
     14 #include "core/or/or.h"
     15 
     16 #include "core/or/policies.h"
     17 #include "feature/dirparse/parsecommon.h"
     18 #include "feature/dirparse/policy_parse.h"
     19 #include "feature/dirparse/routerparse.h"
     20 #include "feature/dirparse/unparseable.h"
     21 #include "lib/memarea/memarea.h"
     22 
     23 #include "core/or/addr_policy_st.h"
     24 
     25 static addr_policy_t *router_parse_addr_policy_private(directory_token_t *tok);
     26 
     27 /** Parse the addr policy in the string <b>s</b> and return it.  If
     28 * assume_action is nonnegative, then insert its action (ADDR_POLICY_ACCEPT or
     29 * ADDR_POLICY_REJECT) for items that specify no action.
     30 *
     31 * Returns NULL on policy errors.
     32 *
     33 * Set *<b>malformed_list</b> to true if the entire policy list should be
     34 * discarded. Otherwise, set it to false, and only this item should be ignored
     35 * on error - the rest of the policy list can continue to be processed and
     36 * used.
     37 *
     38 * The addr_policy_t returned by this function can have its address set to
     39 * AF_UNSPEC for '*'.  Use policy_expand_unspec() to turn this into a pair
     40 * of AF_INET and AF_INET6 items.
     41 */
     42 MOCK_IMPL(addr_policy_t *,
     43 router_parse_addr_policy_item_from_string,(const char *s, int assume_action,
     44                                           int *malformed_list))
     45 {
     46  directory_token_t *tok = NULL;
     47  const char *cp, *eos;
     48  /* Longest possible policy is
     49   * "accept6 [ffff:ffff:..255]/128:10000-65535",
     50   * which contains a max-length IPv6 address, plus 26 characters.
     51   * But note that there can be an arbitrary amount of space between the
     52   * accept and the address:mask/port element.
     53   * We don't need to multiply TOR_ADDR_BUF_LEN by 2, as there is only one
     54   * IPv6 address. But making the buffer shorter might cause valid long lines,
     55   * which parsed in previous versions, to fail to parse in new versions.
     56   * (These lines would have to have excessive amounts of whitespace.) */
     57  char line[TOR_ADDR_BUF_LEN*2 + 32];
     58  addr_policy_t *r;
     59  memarea_t *area = NULL;
     60 
     61  tor_assert(malformed_list);
     62  *malformed_list = 0;
     63 
     64  s = eat_whitespace(s);
     65  /* We can only do assume_action on []-quoted IPv6, as "a" (accept)
     66   * and ":" (port separator) are ambiguous */
     67  if ((*s == '*' || *s == '[' || TOR_ISDIGIT(*s)) && assume_action >= 0) {
     68    if (tor_snprintf(line, sizeof(line), "%s %s",
     69               assume_action == ADDR_POLICY_ACCEPT?"accept":"reject", s)<0) {
     70      log_warn(LD_DIR, "Policy %s is too long.", escaped(s));
     71      return NULL;
     72    }
     73    cp = line;
     74    tor_strlower(line);
     75  } else { /* assume an already well-formed address policy line */
     76    cp = s;
     77  }
     78 
     79  eos = cp + strlen(cp);
     80  area = memarea_new();
     81  tok = get_next_token(area, &cp, eos, routerdesc_token_table);
     82  if (tok->tp == ERR_) {
     83    log_warn(LD_DIR, "Error reading address policy: %s", tok->error);
     84    goto err;
     85  }
     86  if (tok->tp != K_ACCEPT && tok->tp != K_ACCEPT6 &&
     87      tok->tp != K_REJECT && tok->tp != K_REJECT6) {
     88    log_warn(LD_DIR, "Expected 'accept' or 'reject'.");
     89    goto err;
     90  }
     91 
     92  /* Use the extended interpretation of accept/reject *,
     93   * expanding it into an IPv4 wildcard and an IPv6 wildcard.
     94   * Also permit *4 and *6 for IPv4 and IPv6 only wildcards. */
     95  r = router_parse_addr_policy(tok, TAPMP_EXTENDED_STAR);
     96  if (!r) {
     97    goto err;
     98  }
     99 
    100  /* Ensure that accept6/reject6 fields are followed by IPv6 addresses.
    101   * AF_UNSPEC addresses are only permitted on the accept/reject field type.
    102   * Unlike descriptors, torrcs exit policy accept/reject can be followed by
    103   * either an IPv4 or IPv6 address. */
    104  if ((tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) &&
    105       tor_addr_family(&r->addr) != AF_INET6) {
    106    /* This is a non-fatal error, just ignore this one entry. */
    107    *malformed_list = 0;
    108    log_warn(LD_DIR, "IPv4 address '%s' with accept6/reject6 field type in "
    109             "exit policy. Ignoring, but continuing to parse rules. (Use "
    110             "accept/reject with IPv4 addresses.)",
    111             tok->n_args == 1 ? tok->args[0] : "");
    112    addr_policy_free(r);
    113    r = NULL;
    114    goto done;
    115  }
    116 
    117  goto done;
    118 err:
    119  *malformed_list = 1;
    120  r = NULL;
    121 done:
    122  token_clear(tok);
    123  if (area) {
    124    DUMP_AREA(area, "policy item");
    125    memarea_drop_all(area);
    126  }
    127  return r;
    128 }
    129 
    130 /** Given a K_ACCEPT[6] or K_REJECT[6] token and a router, create and return
    131 * a new exit_policy_t corresponding to the token. If TAPMP_EXTENDED_STAR
    132 * is set in fmt_flags, K_ACCEPT6 and K_REJECT6 tokens followed by *
    133 * expand to IPv6-only policies, otherwise they expand to IPv4 and IPv6
    134 * policies */
    135 addr_policy_t *
    136 router_parse_addr_policy(directory_token_t *tok, unsigned fmt_flags)
    137 {
    138  addr_policy_t newe;
    139  char *arg;
    140 
    141  tor_assert(tok->tp == K_REJECT || tok->tp == K_REJECT6 ||
    142             tok->tp == K_ACCEPT || tok->tp == K_ACCEPT6);
    143 
    144  if (tok->n_args != 1)
    145    return NULL;
    146  arg = tok->args[0];
    147 
    148  if (!strcmpstart(arg,"private"))
    149    return router_parse_addr_policy_private(tok);
    150 
    151  memset(&newe, 0, sizeof(newe));
    152 
    153  if (tok->tp == K_REJECT || tok->tp == K_REJECT6)
    154    newe.policy_type = ADDR_POLICY_REJECT;
    155  else
    156    newe.policy_type = ADDR_POLICY_ACCEPT;
    157 
    158  /* accept6/reject6 * produces an IPv6 wildcard address only.
    159   * (accept/reject * produces rules for IPv4 and IPv6 wildcard addresses.) */
    160  if ((fmt_flags & TAPMP_EXTENDED_STAR)
    161      && (tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6)) {
    162    fmt_flags |= TAPMP_STAR_IPV6_ONLY;
    163  }
    164 
    165  if (tor_addr_parse_mask_ports(arg, fmt_flags, &newe.addr, &newe.maskbits,
    166                                &newe.prt_min, &newe.prt_max) < 0) {
    167    log_warn(LD_DIR,"Couldn't parse line %s. Dropping", escaped(arg));
    168    return NULL;
    169  }
    170 
    171  addr_policy_t *result = addr_policy_get_canonical_entry(&newe);
    172  /* It would be a nasty error to return 'newe', and sometimes
    173   * addr_policy_get_canonical_entry() can return its argument.  But in this
    174   * case, it won't, since newe is *not* canonical.  We assert here to make
    175   * sure that the compiler knows it too.
    176   */
    177  tor_assert(result != &newe);
    178  return result;
    179 }
    180 
    181 /** Parse an exit policy line of the format "accept[6]/reject[6] private:...".
    182 * This didn't exist until Tor 0.1.1.15, so nobody should generate it in
    183 * router descriptors until earlier versions are obsolete.
    184 *
    185 * accept/reject and accept6/reject6 private all produce rules for both
    186 * IPv4 and IPv6 addresses.
    187 */
    188 static addr_policy_t *
    189 router_parse_addr_policy_private(directory_token_t *tok)
    190 {
    191  const char *arg;
    192  uint16_t port_min, port_max;
    193  addr_policy_t result;
    194 
    195  /* Safeguard: always flag non canonical because it is a stack allocated
    196   * object and thus should not be considered a copy stored in a map. */
    197  result.is_canonical = 0;
    198 
    199  arg = tok->args[0];
    200  if (strcmpstart(arg, "private"))
    201    return NULL;
    202 
    203  arg += strlen("private");
    204  arg = (char*) eat_whitespace(arg);
    205  if (!arg || *arg != ':')
    206    return NULL;
    207 
    208  if (parse_port_range(arg+1, &port_min, &port_max)<0)
    209    return NULL;
    210 
    211  memset(&result, 0, sizeof(result));
    212  if (tok->tp == K_REJECT || tok->tp == K_REJECT6)
    213    result.policy_type = ADDR_POLICY_REJECT;
    214  else
    215    result.policy_type = ADDR_POLICY_ACCEPT;
    216  result.is_private = 1;
    217  result.prt_min = port_min;
    218  result.prt_max = port_max;
    219 
    220  if (tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) {
    221    log_warn(LD_GENERAL,
    222             "'%s' expands into rules which apply to all private IPv4 and "
    223             "IPv6 addresses. (Use accept/reject private:* for IPv4 and "
    224             "IPv6.)", tok->n_args == 1 ? tok->args[0] : "");
    225  }
    226 
    227  return addr_policy_get_canonical_entry(&result);
    228 }