Tor 0.4.9.0-alpha-dev
policy_parse.c
Go to the documentation of this file.
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"
21#include "lib/memarea/memarea.h"
22
24
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 */
43router_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];
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 */
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"))
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
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 */
188static addr_policy_t *
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}
Address policy structures.
int tor_addr_parse_mask_ports(const char *s, unsigned flags, tor_addr_t *addr_out, maskbits_t *maskbits_out, uint16_t *port_min_out, uint16_t *port_max_out)
Definition: address.c:543
int parse_port_range(const char *port, uint16_t *port_min_out, uint16_t *port_max_out)
Definition: address.c:1994
static sa_family_t tor_addr_family(const tor_addr_t *a)
Definition: address.h:187
#define TOR_ADDR_BUF_LEN
Definition: address.h:224
const char * escaped(const char *s)
Definition: escape.c:126
#define LD_GENERAL
Definition: log.h:62
#define LD_DIR
Definition: log.h:88
memarea_t * memarea_new(void)
Definition: memarea.c:153
Header for memarea.c.
#define memarea_drop_all(area)
Definition: memarea.h:22
Master header file for Tor-specific functionality.
void token_clear(directory_token_t *tok)
Definition: parsecommon.c:41
directory_token_t * get_next_token(memarea_t *area, const char **s, const char *eos, const token_rule_t *table)
Definition: parsecommon.c:261
Header file for parsecommon.c.
addr_policy_t * addr_policy_get_canonical_entry(addr_policy_t *e)
Definition: policies.c:1389
Header file for policies.c.
static addr_policy_t * router_parse_addr_policy_private(directory_token_t *tok)
Definition: policy_parse.c:189
addr_policy_t * router_parse_addr_policy(directory_token_t *tok, unsigned fmt_flags)
Definition: policy_parse.c:136
addr_policy_t * router_parse_addr_policy_item_from_string(const char *s, int assume_action, int *malformed_list)
Definition: policy_parse.c:44
Header file for policy_parse.c.
int tor_snprintf(char *str, size_t size, const char *format,...)
Definition: printf.c:27
const token_rule_t routerdesc_token_table[]
Definition: routerparse.c:85
Header file for routerparse.c.
addr_policy_action_bitfield_t policy_type
uint16_t prt_max
unsigned int is_private
uint16_t prt_min
maskbits_t maskbits
unsigned int is_canonical
tor_addr_t addr
directory_keyword tp
Definition: parsecommon.h:204
#define MOCK_IMPL(rv, funcname, arglist)
Definition: testsupport.h:133
Header file for unparseable.c.
#define tor_assert(expr)
Definition: util_bug.h:103
void tor_strlower(char *s)
Definition: util_string.c:129
int strcmpstart(const char *s1, const char *s2)
Definition: util_string.c:217
const char * eat_whitespace(const char *s)
Definition: util_string.c:279