diff options
author | Nick Mathewson <nickm@torproject.org> | 2018-10-01 11:08:09 -0500 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2018-10-01 11:17:19 -0500 |
commit | 35db3f8162f132cec7afc148eda8f7482dbeeb76 (patch) | |
tree | 7c00b06286d5c75f5ab5d854a201031c7e7a0f9a /src/feature/dirparse/routerparse.c | |
parent | 95e2eb9083d2cd9c79c3f4151850c86cbeaf4cc4 (diff) | |
download | tor-35db3f8162f132cec7afc148eda8f7482dbeeb76.tar.gz tor-35db3f8162f132cec7afc148eda8f7482dbeeb76.zip |
Extract addr-policy parsing code.
Diffstat (limited to 'src/feature/dirparse/routerparse.c')
-rw-r--r-- | src/feature/dirparse/routerparse.c | 200 |
1 files changed, 3 insertions, 197 deletions
diff --git a/src/feature/dirparse/routerparse.c b/src/feature/dirparse/routerparse.c index 0e97735643..54c0e89480 100644 --- a/src/feature/dirparse/routerparse.c +++ b/src/feature/dirparse/routerparse.c @@ -51,6 +51,7 @@ **/ #define ROUTERPARSE_PRIVATE +#define EXPOSE_ROUTERDESC_TOKEN_TABLE #include "core/or/or.h" #include "app/config/config.h" @@ -61,6 +62,7 @@ #include "feature/dirauth/shared_random.h" #include "feature/dircommon/voting_schedule.h" #include "feature/dirparse/parsecommon.h" +#include "feature/dirparse/policy_parse.h" #include "feature/dirparse/routerparse.h" #include "feature/hs_common/shared_random_client.h" #include "feature/nodelist/authcert.h" @@ -111,7 +113,7 @@ /****************************************************************************/ /** List of tokens recognized in router descriptors */ -static token_rule_t routerdesc_token_table[] = { +const token_rule_t routerdesc_token_table[] = { T0N("reject", K_REJECT, ARGS, NO_OBJ ), T0N("accept", K_ACCEPT, ARGS, NO_OBJ ), T0N("reject6", K_REJECT6, ARGS, NO_OBJ ), @@ -197,10 +199,6 @@ static token_rule_t extrainfo_token_table[] = { /* static function prototypes */ static int router_add_exit_policy(routerinfo_t *router,directory_token_t *tok); -static addr_policy_t *router_parse_addr_policy(directory_token_t *tok, - unsigned fmt_flags); -static addr_policy_t *router_parse_addr_policy_private(directory_token_t *tok); - static smartlist_t *find_all_exitpolicy(smartlist_t *s); /** Set <b>digest</b> to the SHA-1 digest of the hash of the first router in @@ -1201,109 +1199,6 @@ extrainfo_parse_entry_from_string(const char *s, const char *end, return extrainfo; } -/** Parse the addr policy in the string <b>s</b> and return it. If - * 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. - * - * Set *<b>malformed_list</b> to true if the entire policy list should be - * discarded. Otherwise, set it to false, and only this item should be ignored - * on error - 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, - int *malformed_list)) -{ - directory_token_t *tok = NULL; - const char *cp, *eos; - /* Longest possible policy is - * "accept6 [ffff:ffff:..255]/128:10000-65535", - * which contains a max-length IPv6 address, plus 26 characters. - * But note that there can be an arbitrary amount of space between the - * accept and the address:mask/port element. - * We don't need to multiply TOR_ADDR_BUF_LEN by 2, as there is only one - * IPv6 address. But making the buffer shorter might cause valid long lines, - * which parsed in previous versions, to fail to parse in new versions. - * (These lines would have to have excessive amounts of whitespace.) */ - char line[TOR_ADDR_BUF_LEN*2 + 32]; - addr_policy_t *r; - memarea_t *area = NULL; - - tor_assert(malformed_list); - *malformed_list = 0; - - s = eat_whitespace(s); - /* We can only do assume_action on []-quoted IPv6, as "a" (accept) - * and ":" (port separator) are ambiguous */ - if ((*s == '*' || *s == '[' || TOR_ISDIGIT(*s)) && assume_action >= 0) { - if (tor_snprintf(line, sizeof(line), "%s %s", - assume_action == ADDR_POLICY_ACCEPT?"accept":"reject", s)<0) { - log_warn(LD_DIR, "Policy %s is too long.", escaped(s)); - return NULL; - } - cp = line; - tor_strlower(line); - } else { /* assume an already well-formed address policy line */ - cp = s; - } - - eos = cp + strlen(cp); - area = memarea_new(); - tok = get_next_token(area, &cp, eos, routerdesc_token_table); - if (tok->tp == ERR_) { - log_warn(LD_DIR, "Error reading address policy: %s", tok->error); - goto err; - } - if (tok->tp != K_ACCEPT && tok->tp != K_ACCEPT6 && - tok->tp != K_REJECT && tok->tp != K_REJECT6) { - log_warn(LD_DIR, "Expected 'accept' or 'reject'."); - 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] : ""); - addr_policy_free(r); - r = NULL; - goto done; - } - - goto done; - err: - *malformed_list = 1; - r = NULL; - done: - token_clear(tok); - if (area) { - DUMP_AREA(area, "policy item"); - memarea_drop_all(area); - } - return r; -} - /** Add an exit policy stored in the token <b>tok</b> to the router info in * <b>router</b>. Return 0 on success, -1 on failure. */ static int @@ -1340,95 +1235,6 @@ router_add_exit_policy(routerinfo_t *router, directory_token_t *tok) return 0; } -/** Given a K_ACCEPT[6] or K_REJECT[6] token and a router, create and return - * a new exit_policy_t corresponding to the token. If TAPMP_EXTENDED_STAR - * is set in fmt_flags, K_ACCEPT6 and K_REJECT6 tokens followed by * - * expand to IPv6-only policies, otherwise they expand to IPv4 and IPv6 - * policies */ -static addr_policy_t * -router_parse_addr_policy(directory_token_t *tok, unsigned fmt_flags) -{ - addr_policy_t newe; - char *arg; - - tor_assert(tok->tp == K_REJECT || tok->tp == K_REJECT6 || - tok->tp == K_ACCEPT || tok->tp == K_ACCEPT6); - - if (tok->n_args != 1) - return NULL; - arg = tok->args[0]; - - if (!strcmpstart(arg,"private")) - return router_parse_addr_policy_private(tok); - - memset(&newe, 0, sizeof(newe)); - - if (tok->tp == K_REJECT || tok->tp == K_REJECT6) - newe.policy_type = ADDR_POLICY_REJECT; - else - newe.policy_type = ADDR_POLICY_ACCEPT; - - /* accept6/reject6 * produces an IPv6 wildcard address only. - * (accept/reject * produces rules for IPv4 and IPv6 wildcard addresses.) */ - if ((fmt_flags & TAPMP_EXTENDED_STAR) - && (tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6)) { - fmt_flags |= TAPMP_STAR_IPV6_ONLY; - } - - if (tor_addr_parse_mask_ports(arg, fmt_flags, &newe.addr, &newe.maskbits, - &newe.prt_min, &newe.prt_max) < 0) { - log_warn(LD_DIR,"Couldn't parse line %s. Dropping", escaped(arg)); - return NULL; - } - - return addr_policy_get_canonical_entry(&newe); -} - -/** Parse an exit policy line of the format "accept[6]/reject[6] private:...". - * This didn't exist until Tor 0.1.1.15, so nobody should generate it in - * router descriptors until earlier versions are obsolete. - * - * accept/reject and accept6/reject6 private all produce rules for both - * IPv4 and IPv6 addresses. - */ -static addr_policy_t * -router_parse_addr_policy_private(directory_token_t *tok) -{ - const char *arg; - uint16_t port_min, port_max; - addr_policy_t result; - - arg = tok->args[0]; - if (strcmpstart(arg, "private")) - return NULL; - - arg += strlen("private"); - arg = (char*) eat_whitespace(arg); - if (!arg || *arg != ':') - return NULL; - - if (parse_port_range(arg+1, &port_min, &port_max)<0) - return NULL; - - memset(&result, 0, sizeof(result)); - if (tok->tp == K_REJECT || tok->tp == K_REJECT6) - result.policy_type = ADDR_POLICY_REJECT; - else - result.policy_type = ADDR_POLICY_ACCEPT; - result.is_private = 1; - 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); -} - /** Return a newly allocated smartlist of all accept or reject tokens in * <b>s</b>. */ |