Loading src/or/microdesc.c +5 −4 Original line number Diff line number Diff line Loading @@ -4,12 +4,13 @@ #include "or.h" #include "config.h" #include "directory.h" #include "dirserv.h" #include "microdesc.h" #include "nodelist.h" #include "routerparse.h" #include "networkstatus.h" #include "nodelist.h" #include "policies.h" #include "routerlist.h" #include "dirserv.h" #include "routerparse.h" /** A data structure to hold a bunch of cached microdescriptors. There are * two active files in the cache: a "cache file" that we mmap, and a "journal Loading Loading @@ -458,7 +459,7 @@ microdesc_free(microdesc_t *md) SMARTLIST_FOREACH(md->family, char *, cp, tor_free(cp)); smartlist_free(md->family); } tor_free(md->exitsummary); short_policy_free(md->exit_policy); tor_free(md); } Loading src/or/nodelist.c +10 −5 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ #include "microdesc.h" #include "networkstatus.h" #include "nodelist.h" #include "policies.h" #include "router.h" #include "routerlist.h" Loading Loading @@ -597,14 +598,18 @@ node_allows_single_hop_exits(const node_t *node) return 0; } /** Return true iff it seems that <b>node</b> has an exit policy that * doesn't actually permit anything to exit. */ /** Return true iff it seems that <b>node</b> has an exit policy that doesn't * actually permit anything to exit, or we don't know its exit policy */ int node_exit_policy_rejects_all(const node_t *node) { (void)node; UNIMPLEMENTED_NODELIST(); return 0; if (node->ri) return node->ri->policy_is_reject_star; else if (node->md) return node->md->exit_policy == NULL || short_policy_is_reject_star(node->md->exit_policy); else return 1; } /** Copy the address for <b>node</b> into *<b>addr_out</b>. */ Loading src/or/or.h +15 −4 Original line number Diff line number Diff line Loading @@ -1648,6 +1648,18 @@ typedef struct routerstatus_t { } routerstatus_t; /** DOCDOC */ typedef struct short_policy_entry_t { uint16_t min_port, max_port; } short_policy_entry_t; /** DOCDOC */ typedef struct short_policy_t { unsigned int is_accept : 1; unsigned int n_entries : 31; short_policy_entry_t entries[1]; } short_policy_t; /** A microdescriptor is the smallest amount of information needed to build a * circuit through a router. They are generated by the directory authorities, * using information from the uploaded routerinfo documents. They are not Loading Loading @@ -1689,9 +1701,8 @@ typedef struct microdesc_t { crypto_pk_env_t *onion_pkey; /** As routerinfo_t.family */ smartlist_t *family; /** Encoded exit policy summary */ char *exitsummary; /**< exit policy summary - * XXX this probably should not stay a string. */ /** Exit policy summary */ short_policy_t *exit_policy; } microdesc_t; /** A node_t represents a Tor router. Loading Loading @@ -3444,7 +3455,7 @@ typedef enum { ADDR_POLICY_PROBABLY_ACCEPTED=1, /** Part of the address was unknown, but as far as we can tell, it was * rejected. */ ADDR_POLICY_PROBABLY_REJECTED=2 ADDR_POLICY_PROBABLY_REJECTED=2, } addr_policy_result_t; /********************************* rephist.c ***************************/ Loading src/or/policies.c +161 −5 Original line number Diff line number Diff line Loading @@ -1315,6 +1315,157 @@ policy_summarize(smartlist_t *policy) return result; } /** DOCDOC */ 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 = sizeof(short_policy_t) + sizeof(short_policy_entry_t)*(n_entries-1); 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; } /** DOCDOC */ void short_policy_free(short_policy_t *policy) { tor_free(policy); } /** DOCDOC */ 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_internal(addr, 0) || tor_addr_is_null(addr) || 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; } /* DOCDOC */ 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. */ Loading @@ -1333,11 +1484,16 @@ addr_policy_result_t compare_tor_addr_to_node_policy(const tor_addr_t *addr, uint16_t port, const node_t *node) { (void)addr; (void)port; (void)node; UNIMPLEMENTED_NODELIST(); return 0; if (node->ri) return compare_tor_addr_to_addr_policy(addr, port, node->ri->exit_policy); else if (node->md && 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 Loading src/or/policies.h +7 −0 Original line number Diff line number Diff line Loading @@ -63,5 +63,12 @@ void policies_free_all(void); char *policy_summarize(smartlist_t *policy); short_policy_t *parse_short_policy(const char *summary); void short_policy_free(short_policy_t *policy); int short_policy_is_reject_star(const short_policy_t *policy); addr_policy_result_t compare_tor_addr_to_short_policy( const tor_addr_t *addr, uint16_t port, const short_policy_t *policy); #endif Loading
src/or/microdesc.c +5 −4 Original line number Diff line number Diff line Loading @@ -4,12 +4,13 @@ #include "or.h" #include "config.h" #include "directory.h" #include "dirserv.h" #include "microdesc.h" #include "nodelist.h" #include "routerparse.h" #include "networkstatus.h" #include "nodelist.h" #include "policies.h" #include "routerlist.h" #include "dirserv.h" #include "routerparse.h" /** A data structure to hold a bunch of cached microdescriptors. There are * two active files in the cache: a "cache file" that we mmap, and a "journal Loading Loading @@ -458,7 +459,7 @@ microdesc_free(microdesc_t *md) SMARTLIST_FOREACH(md->family, char *, cp, tor_free(cp)); smartlist_free(md->family); } tor_free(md->exitsummary); short_policy_free(md->exit_policy); tor_free(md); } Loading
src/or/nodelist.c +10 −5 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ #include "microdesc.h" #include "networkstatus.h" #include "nodelist.h" #include "policies.h" #include "router.h" #include "routerlist.h" Loading Loading @@ -597,14 +598,18 @@ node_allows_single_hop_exits(const node_t *node) return 0; } /** Return true iff it seems that <b>node</b> has an exit policy that * doesn't actually permit anything to exit. */ /** Return true iff it seems that <b>node</b> has an exit policy that doesn't * actually permit anything to exit, or we don't know its exit policy */ int node_exit_policy_rejects_all(const node_t *node) { (void)node; UNIMPLEMENTED_NODELIST(); return 0; if (node->ri) return node->ri->policy_is_reject_star; else if (node->md) return node->md->exit_policy == NULL || short_policy_is_reject_star(node->md->exit_policy); else return 1; } /** Copy the address for <b>node</b> into *<b>addr_out</b>. */ Loading
src/or/or.h +15 −4 Original line number Diff line number Diff line Loading @@ -1648,6 +1648,18 @@ typedef struct routerstatus_t { } routerstatus_t; /** DOCDOC */ typedef struct short_policy_entry_t { uint16_t min_port, max_port; } short_policy_entry_t; /** DOCDOC */ typedef struct short_policy_t { unsigned int is_accept : 1; unsigned int n_entries : 31; short_policy_entry_t entries[1]; } short_policy_t; /** A microdescriptor is the smallest amount of information needed to build a * circuit through a router. They are generated by the directory authorities, * using information from the uploaded routerinfo documents. They are not Loading Loading @@ -1689,9 +1701,8 @@ typedef struct microdesc_t { crypto_pk_env_t *onion_pkey; /** As routerinfo_t.family */ smartlist_t *family; /** Encoded exit policy summary */ char *exitsummary; /**< exit policy summary - * XXX this probably should not stay a string. */ /** Exit policy summary */ short_policy_t *exit_policy; } microdesc_t; /** A node_t represents a Tor router. Loading Loading @@ -3444,7 +3455,7 @@ typedef enum { ADDR_POLICY_PROBABLY_ACCEPTED=1, /** Part of the address was unknown, but as far as we can tell, it was * rejected. */ ADDR_POLICY_PROBABLY_REJECTED=2 ADDR_POLICY_PROBABLY_REJECTED=2, } addr_policy_result_t; /********************************* rephist.c ***************************/ Loading
src/or/policies.c +161 −5 Original line number Diff line number Diff line Loading @@ -1315,6 +1315,157 @@ policy_summarize(smartlist_t *policy) return result; } /** DOCDOC */ 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 = sizeof(short_policy_t) + sizeof(short_policy_entry_t)*(n_entries-1); 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; } /** DOCDOC */ void short_policy_free(short_policy_t *policy) { tor_free(policy); } /** DOCDOC */ 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_internal(addr, 0) || tor_addr_is_null(addr) || 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; } /* DOCDOC */ 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. */ Loading @@ -1333,11 +1484,16 @@ addr_policy_result_t compare_tor_addr_to_node_policy(const tor_addr_t *addr, uint16_t port, const node_t *node) { (void)addr; (void)port; (void)node; UNIMPLEMENTED_NODELIST(); return 0; if (node->ri) return compare_tor_addr_to_addr_policy(addr, port, node->ri->exit_policy); else if (node->md && 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 Loading
src/or/policies.h +7 −0 Original line number Diff line number Diff line Loading @@ -63,5 +63,12 @@ void policies_free_all(void); char *policy_summarize(smartlist_t *policy); short_policy_t *parse_short_policy(const char *summary); void short_policy_free(short_policy_t *policy); int short_policy_is_reject_star(const short_policy_t *policy); addr_policy_result_t compare_tor_addr_to_short_policy( const tor_addr_t *addr, uint16_t port, const short_policy_t *policy); #endif