mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 13:13:44 +01:00
Add a new family-specific syntax for tor_addr_parse_mask_ports
By default, "*" means "All IPv4 addresses" with tor_addr_parse_mask_ports, so I won't break anything. But if the new EXTENDED_STAR flag is provided, then * means "any address", *4 means "any IPv4 address" (that is, 0.0.0.0/0), and "*6" means "any IPv6 address" (that is, [::]/0). This is going to let us have a syntax for specifying exit policies in torrc that won't drive people mad. Also, add a bunch of unit tests for tor_addr_parse_mask_ports to test these new features, and to increase coverage.
This commit is contained in:
parent
462ebb270a
commit
2eb7eafc9d
@ -559,9 +559,22 @@ tor_addr_to_PTR_name(char *out, size_t outlen,
|
||||
*
|
||||
* Return an address family on success, or -1 if an invalid address string is
|
||||
* provided.
|
||||
*
|
||||
* If 'flags & TAPMP_EXTENDED_STAR' is false, then the wildcard address '*'
|
||||
* yield an IPv4 wildcard.
|
||||
*
|
||||
* If 'flags & TAPMP_EXTENDED_STAR' is true, then the wildcard address '*'
|
||||
* yields an AF_UNSPEC wildcard address, and the following change is made
|
||||
* in the grammar above:
|
||||
* Address ::= IPv4Address / "[" IPv6Address "]" / "*" / "*4" / "*6"
|
||||
* with the new "*4" and "*6" productions creating a wildcard to match
|
||||
* IPv4 or IPv6 addresses.
|
||||
*
|
||||
*/
|
||||
int
|
||||
tor_addr_parse_mask_ports(const char *s, tor_addr_t *addr_out,
|
||||
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)
|
||||
{
|
||||
@ -618,9 +631,23 @@ tor_addr_parse_mask_ports(const char *s, tor_addr_t *addr_out,
|
||||
memset(addr_out, 0, sizeof(tor_addr_t));
|
||||
|
||||
if (!strcmp(address, "*")) {
|
||||
family = AF_INET; /* AF_UNSPEC ???? XXXX_IP6 */
|
||||
if (flags & TAPMP_EXTENDED_STAR) {
|
||||
family = AF_UNSPEC;
|
||||
tor_addr_make_unspec(addr_out);
|
||||
} else {
|
||||
family = AF_INET;
|
||||
tor_addr_from_ipv4h(addr_out, 0);
|
||||
}
|
||||
any_flag = 1;
|
||||
} else if (!strcmp(address, "*4") && (flags & TAPMP_EXTENDED_STAR)) {
|
||||
family = AF_INET;
|
||||
tor_addr_from_ipv4h(addr_out, 0);
|
||||
any_flag = 1;
|
||||
} else if (!strcmp(address, "*6") && (flags & TAPMP_EXTENDED_STAR)) {
|
||||
static char nil_bytes[16] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 };
|
||||
family = AF_INET6;
|
||||
tor_addr_from_ipv6_bytes(addr_out, nil_bytes);
|
||||
any_flag = 1;
|
||||
} else if (tor_inet_pton(AF_INET6, address, &in6_tmp) > 0) {
|
||||
family = AF_INET6;
|
||||
tor_addr_from_in6(addr_out, &in6_tmp);
|
||||
|
@ -183,7 +183,8 @@ int tor_addr_parse_PTR_name(tor_addr_t *result, const char *address,
|
||||
|
||||
int tor_addr_port_lookup(const char *s, tor_addr_t *addr_out,
|
||||
uint16_t *port_out);
|
||||
int tor_addr_parse_mask_ports(const char *s,
|
||||
#define TAPMP_EXTENDED_STAR 1
|
||||
int tor_addr_parse_mask_ports(const char *s, unsigned flags,
|
||||
tor_addr_t *addr_out, maskbits_t *mask_out,
|
||||
uint16_t *port_min_out, uint16_t *port_max_out);
|
||||
const char * tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len,
|
||||
|
@ -276,6 +276,7 @@ static config_var_t option_vars_[] = {
|
||||
V(HTTPProxyAuthenticator, STRING, NULL),
|
||||
V(HTTPSProxy, STRING, NULL),
|
||||
V(HTTPSProxyAuthenticator, STRING, NULL),
|
||||
// V(IPv6EXit, BOOL, "0"),
|
||||
VAR("ServerTransportPlugin", LINELIST, ServerTransportPlugin, NULL),
|
||||
V(Socks4Proxy, STRING, NULL),
|
||||
V(Socks5Proxy, STRING, NULL),
|
||||
|
@ -87,7 +87,8 @@ policy_expand_private(smartlist_t **policy)
|
||||
memcpy(&newpolicy, p, sizeof(addr_policy_t));
|
||||
newpolicy.is_private = 0;
|
||||
newpolicy.is_canonical = 0;
|
||||
if (tor_addr_parse_mask_ports(private_nets[i], &newpolicy.addr,
|
||||
if (tor_addr_parse_mask_ports(private_nets[i], 0,
|
||||
&newpolicy.addr,
|
||||
&newpolicy.maskbits, &port_min, &port_max)<0) {
|
||||
tor_assert(0);
|
||||
}
|
||||
@ -1192,8 +1193,8 @@ policy_summary_add_item(smartlist_t *summary, addr_policy_t *p)
|
||||
for (i = 0; private_nets[i]; ++i) {
|
||||
tor_addr_t addr;
|
||||
maskbits_t maskbits;
|
||||
if (tor_addr_parse_mask_ports(private_nets[i], &addr,
|
||||
&maskbits, NULL, NULL)<0) {
|
||||
if (tor_addr_parse_mask_ports(private_nets[i], 0, &addr,
|
||||
&maskbits, NULL, NULL)<0) {
|
||||
tor_assert(0);
|
||||
}
|
||||
if (tor_addr_compare(&p->addr, &addr, CMP_EXACT) == 0 &&
|
||||
|
@ -1280,7 +1280,8 @@ find_single_ipv6_orport(const smartlist_t *list,
|
||||
uint16_t port_min, port_max;
|
||||
tor_assert(t->n_args >= 1);
|
||||
/* XXXX Prop186 the full spec allows much more than this. */
|
||||
if (tor_addr_parse_mask_ports(t->args[0], &a, &bits, &port_min,
|
||||
if (tor_addr_parse_mask_ports(t->args[0], 0,
|
||||
&a, &bits, &port_min,
|
||||
&port_max) == AF_INET6 &&
|
||||
bits == 128 &&
|
||||
port_min == port_max) {
|
||||
@ -3737,7 +3738,7 @@ router_parse_addr_policy(directory_token_t *tok)
|
||||
else
|
||||
newe.policy_type = ADDR_POLICY_ACCEPT;
|
||||
|
||||
if (tor_addr_parse_mask_ports(arg, &newe.addr, &newe.maskbits,
|
||||
if (tor_addr_parse_mask_ports(arg, 0, &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;
|
||||
|
@ -159,7 +159,8 @@ test_addr_basic(void)
|
||||
* as <b>pt1..pt2</b>. */
|
||||
#define test_addr_mask_ports_parse(xx, f, ip1, ip2, ip3, ip4, mm, pt1, pt2) \
|
||||
STMT_BEGIN \
|
||||
test_eq(tor_addr_parse_mask_ports(xx, &t1, &mask, &port1, &port2), f); \
|
||||
test_eq(tor_addr_parse_mask_ports(xx, 0, &t1, &mask, &port1, &port2), \
|
||||
f); \
|
||||
p1=tor_inet_ntop(AF_INET6, &t1.addr.in6_addr, bug, sizeof(bug)); \
|
||||
test_eq(htonl(ip1), tor_addr_to_in6_addr32(&t1)[0]); \
|
||||
test_eq(htonl(ip2), tor_addr_to_in6_addr32(&t1)[1]); \
|
||||
@ -401,11 +402,11 @@ test_addr_ip6_helpers(void)
|
||||
test_addr_compare("0::2:2:1", <, "0::ffff:0.3.2.1");
|
||||
test_addr_compare("0::ffff:0.3.2.1", >, "0::0:0:0");
|
||||
test_addr_compare("0::ffff:5.2.2.1", <, "::ffff:6.0.0.0"); /* XXXX wrong. */
|
||||
tor_addr_parse_mask_ports("[::ffff:2.3.4.5]", &t1, NULL, NULL, NULL);
|
||||
tor_addr_parse_mask_ports("2.3.4.5", &t2, NULL, NULL, NULL);
|
||||
tor_addr_parse_mask_ports("[::ffff:2.3.4.5]", 0, &t1, NULL, NULL, NULL);
|
||||
tor_addr_parse_mask_ports("2.3.4.5", 0, &t2, NULL, NULL, NULL);
|
||||
test_assert(tor_addr_compare(&t1, &t2, CMP_SEMANTIC) == 0);
|
||||
tor_addr_parse_mask_ports("[::ffff:2.3.4.4]", &t1, NULL, NULL, NULL);
|
||||
tor_addr_parse_mask_ports("2.3.4.5", &t2, NULL, NULL, NULL);
|
||||
tor_addr_parse_mask_ports("[::ffff:2.3.4.4]", 0, &t1, NULL, NULL, NULL);
|
||||
tor_addr_parse_mask_ports("2.3.4.5", 0, &t2, NULL, NULL, NULL);
|
||||
test_assert(tor_addr_compare(&t1, &t2, CMP_SEMANTIC) < 0);
|
||||
|
||||
/* test compare_masked */
|
||||
@ -568,6 +569,7 @@ test_addr_ip6_helpers(void)
|
||||
test_streq(rbuf, addr_PTR);
|
||||
}
|
||||
|
||||
/* XXXX turn this into a separate function; it's not all IPv6. */
|
||||
/* test tor_addr_parse_mask_ports */
|
||||
test_addr_mask_ports_parse("[::f]/17:47-95", AF_INET6,
|
||||
0, 0, 0, 0x0000000f, 17, 47, 95);
|
||||
@ -581,27 +583,123 @@ test_addr_ip6_helpers(void)
|
||||
0xabcd0002, 0, 0, 0x044a0000, 128, 2, 65000);
|
||||
|
||||
test_streq(p1, "abcd:2::44a:0");
|
||||
r=tor_addr_parse_mask_ports("[fefef::]/112", &t1, NULL, NULL, NULL);
|
||||
/* Try some long addresses. */
|
||||
r=tor_addr_parse_mask_ports("[ffff:1111:1111:1111:1111:1111:1111:1111]",
|
||||
0, &t1, NULL, NULL, NULL);
|
||||
test_assert(r == AF_INET6);
|
||||
r=tor_addr_parse_mask_ports("[ffff:1111:1111:1111:1111:1111:1111:11111]",
|
||||
0, &t1, NULL, NULL, NULL);
|
||||
test_assert(r == -1);
|
||||
r=tor_addr_parse_mask_ports("efef::/112", &t1, NULL, NULL, NULL);
|
||||
r=tor_addr_parse_mask_ports("[ffff:1111:1111:1111:1111:1111:1111:1111:1]",
|
||||
0, &t1, NULL, NULL, NULL);
|
||||
test_assert(r == -1);
|
||||
r=tor_addr_parse_mask_ports("[f:f:f:f:f:f:f:f::]", &t1, NULL, NULL, NULL);
|
||||
r=tor_addr_parse_mask_ports(
|
||||
"[ffff:1111:1111:1111:1111:1111:1111:ffff:"
|
||||
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:"
|
||||
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:"
|
||||
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]",
|
||||
0, &t1, NULL, NULL, NULL);
|
||||
test_assert(r == -1);
|
||||
r=tor_addr_parse_mask_ports("[::f:f:f:f:f:f:f:f]", &t1, NULL, NULL, NULL);
|
||||
/* Try some failing cases. */
|
||||
r=tor_addr_parse_mask_ports("[fefef::]/112", 0, &t1, NULL, NULL, NULL);
|
||||
test_assert(r == -1);
|
||||
r=tor_addr_parse_mask_ports("[f:f:f:f:f:f:f:f:f]", &t1, NULL, NULL, NULL);
|
||||
r=tor_addr_parse_mask_ports("[fefe::/112", 0, &t1, NULL, NULL, NULL);
|
||||
test_assert(r == -1);
|
||||
r=tor_addr_parse_mask_ports("[fefe::", 0, &t1, NULL, NULL, NULL);
|
||||
test_assert(r == -1);
|
||||
r=tor_addr_parse_mask_ports("[fefe::X]", 0, &t1, NULL, NULL, NULL);
|
||||
test_assert(r == -1);
|
||||
r=tor_addr_parse_mask_ports("efef::/112", 0, &t1, NULL, NULL, NULL);
|
||||
test_assert(r == -1);
|
||||
r=tor_addr_parse_mask_ports("[f:f:f:f:f:f:f:f::]",0,&t1, NULL, NULL, NULL);
|
||||
test_assert(r == -1);
|
||||
r=tor_addr_parse_mask_ports("[::f:f:f:f:f:f:f:f]",0,&t1, NULL, NULL, NULL);
|
||||
test_assert(r == -1);
|
||||
r=tor_addr_parse_mask_ports("[f:f:f:f:f:f:f:f:f]",0,&t1, NULL, NULL, NULL);
|
||||
test_assert(r == -1);
|
||||
r=tor_addr_parse_mask_ports("[f:f:f:f:f::]/fred",0,&t1,&mask, NULL, NULL);
|
||||
test_assert(r == -1);
|
||||
r=tor_addr_parse_mask_ports("[f:f:f:f:f::]/255.255.0.0",
|
||||
0,&t1, NULL, NULL, NULL);
|
||||
test_assert(r == -1);
|
||||
/* This one will get rejected because it isn't a pure prefix. */
|
||||
r=tor_addr_parse_mask_ports("1.1.2.3/255.255.64.0",0,&t1, &mask,NULL,NULL);
|
||||
test_assert(r == -1);
|
||||
/* Test for V4-mapped address with mask < 96. (arguably not valid) */
|
||||
r=tor_addr_parse_mask_ports("[::ffff:1.1.2.2/33]", &t1, &mask, NULL, NULL);
|
||||
r=tor_addr_parse_mask_ports("[::ffff:1.1.2.2/33]",0,&t1, &mask, NULL, NULL);
|
||||
test_assert(r == -1);
|
||||
r=tor_addr_parse_mask_ports("1.1.2.2/33", &t1, &mask, NULL, NULL);
|
||||
r=tor_addr_parse_mask_ports("1.1.2.2/33",0,&t1, &mask, NULL, NULL);
|
||||
test_assert(r == -1);
|
||||
r=tor_addr_parse_mask_ports("1.1.2.2/31", &t1, &mask, NULL, NULL);
|
||||
/* Try extended wildcard addresses with out TAPMP_EXTENDED_STAR*/
|
||||
r=tor_addr_parse_mask_ports("*4",0,&t1, &mask, NULL, NULL);
|
||||
test_assert(r == -1);
|
||||
r=tor_addr_parse_mask_ports("*6",0,&t1, &mask, NULL, NULL);
|
||||
test_assert(r == -1);
|
||||
#if 0
|
||||
/* Try a mask with a wildcard. */
|
||||
r=tor_addr_parse_mask_ports("*/16",0,&t1, &mask, NULL, NULL);
|
||||
test_assert(r == -1);
|
||||
r=tor_addr_parse_mask_ports("*4/16",TAPMP_EXTENDED_STAR,
|
||||
&t1, &mask, NULL, NULL);
|
||||
test_assert(r == -1);
|
||||
r=tor_addr_parse_mask_ports("*6/30",TAPMP_EXTENDED_STAR,
|
||||
&t1, &mask, NULL, NULL);
|
||||
test_assert(r == -1);
|
||||
#endif
|
||||
/* Basic mask tests*/
|
||||
r=tor_addr_parse_mask_ports("1.1.2.2/31",0,&t1, &mask, NULL, NULL);
|
||||
test_assert(r == AF_INET);
|
||||
r=tor_addr_parse_mask_ports("[efef::]/112", &t1, &mask, &port1, &port2);
|
||||
tt_int_op(mask,==,31);
|
||||
tt_int_op(tor_addr_family(&t1),==,AF_INET);
|
||||
tt_int_op(tor_addr_to_ipv4h(&t1),==,0x01010202);
|
||||
r=tor_addr_parse_mask_ports("3.4.16.032:1-2",0,&t1, &mask, &port1, &port2);
|
||||
test_assert(r == AF_INET);
|
||||
tt_int_op(mask,==,32);
|
||||
tt_int_op(tor_addr_family(&t1),==,AF_INET);
|
||||
tt_int_op(tor_addr_to_ipv4h(&t1),==,0x03041020);
|
||||
test_assert(port1 == 1);
|
||||
test_assert(port2 == 2);
|
||||
r=tor_addr_parse_mask_ports("1.1.2.3/255.255.128.0",0,&t1, &mask,NULL,NULL);
|
||||
test_assert(r == AF_INET);
|
||||
tt_int_op(mask,==,17);
|
||||
tt_int_op(tor_addr_family(&t1),==,AF_INET);
|
||||
tt_int_op(tor_addr_to_ipv4h(&t1),==,0x01010203);
|
||||
r=tor_addr_parse_mask_ports("[efef::]/112",0,&t1, &mask, &port1, &port2);
|
||||
test_assert(r == AF_INET6);
|
||||
test_assert(port1 == 1);
|
||||
test_assert(port2 == 65535);
|
||||
/* Try regular wildcard behavior without TAPMP_EXTENDED_STAR */
|
||||
r=tor_addr_parse_mask_ports("*:80-443",0,&t1,&mask,&port1,&port2);
|
||||
tt_int_op(r,==,AF_INET); /* Old users of this always get inet */
|
||||
tt_int_op(tor_addr_family(&t1),==,AF_INET);
|
||||
tt_int_op(tor_addr_to_ipv4h(&t1),==,0);
|
||||
tt_int_op(mask,==,0);
|
||||
tt_int_op(port1,==,80);
|
||||
tt_int_op(port2,==,443);
|
||||
/* Now try wildcards *with* TAPMP_EXTENDED_STAR */
|
||||
r=tor_addr_parse_mask_ports("*:8000-9000",TAPMP_EXTENDED_STAR,
|
||||
&t1,&mask,&port1,&port2);
|
||||
tt_int_op(r,==,AF_UNSPEC);
|
||||
tt_int_op(tor_addr_family(&t1),==,AF_UNSPEC);
|
||||
tt_int_op(mask,==,0);
|
||||
tt_int_op(port1,==,8000);
|
||||
tt_int_op(port2,==,9000);
|
||||
r=tor_addr_parse_mask_ports("*4:6667",TAPMP_EXTENDED_STAR,
|
||||
&t1,&mask,&port1,&port2);
|
||||
tt_int_op(r,==,AF_INET);
|
||||
tt_int_op(tor_addr_family(&t1),==,AF_INET);
|
||||
tt_int_op(tor_addr_to_ipv4h(&t1),==,0);
|
||||
tt_int_op(mask,==,0);
|
||||
tt_int_op(port1,==,6667);
|
||||
tt_int_op(port2,==,6667);
|
||||
r=tor_addr_parse_mask_ports("*6",TAPMP_EXTENDED_STAR,
|
||||
&t1,&mask,&port1,&port2);
|
||||
tt_int_op(r,==,AF_INET6);
|
||||
tt_int_op(tor_addr_family(&t1),==,AF_INET6);
|
||||
tt_assert(tor_mem_is_zero((const char*)tor_addr_to_in6_addr32(&t1), 16));
|
||||
tt_int_op(mask,==,0);
|
||||
tt_int_op(port1,==,1);
|
||||
tt_int_op(port2,==,65535);
|
||||
|
||||
/* make sure inet address lengths >= max */
|
||||
test_assert(INET_NTOA_BUF_LEN >= sizeof("255.255.255.255"));
|
||||
|
Loading…
Reference in New Issue
Block a user