diff options
-rw-r--r-- | src/common/util.c | 78 | ||||
-rw-r--r-- | src/common/util.h | 2 | ||||
-rw-r--r-- | src/or/config.c | 4 | ||||
-rw-r--r-- | src/or/routerparse.c | 55 |
4 files changed, 107 insertions, 32 deletions
diff --git a/src/common/util.c b/src/common/util.c index 1f94345fc0..7e4f0a1457 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -1440,8 +1440,52 @@ addr_mask_get_bits(uint32_t mask) return -1; } +/** Parse a string <b>s</b> in the format of (*|port(-maxport)?)?, setting the + * various *out pointers as appropriate. Return 0 on success, -1 on failure. + */ +int +parse_port_range(const char *port, uint16_t *port_min_out, + uint16_t *port_max_out) +{ + tor_assert(port_min_out); + tor_assert(port_max_out); + + if (!port || *port == '\0' || strcmp(port, "*") == 0) { + *port_min_out = 1; + *port_max_out = 65535; + } else { + char *endptr = NULL; + *port_min_out = (uint16_t) tor_parse_long(port, 10, 1, 65535, + NULL, &endptr); + if (*endptr == '-') { + port = endptr+1; + endptr = NULL; + *port_max_out = (uint16_t) tor_parse_long(port, 10, 1, 65535, NULL, + &endptr); + if (*endptr || !*port_max_out) { + log_warn(LD_GENERAL, + "Malformed port \"%s\" on address range rejecting.", + port); + } + } else if (*endptr || !*port_min_out) { + log_warn(LD_GENERAL, + "Malformed port \"%s\" on address range; rejecting.", + port); + return -1; + } else { + *port_max_out = *port_min_out; + } + if (*port_min_out > *port_max_out) { + log_warn(LD_GENERAL, "Insane port range on address policy; rejecting."); + return -1; + } + } + + return 0; +} + /** Parse a string <b>s</b> in the format of - * (IP(/mask|/mask-bits)?|*):(*|port(-maxport)?), setting the various + * (IP(/mask|/mask-bits)?|*)(:*|port(-maxport)?)?, setting the various * *out pointers as appropriate. Return 0 on success, -1 on failure. */ int @@ -1510,36 +1554,8 @@ parse_addr_and_port_range(const char *s, uint32_t *addr_out, } } - if (!port || strcmp(port, "*") == 0) { - *port_min_out = 1; - *port_max_out = 65535; - } else { - endptr = NULL; - *port_min_out = (uint16_t) tor_parse_long(port, 10, 1, 65535, - NULL, &endptr); - if (*endptr == '-') { - port = endptr+1; - endptr = NULL; - *port_max_out = (uint16_t) tor_parse_long(port, 10, 1, 65535, NULL, - &endptr); - if (*endptr || !*port_max_out) { - log_warn(LD_GENERAL, - "Malformed port \"%s\" on address range rejecting.", - port); - } - } else if (*endptr || !*port_min_out) { - log_warn(LD_GENERAL, - "Malformed port \"%s\" on address range; rejecting.", - port); - goto err; - } else { - *port_max_out = *port_min_out; - } - if (*port_min_out > *port_max_out) { - log_warn(LD_GENERAL, "Insane port range on address policy; rejecting."); - goto err; - } - } + if (parse_port_range(port, port_min_out, port_max_out)<0) + goto err; tor_free(address); return 0; diff --git a/src/common/util.h b/src/common/util.h index 36c02164eb..64aca2392c 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -165,6 +165,8 @@ int is_internal_IP(uint32_t ip, int for_listening); int is_local_IP(uint32_t ip); int parse_addr_port(const char *addrport, char **address, uint32_t *addr, uint16_t *port); +int parse_port_range(const char *port, uint16_t *port_min_out, + uint16_t *port_max_out); int parse_addr_and_port_range(const char *s, uint32_t *addr_out, uint32_t *mask_out, uint16_t *port_min_out, uint16_t *port_max_out); diff --git a/src/or/config.c b/src/or/config.c index 08a17814a1..b97c07fb85 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -3299,7 +3299,9 @@ config_parse_addr_policy(config_line_t *cfg, log_warn(LD_CONFIG, "Address policy element '%s' can't be expressed " "as a bit prefix.", ent); } - nextp = &((*nextp)->next); + /* Advance nextp to the end of the policy. */ + while (*nextp) + nextp = &((*nextp)->next); } else { log_warn(LD_CONFIG,"Malformed policy '%s'.", ent); r = -1; diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 4bdd1ce06a..c5df489f35 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -151,6 +151,8 @@ static struct { /* static function prototypes */ static int router_add_exit_policy(routerinfo_t *router,directory_token_t *tok); static addr_policy_t *router_parse_addr_policy(directory_token_t *tok); +static addr_policy_t *router_parse_private_addr_policy_private( + directory_token_t *tok); static int router_get_hash_impl(const char *s, char *digest, const char *start_str, const char *end_str); static void token_free(directory_token_t *tok); @@ -1338,6 +1340,9 @@ router_parse_addr_policy(directory_token_t *tok) return NULL; arg = tok->args[0]; + if (!strcmpstart(arg,"private")) + return router_parse_private_addr_policy_private(tok); + newe = tor_malloc_zero(sizeof(addr_policy_t)); newe->string = tor_malloc(8+strlen(arg)); @@ -1370,6 +1375,56 @@ policy_read_failed: return NULL; } +/** Parse an exit policy line of the format "accept/reject private:...". + * This didn't exist until Tor 0.1.1.15, so nobody should generate it in + * router descriptors until earlier versions are obsolete. + */ +static addr_policy_t * +router_parse_private_addr_policy_private(directory_token_t *tok) +{ + /* XXXX duplicated from config.c */ + static const char *private_nets[] = { + "0.0.0.0/8", "169.254.0.0/16", + "127.0.0.0/8", "192.168.0.0/16", "10.0.0.0/8", "172.16.0.0/12",NULL }; + char *arg; + addr_policy_t *result, **nextp; + int net; + uint16_t port_min, port_max; + + arg = tok->args[0]; + if (strcmpstart(arg, "private")) + return NULL; + arg += strlen("private"); + arg = (char*) eat_whitespace(arg); + if (!arg || *arg != ':') + return NULL; + + if (parse_port_range(arg+1, &port_min, &port_max)<0) + return NULL; + + nextp = &result; + for (net = 0; private_nets[net]; ++net) { + size_t len; + *nextp = tor_malloc_zero(sizeof(addr_policy_t)); + (*nextp)->policy_type = (tok->tp == K_REJECT) ? ADDR_POLICY_REJECT + : ADDR_POLICY_ACCEPT; + len = strlen(arg)+strlen(private_nets[net])+16; + (*nextp)->string = tor_malloc(len+1); + tor_snprintf((*nextp)->string, len, "%s %s%s", + tok->tp == K_REJECT ? "reject" : "accept", + private_nets[net], arg); + if (parse_addr_and_port_range((*nextp)->string + 7, + &(*nextp)->addr, &(*nextp)->msk, + &(*nextp)->prt_min, &(*nextp)->prt_max)) { + log_warn(LD_BUG, "Couldn't parse an address range we generated!"); + return NULL; + } + nextp = &(*nextp)->next; + } + + return result; +} + /** Log and exit if <b>t</b> is malformed */ void assert_addr_policy_ok(addr_policy_t *t) |