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 }