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 : }
|