aboutsummaryrefslogtreecommitdiff
path: root/src/or/policies.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/policies.c')
-rw-r--r--src/or/policies.c245
1 files changed, 213 insertions, 32 deletions
diff --git a/src/or/policies.c b/src/or/policies.c
index c87036013d..40e5277478 100644
--- a/src/or/policies.c
+++ b/src/or/policies.c
@@ -11,6 +11,7 @@
#include "or.h"
#include "config.h"
#include "dirserv.h"
+#include "nodelist.h"
#include "policies.h"
#include "routerparse.h"
#include "ht.h"
@@ -82,15 +83,15 @@ policy_expand_private(smartlist_t **policy)
continue;
}
for (i = 0; private_nets[i]; ++i) {
- addr_policy_t policy;
- memcpy(&policy, p, sizeof(addr_policy_t));
- policy.is_private = 0;
- policy.is_canonical = 0;
- if (tor_addr_parse_mask_ports(private_nets[i], &policy.addr,
- &policy.maskbits, &port_min, &port_max)<0) {
+ addr_policy_t newpolicy;
+ 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,
+ &newpolicy.maskbits, &port_min, &port_max)<0) {
tor_assert(0);
}
- smartlist_add(tmp, addr_policy_get_canonical_entry(&policy));
+ smartlist_add(tmp, addr_policy_get_canonical_entry(&newpolicy));
}
addr_policy_free(p);
});
@@ -163,7 +164,7 @@ parse_addr_policy(config_line_t *cfg, smartlist_t **dest,
static int
parse_reachable_addresses(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int ret = 0;
if (options->ReachableDirAddresses &&
@@ -261,7 +262,7 @@ fascist_firewall_allows_address_or(const tor_addr_t *addr, uint16_t port)
/** Return true iff we think our firewall will let us make an OR connection to
* <b>ri</b>. */
int
-fascist_firewall_allows_or(routerinfo_t *ri)
+fascist_firewall_allows_or(const routerinfo_t *ri)
{
/* XXXX proposal 118 */
tor_addr_t addr;
@@ -269,6 +270,22 @@ fascist_firewall_allows_or(routerinfo_t *ri)
return fascist_firewall_allows_address_or(&addr, ri->or_port);
}
+/** Return true iff we think our firewall will let us make an OR connection to
+ * <b>node</b>. */
+int
+fascist_firewall_allows_node(const node_t *node)
+{
+ if (node->ri) {
+ return fascist_firewall_allows_or(node->ri);
+ } else if (node->rs) {
+ tor_addr_t addr;
+ tor_addr_from_ipv4h(&addr, node->rs->addr);
+ return fascist_firewall_allows_address_or(&addr, node->rs->or_port);
+ } else {
+ return 1;
+ }
+}
+
/** Return true iff we think our firewall will let us make a directory
* connection to addr:port. */
int
@@ -339,7 +356,7 @@ authdir_policy_badexit_address(uint32_t addr, uint16_t port)
* options in <b>options</b>, return -1 and set <b>msg</b> to a newly
* allocated description of the error. Else return 0. */
int
-validate_addr_policies(or_options_t *options, char **msg)
+validate_addr_policies(const or_options_t *options, char **msg)
{
/* XXXX Maybe merge this into parse_policies_from_options, to make sure
* that the two can't go out of sync. */
@@ -423,7 +440,7 @@ load_policy_from_option(config_line_t *config, smartlist_t **policy,
/** Set all policies based on <b>options</b>, which should have been validated
* first by validate_addr_policies. */
int
-policies_parse_from_options(or_options_t *options)
+policies_parse_from_options(const or_options_t *options)
{
int ret = 0;
if (load_policy_from_option(options->SocksPolicy, &socks_policy, -1) < 0)
@@ -553,18 +570,6 @@ addr_policy_get_canonical_entry(addr_policy_t *e)
return found->policy;
}
-/** As compare_tor_addr_to_addr_policy, but instead of a tor_addr_t, takes
- * in host order. */
-addr_policy_result_t
-compare_addr_to_addr_policy(uint32_t addr, uint16_t port,
- const smartlist_t *policy)
-{
- /*XXXX deprecate this function when possible. */
- tor_addr_t a;
- tor_addr_from_ipv4h(&a, addr);
- return compare_tor_addr_to_addr_policy(&a, port, policy);
-}
-
/** Helper for compare_tor_addr_to_addr_policy. Implements the case where
* addr and port are both known. */
static addr_policy_result_t
@@ -684,7 +689,7 @@ compare_tor_addr_to_addr_policy(const tor_addr_t *addr, uint16_t port,
if (!policy) {
/* no policy? accept all. */
return ADDR_POLICY_ACCEPTED;
- } else if (tor_addr_is_null(addr)) {
+ } else if (addr == NULL || tor_addr_is_null(addr)) {
tor_assert(port != 0);
return compare_unknown_tor_addr_to_addr_policy(port, policy);
} else if (port == 0) {
@@ -866,15 +871,11 @@ policies_exit_policy_append_reject_star(smartlist_t **dest)
append_exit_policy_string(dest, "reject *:*");
}
-/** Replace the exit policy of <b>r</b> with reject *:*. */
+/** Replace the exit policy of <b>node</b> with reject *:* */
void
-policies_set_router_exitpolicy_to_reject_all(routerinfo_t *r)
+policies_set_node_exitpolicy_to_reject_all(node_t *node)
{
- addr_policy_t *item;
- addr_policy_list_free(r->exit_policy);
- r->exit_policy = smartlist_create();
- item = router_parse_addr_policy_item_from_string("reject *:*", -1);
- smartlist_add(r->exit_policy, item);
+ node->rejects_all = 1;
}
/** Return 1 if there is at least one /8 subnet in <b>policy</b> that
@@ -1085,7 +1086,7 @@ policy_summary_split(smartlist_t *summary,
int start_at_index;
int i = 0;
- /* XXXX Do a binary search if run time matters */
+
while (AT(i)->prt_max < prt_min)
i++;
if (AT(i)->prt_min != prt_min) {
@@ -1298,6 +1299,186 @@ policy_summarize(smartlist_t *policy)
return result;
}
+/** Convert a summarized policy string into a short_policy_t. Return NULL
+ * if the string is not well-formed. */
+short_policy_t *
+parse_short_policy(const char *summary)
+{
+ const char *orig_summary = summary;
+ short_policy_t *result;
+ int is_accept;
+ int n_entries;
+ short_policy_entry_t entries[MAX_EXITPOLICY_SUMMARY_LEN]; /* overkill */
+ const char *next;
+
+ if (!strcmpstart(summary, "accept ")) {
+ is_accept = 1;
+ summary += strlen("accept ");
+ } else if (!strcmpstart(summary, "reject ")) {
+ is_accept = 0;
+ summary += strlen("reject ");
+ } else {
+ log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Unrecognized policy summary keyword");
+ return NULL;
+ }
+
+ n_entries = 0;
+ for ( ; *summary; summary = next) {
+ const char *comma = strchr(summary, ',');
+ unsigned low, high;
+ char dummy;
+ char ent_buf[32];
+
+ next = comma ? comma+1 : strchr(summary, '\0');
+
+ if (n_entries == MAX_EXITPOLICY_SUMMARY_LEN) {
+ log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Impossibly long policy summary %s",
+ escaped(orig_summary));
+ return NULL;
+ }
+
+ if (! TOR_ISDIGIT(*summary) || next-summary > (int)(sizeof(ent_buf)-1)) {
+ /* unrecognized entry format. skip it. */
+ continue;
+ }
+ if (next-summary < 2) {
+ /* empty; skip it. */
+ continue;
+ }
+
+ memcpy(ent_buf, summary, next-summary-1);
+ ent_buf[next-summary-1] = '\0';
+
+ if (tor_sscanf(ent_buf, "%u-%u%c", &low, &high, &dummy) == 2) {
+ if (low<1 || low>65535 || high<1 || high>65535) {
+ log_fn(LOG_PROTOCOL_WARN, LD_DIR,
+ "Found bad entry in policy summary %s", escaped(orig_summary));
+ return NULL;
+ }
+ } else if (tor_sscanf(ent_buf, "%u%c", &low, &dummy) == 1) {
+ if (low<1 || low>65535) {
+ log_fn(LOG_PROTOCOL_WARN, LD_DIR,
+ "Found bad entry in policy summary %s", escaped(orig_summary));
+ return NULL;
+ }
+ high = low;
+ } else {
+ log_fn(LOG_PROTOCOL_WARN, LD_DIR,"Found bad entry in policy summary %s",
+ escaped(orig_summary));
+ return NULL;
+ }
+
+ entries[n_entries].min_port = low;
+ entries[n_entries].max_port = high;
+ n_entries++;
+ }
+
+ if (n_entries == 0) {
+ log_fn(LOG_PROTOCOL_WARN, LD_DIR,
+ "Found no port-range entries in summary %s", escaped(orig_summary));
+ return NULL;
+ }
+
+ {
+ size_t size = STRUCT_OFFSET(short_policy_t, entries) +
+ sizeof(short_policy_entry_t)*(n_entries);
+ result = tor_malloc_zero(size);
+
+ tor_assert( (char*)&result->entries[n_entries-1] < ((char*)result)+size);
+ }
+
+ result->is_accept = is_accept;
+ result->n_entries = n_entries;
+ memcpy(result->entries, entries, sizeof(short_policy_entry_t)*n_entries);
+ return result;
+}
+
+/** Release all storage held in <b>policy</b>. */
+void
+short_policy_free(short_policy_t *policy)
+{
+ tor_free(policy);
+}
+
+/** See whether the <b>addr</b>:<b>port</b> address is likely to be accepted
+ * or rejected by the summarized policy <b>policy</b>. Return values are as
+ * for compare_tor_addr_to_addr_policy. Unlike the regular addr_policy
+ * functions, requires the <b>port</b> be specified. */
+addr_policy_result_t
+compare_tor_addr_to_short_policy(const tor_addr_t *addr, uint16_t port,
+ const short_policy_t *policy)
+{
+ int i;
+ int found_match = 0;
+ int accept;
+ (void)addr;
+
+ tor_assert(port != 0);
+
+ if (addr && tor_addr_is_null(addr))
+ addr = NULL; /* Unspec means 'no address at all,' in this context. */
+
+ if (addr && (tor_addr_is_internal(addr, 0) ||
+ tor_addr_is_loopback(addr)))
+ return ADDR_POLICY_REJECTED;
+
+ for (i=0; i < policy->n_entries; ++i) {
+ const short_policy_entry_t *e = &policy->entries[i];
+ if (e->min_port <= port && port <= e->max_port) {
+ found_match = 1;
+ break;
+ }
+ }
+
+ if (found_match)
+ accept = policy->is_accept;
+ else
+ accept = ! policy->is_accept;
+
+ /* ???? are these right? */
+ if (accept)
+ return ADDR_POLICY_PROBABLY_ACCEPTED;
+ else
+ return ADDR_POLICY_REJECTED;
+}
+
+/** Return true iff <b>policy</b> seems reject all ports */
+int
+short_policy_is_reject_star(const short_policy_t *policy)
+{
+ /* This doesn't need to be as much on the lookout as policy_is_reject_star,
+ * since policy summaries are from the consensus or from consensus
+ * microdescs.
+ */
+ tor_assert(policy);
+ /* Check for an exact match of "reject 1-65535". */
+ return (policy->is_accept == 0 && policy->n_entries == 1 &&
+ policy->entries[0].min_port == 1 &&
+ policy->entries[0].max_port == 65535);
+}
+
+/** Decides whether addr:port is probably or definitely accepted or rejcted by
+ * <b>node</b>. See compare_tor_addr_to_addr_policy for details on addr/port
+ * interpretation. */
+addr_policy_result_t
+compare_tor_addr_to_node_policy(const tor_addr_t *addr, uint16_t port,
+ const node_t *node)
+{
+ if (node->rejects_all)
+ return ADDR_POLICY_REJECTED;
+
+ if (node->ri)
+ return compare_tor_addr_to_addr_policy(addr, port, node->ri->exit_policy);
+ else if (node->md) {
+ if (node->md->exit_policy == NULL)
+ return ADDR_POLICY_REJECTED;
+ else
+ return compare_tor_addr_to_short_policy(addr, port,
+ node->md->exit_policy);
+ } else
+ return ADDR_POLICY_PROBABLY_REJECTED;
+}
+
/** Implementation for GETINFO control command: knows the answer for questions
* about "exit-policy/..." */
int