Tor  0.4.7.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 
23 #include "core/or/addr_policy_st.h"
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  */
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 */
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  */
188 static addr_policy_t *
190 {
191  const char *arg;
192  uint16_t port_min, port_max;
193  addr_policy_t result;
194 
195  arg = tok->args[0];
196  if (strcmpstart(arg, "private"))
197  return NULL;
198 
199  arg += strlen("private");
200  arg = (char*) eat_whitespace(arg);
201  if (!arg || *arg != ':')
202  return NULL;
203 
204  if (parse_port_range(arg+1, &port_min, &port_max)<0)
205  return NULL;
206 
207  memset(&result, 0, sizeof(result));
208  if (tok->tp == K_REJECT || tok->tp == K_REJECT6)
209  result.policy_type = ADDR_POLICY_REJECT;
210  else
211  result.policy_type = ADDR_POLICY_ACCEPT;
212  result.is_private = 1;
213  result.prt_min = port_min;
214  result.prt_max = port_max;
215 
216  if (tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) {
217  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  return addr_policy_get_canonical_entry(&result);
224 }
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:1369
Header file for policies.c.
addr_policy_t * router_parse_addr_policy(directory_token_t *tok, unsigned fmt_flags)
Definition: policy_parse.c:136
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_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
tor_addr_t addr
directory_keyword tp
Definition: parsecommon.h:202
#define MOCK_IMPL(rv, funcname, arglist)
Definition: testsupport.h:133
Header file for unparseable.c.
#define tor_assert(expr)
Definition: util_bug.h:102
void tor_strlower(char *s)
Definition: util_string.c:127
int strcmpstart(const char *s1, const char *s2)
Definition: util_string.c:215
const char * eat_whitespace(const char *s)
Definition: util_string.c:277