LCOV - code coverage report
Current view: top level - feature/dirparse - policy_parse.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 79 85 92.9 %
Date: 2021-11-24 03:28:48 Functions: 3 3 100.0 %

          Line data    Source code
       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       54646 : 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       54646 :   directory_token_t *tok = NULL;
      47       54646 :   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       54646 :   char line[TOR_ADDR_BUF_LEN*2 + 32];
      58       54646 :   addr_policy_t *r;
      59       54646 :   memarea_t *area = NULL;
      60             : 
      61       54646 :   tor_assert(malformed_list);
      62       54646 :   *malformed_list = 0;
      63             : 
      64       54646 :   s = eat_whitespace(s);
      65             :   /* We can only do assume_action on []-quoted IPv6, as "a" (accept)
      66             :    * and ":" (port separator) are ambiguous */
      67       54646 :   if ((*s == '*' || *s == '[' || TOR_ISDIGIT(*s)) && assume_action >= 0) {
      68         270 :     if (tor_snprintf(line, sizeof(line), "%s %s",
      69             :                assume_action == ADDR_POLICY_ACCEPT?"accept":"reject", s)<0) {
      70           0 :       log_warn(LD_DIR, "Policy %s is too long.", escaped(s));
      71           0 :       return NULL;
      72             :     }
      73         150 :     cp = line;
      74         150 :     tor_strlower(line);
      75             :   } else { /* assume an already well-formed address policy line */
      76       54496 :     cp = s;
      77             :   }
      78             : 
      79       54646 :   eos = cp + strlen(cp);
      80       54646 :   area = memarea_new();
      81       54646 :   tok = get_next_token(area, &cp, eos, routerdesc_token_table);
      82       54646 :   if (tok->tp == ERR_) {
      83           0 :     log_warn(LD_DIR, "Error reading address policy: %s", tok->error);
      84           0 :     goto err;
      85             :   }
      86       54646 :   if (tok->tp != K_ACCEPT && tok->tp != K_ACCEPT6 &&
      87         296 :       tok->tp != K_REJECT && tok->tp != K_REJECT6) {
      88           4 :     log_warn(LD_DIR, "Expected 'accept' or 'reject'.");
      89           4 :     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       54642 :   r = router_parse_addr_policy(tok, TAPMP_EXTENDED_STAR);
      96       54642 :   if (!r) {
      97          11 :     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       54631 :   if ((tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) &&
     105         295 :        tor_addr_family(&r->addr) != AF_INET6) {
     106             :     /* This is a non-fatal error, just ignore this one entry. */
     107           3 :     *malformed_list = 0;
     108           3 :     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           3 :     addr_policy_free(r);
     113           3 :     r = NULL;
     114           3 :     goto done;
     115             :   }
     116             : 
     117       54628 :   goto done;
     118          15 :  err:
     119          15 :   *malformed_list = 1;
     120          15 :   r = NULL;
     121       54646 :  done:
     122       54646 :   token_clear(tok);
     123       54646 :   if (area) {
     124       54646 :     DUMP_AREA(area, "policy item");
     125       54646 :     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       54943 : router_parse_addr_policy(directory_token_t *tok, unsigned fmt_flags)
     137             : {
     138       54943 :   addr_policy_t newe;
     139       54943 :   char *arg;
     140             : 
     141       54943 :   tor_assert(tok->tp == K_REJECT || tok->tp == K_REJECT6 ||
     142             :              tok->tp == K_ACCEPT || tok->tp == K_ACCEPT6);
     143             : 
     144       54943 :   if (tok->n_args != 1)
     145             :     return NULL;
     146       54942 :   arg = tok->args[0];
     147             : 
     148       54942 :   if (!strcmpstart(arg,"private"))
     149         246 :     return router_parse_addr_policy_private(tok);
     150             : 
     151       54696 :   memset(&newe, 0, sizeof(newe));
     152             : 
     153       54696 :   if (tok->tp == K_REJECT || tok->tp == K_REJECT6)
     154       29018 :     newe.policy_type = ADDR_POLICY_REJECT;
     155             :   else
     156       25678 :     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       54696 :   if ((fmt_flags & TAPMP_EXTENDED_STAR)
     161       54396 :       && (tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6)) {
     162         298 :     fmt_flags |= TAPMP_STAR_IPV6_ONLY;
     163             :   }
     164             : 
     165       54696 :   if (tor_addr_parse_mask_ports(arg, fmt_flags, &newe.addr, &newe.maskbits,
     166             :                                 &newe.prt_min, &newe.prt_max) < 0) {
     167          14 :     log_warn(LD_DIR,"Couldn't parse line %s. Dropping", escaped(arg));
     168          14 :     return NULL;
     169             :   }
     170             : 
     171       54682 :   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       54682 :   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         246 : router_parse_addr_policy_private(directory_token_t *tok)
     190             : {
     191         246 :   const char *arg;
     192         246 :   uint16_t port_min, port_max;
     193         246 :   addr_policy_t result;
     194             : 
     195         246 :   arg = tok->args[0];
     196         246 :   if (strcmpstart(arg, "private"))
     197             :     return NULL;
     198             : 
     199         246 :   arg += strlen("private");
     200         246 :   arg = (char*) eat_whitespace(arg);
     201         246 :   if (!arg || *arg != ':')
     202             :     return NULL;
     203             : 
     204         246 :   if (parse_port_range(arg+1, &port_min, &port_max)<0)
     205             :     return NULL;
     206             : 
     207         246 :   memset(&result, 0, sizeof(result));
     208         246 :   if (tok->tp == K_REJECT || tok->tp == K_REJECT6)
     209         246 :     result.policy_type = ADDR_POLICY_REJECT;
     210             :   else
     211           0 :     result.policy_type = ADDR_POLICY_ACCEPT;
     212         246 :   result.is_private = 1;
     213         246 :   result.prt_min = port_min;
     214         246 :   result.prt_max = port_max;
     215             : 
     216         246 :   if (tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) {
     217           0 :     log_warn(LD_GENERAL,
     218             :              "'%s' expands into rules which apply to all private IPv4 and "
     219             :              "IPv6 addresses. (Use accept/reject private:* for IPv4 and "
     220             :              "IPv6.)", tok->n_args == 1 ? tok->args[0] : "");
     221             :   }
     222             : 
     223         246 :   return addr_policy_get_canonical_entry(&result);
     224             : }

Generated by: LCOV version 1.14