Back to index

tor  0.2.3.18-rc
Classes | Defines | Typedefs | Functions | Variables
policies.c File Reference

Code to parse and use address policies and exit policies. More...

#include "or.h"
#include "config.h"
#include "dirserv.h"
#include "nodelist.h"
#include "policies.h"
#include "routerparse.h"
#include "geoip.h"
#include "ht.h"

Go to the source code of this file.

Classes

struct  policy_summary_item_t
 Element of an exit policy summary. More...
struct  policy_map_ent_t
 Node in hashtable used to store address policy entries. More...

Defines

#define REJECT(arg)   STMT_BEGIN *msg = tor_strdup(arg); goto err; STMT_END
#define DEFAULT_EXIT_POLICY
#define AT(x)   ((policy_summary_item_t*)smartlist_get(summary, x))
#define REJECT_CUTOFF_COUNT   (1<<25)

Typedefs

typedef struct
policy_summary_item_t 
policy_summary_item_t
 Element of an exit policy summary.
typedef struct policy_map_ent_t policy_map_ent_t
 Node in hashtable used to store address policy entries.

Functions

void policy_expand_private (smartlist_t **policy)
 Replace all "private" entries in *policy with their expanded equivalents.
static int parse_addr_policy (config_line_t *cfg, smartlist_t **dest, int assume_action)
 Given a linked list of config lines containing "allow" and "deny" tokens, parse them and append the result to dest.
static int parse_reachable_addresses (void)
 Helper: parse the Reachable(Dir|OR)?Addresses fields into reachable_(or|dir)_addr_policy.
int firewall_is_fascist_or (void)
 Return true iff the firewall options might block any address:port combination.
static int addr_policy_permits_tor_addr (const tor_addr_t *addr, uint16_t port, smartlist_t *policy)
 Return true iff policy (possibly NULL) will allow a connection to addr:port.
static int addr_policy_permits_address (uint32_t addr, uint16_t port, smartlist_t *policy)
 Return true iff policy (possibly NULL) will allow a connection to addr:port.
int 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 addr:port.
int fascist_firewall_allows_or (const routerinfo_t *ri)
 Return true iff we think our firewall will let us make an OR connection to ri.
int fascist_firewall_allows_node (const node_t *node)
 Return true iff we think our firewall will let us make an OR connection to node.
int fascist_firewall_allows_address_dir (const tor_addr_t *addr, uint16_t port)
 Return true iff we think our firewall will let us make a directory connection to addr:port.
int dir_policy_permits_address (const tor_addr_t *addr)
 Return 1 if addr is permitted to connect to our dir port, based on dir_policy.
int socks_policy_permits_address (const tor_addr_t *addr)
 Return 1 if addr is permitted to connect to our socks port, based on socks_policy.
static int addr_is_in_cc_list (uint32_t addr, const smartlist_t *cc_list)
 Return true iff the address addr is in a country listed in the case-insensitive list of country codes cc_list.
int authdir_policy_permits_address (uint32_t addr, uint16_t port)
 Return 1 if addr:port is permitted to publish to our directory, based on authdir_reject_policy.
int authdir_policy_valid_address (uint32_t addr, uint16_t port)
 Return 1 if addr:port is considered valid in our directory, based on authdir_invalid_policy.
int authdir_policy_baddir_address (uint32_t addr, uint16_t port)
 Return 1 if addr:port should be marked as a bad dir, based on authdir_baddir_policy.
int authdir_policy_badexit_address (uint32_t addr, uint16_t port)
 Return 1 if addr:port should be marked as a bad exit, based on authdir_badexit_policy.
int validate_addr_policies (const or_options_t *options, char **msg)
 Config helper: If there's any problem with the policy configuration options in options, return -1 and set msg to a newly allocated description of the error.
static int load_policy_from_option (config_line_t *config, smartlist_t **policy, int assume_action)
 Parse string in the same way that the exit policy is parsed, and put the processed version in *policy.
int policies_parse_from_options (const or_options_t *options)
 Set all policies based on options, which should have been validated first by validate_addr_policies.
static int cmp_single_addr_policy (addr_policy_t *a, addr_policy_t *b)
 Compare two provided address policy items, and return -1, 0, or 1 if the first is less than, equal to, or greater than the second.
int cmp_addr_policies (smartlist_t *a, smartlist_t *b)
 Like cmp_single_addr_policy() above, but looks at the whole set of policies in each case.
static HT_HEAD (policy_map, policy_map_ent_t)
static unsigned int policy_hash (policy_map_ent_t *ent)
 Return a hashcode for ent
 HT_PROTOTYPE (HT_GENERATE(policy_map, HT_GENERATE(policy_map_ent_t, HT_GENERATE(node, HT_GENERATE(policy_hash, HT_GENERATE(policy_eq)
 Given a pointer to an addr_policy_t, return a copy of the pointer to the "canonical" copy of that addr_policy_t; the canonical copy is a single reference-counted object.
static addr_policy_result_t compare_known_tor_addr_to_addr_policy (const tor_addr_t *addr, uint16_t port, const smartlist_t *policy)
 Helper for compare_tor_addr_to_addr_policy.
static addr_policy_result_t compare_known_tor_addr_to_addr_policy_noport (const tor_addr_t *addr, const smartlist_t *policy)
 Helper for compare_tor_addr_to_addr_policy.
static addr_policy_result_t compare_unknown_tor_addr_to_addr_policy (uint16_t port, const smartlist_t *policy)
 Helper for compare_tor_addr_to_addr_policy.
addr_policy_result_t compare_tor_addr_to_addr_policy (const tor_addr_t *addr, uint16_t port, const smartlist_t *policy)
 Decide whether a given addr:port is definitely accepted, definitely rejected, probably accepted, or probably rejected by a given policy.
static int addr_policy_covers (addr_policy_t *a, addr_policy_t *b)
 Return true iff the address policy a covers every case that would be covered by b, so that a,b is redundant.
static int addr_policy_intersects (addr_policy_t *a, addr_policy_t *b)
 Return true iff the address policies a and b intersect, that is, there exists an address/port that is covered by a that is also covered by b.
static void append_exit_policy_string (smartlist_t **policy, const char *more)
 Add the exit policy described by more to policy.
static void exit_policy_remove_redundancies (smartlist_t *dest)
 Detect and excise "dead code" from the policy *dest.
int policies_parse_exit_policy (config_line_t *cfg, smartlist_t **dest, int rejectprivate, const char *local_address, int add_default_policy)
 Parse the exit policy cfg into the linked list *dest.
void policies_exit_policy_append_reject_star (smartlist_t **dest)
 Add "reject *:*" to the end of the policy in *dest, allocating *dest as needed.
void policies_set_node_exitpolicy_to_reject_all (node_t *node)
 Replace the exit policy of node with reject *:*.
static int exit_policy_is_general_exit_helper (smartlist_t *policy, int port)
 Return 1 if there is at least one /8 subnet in policy that allows exiting to port.
int exit_policy_is_general_exit (smartlist_t *policy)
 Return true iff ri is "useful as an exit node", meaning it allows exit to at least one /8 address space for at least two of ports 80, 443, and 6667.
int policy_is_reject_star (const smartlist_t *policy)
 Return false if policy might permit access to some addr:port; otherwise if we are certain it rejects everything, return true.
int policy_write_item (char *buf, size_t buflen, addr_policy_t *policy, int format_for_desc)
 Write a single address policy to the buf_len byte buffer at buf.
static smartlist_tpolicy_summary_create (void)
 Create a new exit policy summary, initially only with a single port 1-64k item.
static policy_summary_item_tpolicy_summary_item_split (policy_summary_item_t *old, uint16_t new_starts)
 Split the summary item in item at the port new_starts.
static int policy_summary_split (smartlist_t *summary, uint16_t prt_min, uint16_t prt_max)
 Split an exit policy summary so that prt_min and prt_max fall at exactly the start and end of an item respectively.
static void policy_summary_accept (smartlist_t *summary, uint16_t prt_min, uint16_t prt_max)
 Mark port ranges as accepted if they are below the reject_count.
static void policy_summary_reject (smartlist_t *summary, maskbits_t maskbits, uint16_t prt_min, uint16_t prt_max)
 Count the number of addresses in a network with prefixlen maskbits against the given portrange.
static void policy_summary_add_item (smartlist_t *summary, addr_policy_t *p)
 Add a single exit policy item to our summary: If it is an accept ignore it unless it is for all IP addresses ("*"), i.e.
char * policy_summarize (smartlist_t *policy)
 Create a string representing a summary for an exit policy.
short_policy_tparse_short_policy (const char *summary)
 Convert a summarized policy string into a short_policy_t.
void short_policy_free (short_policy_t *policy)
 Release all storage held in policy.
addr_policy_result_t compare_tor_addr_to_short_policy (const tor_addr_t *addr, uint16_t port, const short_policy_t *policy)
 See whether the addr:port address is likely to be accepted or rejected by the summarized policy policy.
int short_policy_is_reject_star (const short_policy_t *policy)
 Return true iff policy seems reject all ports.
addr_policy_result_t compare_tor_addr_to_node_policy (const tor_addr_t *addr, uint16_t port, const node_t *node)
 Decides whether addr:port is probably or definitely accepted or rejcted by node.
int getinfo_helper_policies (control_connection_t *conn, const char *question, char **answer, const char **errmsg)
 Implementation for GETINFO control command: knows the answer for questions about "exit-policy/...".
void addr_policy_list_free (smartlist_t *lst)
 Release all storage held by p.
void addr_policy_free (addr_policy_t *p)
 Release all storage held by p.
void policies_free_all (void)
 Release all storage held by policy variables.

Variables

static smartlist_tsocks_policy = NULL
 Policy that addresses for incoming SOCKS connections must match.
static smartlist_tdir_policy = NULL
 Policy that addresses for incoming directory connections must match.
static smartlist_tauthdir_reject_policy = NULL
 Policy that addresses for incoming router descriptors must match in order to be published by us.
static smartlist_tauthdir_invalid_policy = NULL
 Policy that addresses for incoming router descriptors must match in order to be marked as valid in our networkstatus.
static smartlist_tauthdir_baddir_policy = NULL
 Policy that addresses for incoming router descriptors must not match in order to not be marked as BadDirectory.
static smartlist_tauthdir_badexit_policy = NULL
 Policy that addresses for incoming router descriptors must not match in order to not be marked as BadExit.
static smartlist_treachable_or_addr_policy = NULL
 Parsed addr_policy_t describing which addresses we believe we can start circuits at.
static smartlist_treachable_dir_addr_policy = NULL
 Parsed addr_policy_t describing which addresses we believe we can connect to directories at.
static const char * private_nets []
 Private networks.

Detailed Description

Code to parse and use address policies and exit policies.

Definition in file policies.c.


Class Documentation

struct policy_summary_item_t

Element of an exit policy summary.

Definition at line 45 of file policies.c.

Class Members
unsigned int accepted:1
uint16_t prt_max Highest port number to accept/reject.
uint16_t prt_min Lowest port number to accept/reject.
uint64_t reject_count Number of IP-Addresses that are rejected to this port range.
struct policy_map_ent_t

Node in hashtable used to store address policy entries.

Definition at line 533 of file policies.c.


Define Documentation

#define AT (   x)    ((policy_summary_item_t*)smartlist_get(summary, x))

Definition at line 1100 of file policies.c.

Value:
"reject *:25,reject *:119,reject *:135-139,reject *:445,"         \
  "reject *:563,reject *:1214,reject *:4661-4666,"                  \
  "reject *:6346-6429,reject *:6699,reject *:6881-6999,accept *:*"

Definition at line 854 of file policies.c.

#define REJECT (   arg)    STMT_BEGIN *msg = tor_strdup(arg); goto err; STMT_END

Definition at line 375 of file policies.c.

#define REJECT_CUTOFF_COUNT   (1<<25)

Definition at line 1102 of file policies.c.


Typedef Documentation

Node in hashtable used to store address policy entries.

Element of an exit policy summary.


Function Documentation

static int addr_is_in_cc_list ( uint32_t  addr,
const smartlist_t cc_list 
) [static]

Return true iff the address addr is in a country listed in the case-insensitive list of country codes cc_list.

Definition at line 320 of file policies.c.

{
  country_t country;
  const char *name;
  if (!cc_list)
    return 0;
  country = geoip_get_country_by_ip(addr);
  name = geoip_get_country_name(country);
  return smartlist_string_isin_case(cc_list, name);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int addr_policy_covers ( addr_policy_t a,
addr_policy_t b 
) [static]

Return true iff the address policy a covers every case that would be covered by b, so that a,b is redundant.

Definition at line 729 of file policies.c.

{
  /* We can ignore accept/reject, since "accept *:80, reject *:80" reduces
   * to "accept *:80". */
  if (a->maskbits > b->maskbits) {
    /* a has more fixed bits than b; it can't possibly cover b. */
    return 0;
  }
  if (tor_addr_compare_masked(&a->addr, &b->addr, a->maskbits, CMP_EXACT)) {
    /* There's a fixed bit in a that's set differently in b. */
    return 0;
  }
  return (a->prt_min <= b->prt_min && a->prt_max >= b->prt_max);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Release all storage held by p.

Definition at line 1537 of file policies.c.

{
  if (!p)
    return;

  if (--p->refcnt <= 0) {
    if (p->is_canonical) {
      policy_map_ent_t search, *found;
      search.policy = p;
      found = HT_REMOVE(policy_map, &policy_root, &search);
      if (found) {
        tor_assert(p == found->policy);
        tor_free(found);
      }
    }
    tor_free(p);
  }
}

Here is the caller graph for this function:

static int addr_policy_intersects ( addr_policy_t a,
addr_policy_t b 
) [static]

Return true iff the address policies a and b intersect, that is, there exists an address/port that is covered by a that is also covered by b.

Definition at line 749 of file policies.c.

{
  maskbits_t minbits;
  /* All the bits we care about are those that are set in both
   * netmasks.  If they are equal in a and b's networkaddresses
   * then the networks intersect.  If there is a difference,
   * then they do not. */
  if (a->maskbits < b->maskbits)
    minbits = a->maskbits;
  else
    minbits = b->maskbits;
  if (tor_addr_compare_masked(&a->addr, &b->addr, minbits, CMP_EXACT))
    return 0;
  if (a->prt_max < b->prt_min || b->prt_max < a->prt_min)
    return 0;
  return 1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Release all storage held by p.

Definition at line 1527 of file policies.c.

{
  if (!lst)
    return;
  SMARTLIST_FOREACH(lst, addr_policy_t *, policy, addr_policy_free(policy));
  smartlist_free(lst);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int addr_policy_permits_address ( uint32_t  addr,
uint16_t  port,
smartlist_t policy 
) [static]

Return true iff policy (possibly NULL) will allow a connection to addr:port.

addr is an IPv4 address given in host order.

Definition at line 246 of file policies.c.

{
  tor_addr_t a;
  tor_addr_from_ipv4h(&a, addr);
  return addr_policy_permits_tor_addr(&a, port, policy);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int addr_policy_permits_tor_addr ( const tor_addr_t addr,
uint16_t  port,
smartlist_t policy 
) [static]

Return true iff policy (possibly NULL) will allow a connection to addr:port.

Definition at line 223 of file policies.c.

{
  addr_policy_result_t p;
  p = compare_tor_addr_to_addr_policy(addr, port, policy);
  switch (p) {
    case ADDR_POLICY_PROBABLY_ACCEPTED:
    case ADDR_POLICY_ACCEPTED:
      return 1;
    case ADDR_POLICY_PROBABLY_REJECTED:
    case ADDR_POLICY_REJECTED:
      return 0;
    default:
      log_warn(LD_BUG, "Unexpected result: %d", (int)p);
      return 0;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void append_exit_policy_string ( smartlist_t **  policy,
const char *  more 
) [static]

Add the exit policy described by more to policy.

Definition at line 770 of file policies.c.

{
  config_line_t tmp;

  tmp.key = NULL;
  tmp.value = (char*) more;
  tmp.next = NULL;
  if (parse_addr_policy(&tmp, policy, -1)<0) {
    log_warn(LD_BUG, "Unable to parse internally generated policy %s",more);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int authdir_policy_baddir_address ( uint32_t  addr,
uint16_t  port 
)

Return 1 if addr:port should be marked as a bad dir, based on authdir_baddir_policy.

Else return 0.

Definition at line 357 of file policies.c.

{
  if (! addr_policy_permits_address(addr, port, authdir_baddir_policy))
    return 1;
  return addr_is_in_cc_list(addr, get_options()->AuthDirBadDirCCs);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int authdir_policy_badexit_address ( uint32_t  addr,
uint16_t  port 
)

Return 1 if addr:port should be marked as a bad exit, based on authdir_badexit_policy.

Else return 0.

Definition at line 368 of file policies.c.

{
  if (! addr_policy_permits_address(addr, port, authdir_badexit_policy))
    return 1;
  return addr_is_in_cc_list(addr, get_options()->AuthDirBadExitCCs);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int authdir_policy_permits_address ( uint32_t  addr,
uint16_t  port 
)

Return 1 if addr:port is permitted to publish to our directory, based on authdir_reject_policy.

Else return 0.

Definition at line 335 of file policies.c.

{
  if (! addr_policy_permits_address(addr, port, authdir_reject_policy))
    return 0;
  return !addr_is_in_cc_list(addr, get_options()->AuthDirRejectCCs);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int authdir_policy_valid_address ( uint32_t  addr,
uint16_t  port 
)

Return 1 if addr:port is considered valid in our directory, based on authdir_invalid_policy.

Else return 0.

Definition at line 346 of file policies.c.

{
  if (! addr_policy_permits_address(addr, port, authdir_invalid_policy))
    return 0;
  return !addr_is_in_cc_list(addr, get_options()->AuthDirInvalidCCs);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int cmp_addr_policies ( smartlist_t a,
smartlist_t b 
)

Like cmp_single_addr_policy() above, but looks at the whole set of policies in each case.

Definition at line 514 of file policies.c.

{
  int r, i;
  int len_a = a ? smartlist_len(a) : 0;
  int len_b = b ? smartlist_len(b) : 0;

  for (i = 0; i < len_a && i < len_b; ++i) {
    if ((r = cmp_single_addr_policy(smartlist_get(a, i), smartlist_get(b, i))))
      return r;
  }
  if (i == len_a && i == len_b)
    return 0;
  if (i < len_a)
    return -1;
  else
    return 1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int cmp_single_addr_policy ( addr_policy_t a,
addr_policy_t b 
) [static]

Compare two provided address policy items, and return -1, 0, or 1 if the first is less than, equal to, or greater than the second.

Definition at line 493 of file policies.c.

{
  int r;
  if ((r=((int)a->policy_type - (int)b->policy_type)))
    return r;
  if ((r=((int)a->is_private - (int)b->is_private)))
    return r;
  if ((r=tor_addr_compare(&a->addr, &b->addr, CMP_EXACT)))
    return r;
  if ((r=((int)a->maskbits - (int)b->maskbits)))
    return r;
  if ((r=((int)a->prt_min - (int)b->prt_min)))
    return r;
  if ((r=((int)a->prt_max - (int)b->prt_max)))
    return r;
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static addr_policy_result_t compare_known_tor_addr_to_addr_policy ( const tor_addr_t addr,
uint16_t  port,
const smartlist_t policy 
) [static]

Helper for compare_tor_addr_to_addr_policy.

Implements the case where addr and port are both known.

Definition at line 600 of file policies.c.

{
  /* We know the address and port, and we know the policy, so we can just
   * compute an exact match. */
  SMARTLIST_FOREACH_BEGIN(policy, addr_policy_t *, tmpe) {
    /* Address is known */
    if (!tor_addr_compare_masked(addr, &tmpe->addr, tmpe->maskbits,
                                 CMP_EXACT)) {
      if (port >= tmpe->prt_min && port <= tmpe->prt_max) {
        /* Exact match for the policy */
        return tmpe->policy_type == ADDR_POLICY_ACCEPT ?
          ADDR_POLICY_ACCEPTED : ADDR_POLICY_REJECTED;
      }
    }
  } SMARTLIST_FOREACH_END(tmpe);

  /* accept all by default. */
  return ADDR_POLICY_ACCEPTED;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static addr_policy_result_t compare_known_tor_addr_to_addr_policy_noport ( const tor_addr_t addr,
const smartlist_t policy 
) [static]

Helper for compare_tor_addr_to_addr_policy.

Implements the case where addr is known but port is not.

Definition at line 624 of file policies.c.

{
  /* We look to see if there's a definite match.  If so, we return that
     match's value, unless there's an intervening possible match that says
     something different. */
  int maybe_accept = 0, maybe_reject = 0;

  SMARTLIST_FOREACH_BEGIN(policy, addr_policy_t *, tmpe) {
    if (!tor_addr_compare_masked(addr, &tmpe->addr, tmpe->maskbits,
                                 CMP_EXACT)) {
      if (tmpe->prt_min <= 1 && tmpe->prt_max >= 65535) {
        /* Definitely matches, since it covers all ports. */
        if (tmpe->policy_type == ADDR_POLICY_ACCEPT) {
          /* If we already hit a clause that might trigger a 'reject', than we
           * can't be sure of this certain 'accept'.*/
          return maybe_reject ? ADDR_POLICY_PROBABLY_ACCEPTED :
            ADDR_POLICY_ACCEPTED;
        } else {
          return maybe_accept ? ADDR_POLICY_PROBABLY_REJECTED :
            ADDR_POLICY_REJECTED;
        }
      } else {
        /* Might match. */
        if (tmpe->policy_type == ADDR_POLICY_REJECT)
          maybe_reject = 1;
        else
          maybe_accept = 1;
      }
    }
  } SMARTLIST_FOREACH_END(tmpe);

  /* accept all by default. */
  return maybe_reject ? ADDR_POLICY_PROBABLY_ACCEPTED : ADDR_POLICY_ACCEPTED;
}

Here is the call graph for this function:

Here is the caller graph for this function:

addr_policy_result_t compare_tor_addr_to_addr_policy ( const tor_addr_t addr,
uint16_t  port,
const smartlist_t policy 
)

Decide whether a given addr:port is definitely accepted, definitely rejected, probably accepted, or probably rejected by a given policy.

If addr is 0, we don't know the IP of the target address. If port is 0, we don't know the port of the target address. (At least one of addr and port must be provided. If you want to know whether a policy would definitely reject an unknown address:port, use policy_is_reject_star().)

We could do better by assuming that some ranges never match typical addresses (127.0.0.1, and so on). But we'll try this for now.

Definition at line 710 of file policies.c.

{
  if (!policy) {
    /* no policy? accept all. */
    return ADDR_POLICY_ACCEPTED;
  } 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) {
    return compare_known_tor_addr_to_addr_policy_noport(addr, policy);
  } else {
    return compare_known_tor_addr_to_addr_policy(addr, port, policy);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

addr_policy_result_t compare_tor_addr_to_node_policy ( const tor_addr_t addr,
uint16_t  port,
const node_t node 
)

Decides whether addr:port is probably or definitely accepted or rejcted by node.

See compare_tor_addr_to_addr_policy for details on addr/port interpretation.

Definition at line 1492 of file policies.c.

{
  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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

addr_policy_result_t compare_tor_addr_to_short_policy ( const tor_addr_t addr,
uint16_t  port,
const short_policy_t policy 
)

See whether the addr:port address is likely to be accepted or rejected by the summarized policy policy.

Return values are as for compare_tor_addr_to_addr_policy. Unlike the regular addr_policy functions, requires the port be specified.

Definition at line 1426 of file policies.c.

{
  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? -NM */
  /* We should be sure not to return ADDR_POLICY_ACCEPTED in the accept
   * case here, because it would cause clients to believe that the node
   * allows exit enclaving. Trying it anyway would open up a cool attack
   * where the node refuses due to exitpolicy, the client reacts in
   * surprise by rewriting the node's exitpolicy to reject *:*, and then
   * a bad guy targets users by causing them to attempt such connections
   * to 98% of the exits.
   *
   * Once microdescriptors can handle addresses in special cases (e.g. if
   * we ever solve ticket 1774), we can provide certainty here. -RD */
  if (accept)
    return ADDR_POLICY_PROBABLY_ACCEPTED;
  else
    return ADDR_POLICY_REJECTED;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static addr_policy_result_t compare_unknown_tor_addr_to_addr_policy ( uint16_t  port,
const smartlist_t policy 
) [static]

Helper for compare_tor_addr_to_addr_policy.

Implements the case where port is known but address is not.

Definition at line 663 of file policies.c.

{
  /* We look to see if there's a definite match.  If so, we return that
     match's value, unless there's an intervening possible match that says
     something different. */
  int maybe_accept = 0, maybe_reject = 0;

  SMARTLIST_FOREACH_BEGIN(policy, addr_policy_t *, tmpe) {
    if (tmpe->prt_min <= port && port <= tmpe->prt_max) {
      if (tmpe->maskbits == 0) {
        /* Definitely matches, since it covers all addresses. */
        if (tmpe->policy_type == ADDR_POLICY_ACCEPT) {
          /* If we already hit a clause that might trigger a 'reject', than we
           * can't be sure of this certain 'accept'.*/
          return maybe_reject ? ADDR_POLICY_PROBABLY_ACCEPTED :
            ADDR_POLICY_ACCEPTED;
        } else {
          return maybe_accept ? ADDR_POLICY_PROBABLY_REJECTED :
            ADDR_POLICY_REJECTED;
        }
      } else {
        /* Might match. */
        if (tmpe->policy_type == ADDR_POLICY_REJECT)
          maybe_reject = 1;
        else
          maybe_accept = 1;
      }
    }
  } SMARTLIST_FOREACH_END(tmpe);

  /* accept all by default. */
  return maybe_reject ? ADDR_POLICY_PROBABLY_ACCEPTED : ADDR_POLICY_ACCEPTED;
}

Here is the caller graph for this function:

int dir_policy_permits_address ( const tor_addr_t addr)

Return 1 if addr is permitted to connect to our dir port, based on dir_policy.

Else return 0.

Definition at line 303 of file policies.c.

Here is the call graph for this function:

Here is the caller graph for this function:

Return true iff ri is "useful as an exit node", meaning it allows exit to at least one /8 address space for at least two of ports 80, 443, and 6667.

Definition at line 954 of file policies.c.

{
  static const int ports[] = { 80, 443, 6667 };
  int n_allowed = 0;
  int i;
  if (!policy) /*XXXX disallow NULL policies? */
    return 0;

  for (i = 0; i < 3; ++i) {
    n_allowed += exit_policy_is_general_exit_helper(policy, ports[i]);
  }
  return n_allowed >= 2;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int exit_policy_is_general_exit_helper ( smartlist_t policy,
int  port 
) [static]

Return 1 if there is at least one /8 subnet in policy that allows exiting to port.

Otherwise, return 0.

Definition at line 908 of file policies.c.

{
  uint32_t mask, ip, i;
  /* Is this /8 rejected (1), or undecided (0)? */
  char subnet_status[256];

  memset(subnet_status, 0, sizeof(subnet_status));
  SMARTLIST_FOREACH(policy, addr_policy_t *, p, {
    if (tor_addr_family(&p->addr) != AF_INET)
      continue; /* IPv4 only for now */
    if (p->prt_min > port || p->prt_max < port)
      continue; /* Doesn't cover our port. */
    mask = 0;
    tor_assert(p->maskbits <= 32);

    if (p->maskbits)
      mask = UINT32_MAX<<(32-p->maskbits);
    ip = tor_addr_to_ipv4h(&p->addr);

    /* Calculate the first and last subnet that this exit policy touches
     * and set it as loop boundaries. */
    for (i = ((mask & ip)>>24); i <= (~((mask & ip) ^ mask)>>24); ++i) {
      tor_addr_t addr;
      if (subnet_status[i] != 0)
        continue; /* We already reject some part of this /8 */
      tor_addr_from_ipv4h(&addr, i<<24);
      if (tor_addr_is_internal(&addr, 0))
        continue; /* Local or non-routable addresses */
      if (p->policy_type == ADDR_POLICY_ACCEPT) {
        if (p->maskbits > 8)
          continue; /* Narrower than a /8. */
        /* We found an allowed subnet of at least size /8. Done
         * for this port! */
        return 1;
      } else if (p->policy_type == ADDR_POLICY_REJECT) {
        subnet_status[i] = 1;
      }
    }
  });
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void exit_policy_remove_redundancies ( smartlist_t dest) [static]

Detect and excise "dead code" from the policy *dest.

Definition at line 784 of file policies.c.

{
  addr_policy_t *ap, *tmp, *victim;
  int i, j;

  /* Step one: find a *:* entry and cut off everything after it. */
  for (i = 0; i < smartlist_len(dest); ++i) {
    ap = smartlist_get(dest, i);
    if (ap->maskbits == 0 && ap->prt_min <= 1 && ap->prt_max >= 65535) {
      /* This is a catch-all line -- later lines are unreachable. */
      while (i+1 < smartlist_len(dest)) {
        victim = smartlist_get(dest, i+1);
        smartlist_del(dest, i+1);
        addr_policy_free(victim);
      }
      break;
    }
  }

  /* Step two: for every entry, see if there's a redundant entry
   * later on, and remove it. */
  for (i = 0; i < smartlist_len(dest)-1; ++i) {
    ap = smartlist_get(dest, i);
    for (j = i+1; j < smartlist_len(dest); ++j) {
      tmp = smartlist_get(dest, j);
      tor_assert(j > i);
      if (addr_policy_covers(ap, tmp)) {
        char p1[POLICY_BUF_LEN], p2[POLICY_BUF_LEN];
        policy_write_item(p1, sizeof(p1), tmp, 0);
        policy_write_item(p2, sizeof(p2), ap, 0);
        log(LOG_DEBUG, LD_CONFIG, "Removing exit policy %s (%d).  It is made "
            "redundant by %s (%d).", p1, j, p2, i);
        smartlist_del_keeporder(dest, j--);
        addr_policy_free(tmp);
      }
    }
  }

  /* Step three: for every entry A, see if there's an entry B making this one
   * redundant later on.  This is the case if A and B are of the same type
   * (accept/reject), A is a subset of B, and there is no other entry of
   * different type in between those two that intersects with A.
   *
   * Anybody want to double-check the logic here? XXX
   */
  for (i = 0; i < smartlist_len(dest)-1; ++i) {
    ap = smartlist_get(dest, i);
    for (j = i+1; j < smartlist_len(dest); ++j) {
      // tor_assert(j > i); // j starts out at i+1; j only increases; i only
      //                    // decreases.
      tmp = smartlist_get(dest, j);
      if (ap->policy_type != tmp->policy_type) {
        if (addr_policy_intersects(ap, tmp))
          break;
      } else { /* policy_types are equal. */
        if (addr_policy_covers(tmp, ap)) {
          char p1[POLICY_BUF_LEN], p2[POLICY_BUF_LEN];
          policy_write_item(p1, sizeof(p1), ap, 0);
          policy_write_item(p2, sizeof(p2), tmp, 0);
          log(LOG_DEBUG, LD_CONFIG, "Removing exit policy %s.  It is already "
              "covered by %s.", p1, p2);
          smartlist_del_keeporder(dest, i--);
          addr_policy_free(ap);
          break;
        }
      }
    }
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int fascist_firewall_allows_address_dir ( const tor_addr_t addr,
uint16_t  port 
)

Return true iff we think our firewall will let us make a directory connection to addr:port.

Definition at line 293 of file policies.c.

Here is the call graph for this function:

Here is the caller graph for this function:

int 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 addr:port.

Definition at line 257 of file policies.c.

Here is the call graph for this function:

Here is the caller graph for this function:

int fascist_firewall_allows_node ( const node_t node)

Return true iff we think our firewall will let us make an OR connection to node.

Definition at line 277 of file policies.c.

{
  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;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Return true iff we think our firewall will let us make an OR connection to ri.

Definition at line 266 of file policies.c.

{
  /* XXXX proposal 118 */
  tor_addr_t addr;
  tor_addr_from_ipv4h(&addr, ri->addr);
  return fascist_firewall_allows_address_or(&addr, ri->or_port);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int firewall_is_fascist_or ( void  )

Return true iff the firewall options might block any address:port combination.

Definition at line 214 of file policies.c.

{
  return reachable_or_addr_policy != NULL;
}

Here is the caller graph for this function:

int getinfo_helper_policies ( control_connection_t conn,
const char *  question,
char **  answer,
const char **  errmsg 
)

Implementation for GETINFO control command: knows the answer for questions about "exit-policy/...".

Definition at line 1513 of file policies.c.

{
  (void) conn;
  (void) errmsg;
  if (!strcmp(question, "exit-policy/default")) {
    *answer = tor_strdup(DEFAULT_EXIT_POLICY);
  }
  return 0;
}
static HT_HEAD ( policy_map  ,
policy_map_ent_t   
) [static]

Definition at line 539 of file policies.c.

{
  return cmp_single_addr_policy(a->policy, b->policy) == 0;
}

Here is the call graph for this function:

HT_PROTOTYPE ( HT_GENERATE policy_map,
HT_GENERATE policy_map_ent_t,
HT_GENERATE node,
HT_GENERATE policy_hash,
HT_GENERATE policy_eq 
)

Given a pointer to an addr_policy_t, return a copy of the pointer to the "canonical" copy of that addr_policy_t; the canonical copy is a single reference-counted object.

Definition at line 567 of file policies.c.

{
  policy_map_ent_t search, *found;
  if (e->is_canonical)
    return e;

  search.policy = e;
  found = HT_FIND(policy_map, &policy_root, &search);
  if (!found) {
    found = tor_malloc_zero(sizeof(policy_map_ent_t));
    found->policy = tor_memdup(e, sizeof(addr_policy_t));
    found->policy->is_canonical = 1;
    found->policy->refcnt = 0;
    HT_INSERT(policy_map, &policy_root, found);
  }

  tor_assert(!cmp_single_addr_policy(found->policy, e));
  ++found->policy->refcnt;
  return found->policy;
}

Here is the call graph for this function:

static int load_policy_from_option ( config_line_t config,
smartlist_t **  policy,
int  assume_action 
) [static]

Parse string in the same way that the exit policy is parsed, and put the processed version in *policy.

Ignore port specifiers.

Definition at line 435 of file policies.c.

{
  int r;
  addr_policy_list_free(*policy);
  *policy = NULL;
  r = parse_addr_policy(config, policy, assume_action);
  if (r < 0) {
    return -1;
  }
  if (*policy) {
    SMARTLIST_FOREACH_BEGIN(*policy, addr_policy_t *, n) {
      /* ports aren't used in these. */
      if (n->prt_min > 1 || n->prt_max != 65535) {
        addr_policy_t newp, *c;
        memcpy(&newp, n, sizeof(newp));
        newp.prt_min = 1;
        newp.prt_max = 65535;
        newp.is_canonical = 0;
        c = addr_policy_get_canonical_entry(&newp);
        SMARTLIST_REPLACE_CURRENT(*policy, n, c);
        addr_policy_free(n);
      }
    } SMARTLIST_FOREACH_END(n);
  }
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int parse_addr_policy ( config_line_t cfg,
smartlist_t **  dest,
int  assume_action 
) [static]

Given a linked list of config lines containing "allow" and "deny" tokens, parse them and append the result to dest.

Return -1 if any tokens are malformed (and don't append any), else return 0.

If assume_action is nonnegative, then insert its action (ADDR_POLICY_ACCEPT or ADDR_POLICY_REJECT) for items that specify no action.

Definition at line 114 of file policies.c.

{
  smartlist_t *result;
  smartlist_t *entries;
  addr_policy_t *item;
  int r = 0;

  if (!cfg)
    return 0;

  result = smartlist_new();
  entries = smartlist_new();
  for (; cfg; cfg = cfg->next) {
    smartlist_split_string(entries, cfg->value, ",",
                           SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
    SMARTLIST_FOREACH(entries, const char *, ent,
    {
      log_debug(LD_CONFIG,"Adding new entry '%s'",ent);
      item = router_parse_addr_policy_item_from_string(ent, assume_action);
      if (item) {
        smartlist_add(result, item);
      } else {
        log_warn(LD_CONFIG,"Malformed policy '%s'.", ent);
        r = -1;
      }
    });
    SMARTLIST_FOREACH(entries, char *, ent, tor_free(ent));
    smartlist_clear(entries);
  }
  smartlist_free(entries);
  if (r == -1) {
    addr_policy_list_free(result);
  } else {
    policy_expand_private(&result);

    if (*dest) {
      smartlist_add_all(*dest, result);
      smartlist_free(result);
    } else {
      *dest = result;
    }
  }

  return r;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int parse_reachable_addresses ( void  ) [static]

Helper: parse the Reachable(Dir|OR)?Addresses fields into reachable_(or|dir)_addr_policy.

The options should already have been validated by validate_addr_policies.

Definition at line 166 of file policies.c.

{
  const or_options_t *options = get_options();
  int ret = 0;

  if (options->ReachableDirAddresses &&
      options->ReachableORAddresses &&
      options->ReachableAddresses) {
    log_warn(LD_CONFIG,
             "Both ReachableDirAddresses and ReachableORAddresses are set. "
             "ReachableAddresses setting will be ignored.");
  }
  addr_policy_list_free(reachable_or_addr_policy);
  reachable_or_addr_policy = NULL;
  if (!options->ReachableORAddresses && options->ReachableAddresses)
    log_info(LD_CONFIG,
             "Using ReachableAddresses as ReachableORAddresses.");
  if (parse_addr_policy(options->ReachableORAddresses ?
                          options->ReachableORAddresses :
                          options->ReachableAddresses,
                        &reachable_or_addr_policy, ADDR_POLICY_ACCEPT)) {
    log_warn(LD_CONFIG,
             "Error parsing Reachable%sAddresses entry; ignoring.",
             options->ReachableORAddresses ? "OR" : "");
    ret = -1;
  }

  addr_policy_list_free(reachable_dir_addr_policy);
  reachable_dir_addr_policy = NULL;
  if (!options->ReachableDirAddresses && options->ReachableAddresses)
    log_info(LD_CONFIG,
             "Using ReachableAddresses as ReachableDirAddresses");
  if (parse_addr_policy(options->ReachableDirAddresses ?
                          options->ReachableDirAddresses :
                          options->ReachableAddresses,
                        &reachable_dir_addr_policy, ADDR_POLICY_ACCEPT)) {
    if (options->ReachableDirAddresses)
      log_warn(LD_CONFIG,
               "Error parsing ReachableDirAddresses entry; ignoring.");
    ret = -1;
  }
  return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

short_policy_t* parse_short_policy ( const char *  summary)

Convert a summarized policy string into a short_policy_t.

Return NULL if the string is not well-formed.

Definition at line 1323 of file policies.c.

{
  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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Add "reject *:*" to the end of the policy in *dest, allocating *dest as needed.

Definition at line 893 of file policies.c.

{
  append_exit_policy_string(dest, "reject *:*");
}

Here is the call graph for this function:

Here is the caller graph for this function:

void policies_free_all ( void  )

Release all storage held by policy variables.

Definition at line 1558 of file policies.c.

{
  addr_policy_list_free(reachable_or_addr_policy);
  reachable_or_addr_policy = NULL;
  addr_policy_list_free(reachable_dir_addr_policy);
  reachable_dir_addr_policy = NULL;
  addr_policy_list_free(socks_policy);
  socks_policy = NULL;
  addr_policy_list_free(dir_policy);
  dir_policy = NULL;
  addr_policy_list_free(authdir_reject_policy);
  authdir_reject_policy = NULL;
  addr_policy_list_free(authdir_invalid_policy);
  authdir_invalid_policy = NULL;
  addr_policy_list_free(authdir_baddir_policy);
  authdir_baddir_policy = NULL;
  addr_policy_list_free(authdir_badexit_policy);
  authdir_badexit_policy = NULL;

  if (!HT_EMPTY(&policy_root)) {
    policy_map_ent_t **ent;
    int n = 0;
    char buf[POLICY_BUF_LEN];

    log_warn(LD_MM, "Still had %d address policies cached at shutdown.",
             (int)HT_SIZE(&policy_root));

    /* Note the first 10 cached policies to try to figure out where they
     * might be coming from. */
    HT_FOREACH(ent, policy_map, &policy_root) {
      if (++n > 10)
        break;
      if (policy_write_item(buf, sizeof(buf), (*ent)->policy, 0) >= 0)
        log_warn(LD_MM,"  %d [%d]: %s", n, (*ent)->policy->refcnt, buf);
    }
  }
  HT_CLEAR(policy_map, &policy_root);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int policies_parse_exit_policy ( config_line_t cfg,
smartlist_t **  dest,
int  rejectprivate,
const char *  local_address,
int  add_default_policy 
)

Parse the exit policy cfg into the linked list *dest.

If cfg doesn't end in an absolute accept or reject and if add_default_policy is true, add the default exit policy afterwards. If rejectprivate is true, prepend "reject private:*" to the policy. Return -1 if we can't parse cfg, else return 0.

Definition at line 867 of file policies.c.

{
  if (rejectprivate) {
    append_exit_policy_string(dest, "reject private:*");
    if (local_address) {
      char buf[POLICY_BUF_LEN];
      tor_snprintf(buf, sizeof(buf), "reject %s:*", local_address);
      append_exit_policy_string(dest, buf);
    }
  }
  if (parse_addr_policy(cfg, dest, -1))
    return -1;
  if (add_default_policy)
    append_exit_policy_string(dest, DEFAULT_EXIT_POLICY);
  else
    append_exit_policy_string(dest, "reject *:*");
  exit_policy_remove_redundancies(*dest);

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int policies_parse_from_options ( const or_options_t options)

Set all policies based on options, which should have been validated first by validate_addr_policies.

Definition at line 466 of file policies.c.

Here is the call graph for this function:

Here is the caller graph for this function:

Replace the exit policy of node with reject *:*.

Definition at line 900 of file policies.c.

{
  node->rejects_all = 1;
}

Here is the caller graph for this function:

void policy_expand_private ( smartlist_t **  policy)

Replace all "private" entries in *policy with their expanded equivalents.

Definition at line 68 of file policies.c.

{
  uint16_t port_min, port_max;

  int i;
  smartlist_t *tmp;

  if (!*policy) /*XXXX disallow NULL policies? */
    return;

  tmp = smartlist_new();

  SMARTLIST_FOREACH(*policy, addr_policy_t *, p,
  {
     if (! p->is_private) {
       smartlist_add(tmp, p);
       continue;
     }
     for (i = 0; private_nets[i]; ++i) {
       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(&newpolicy));
     }
     addr_policy_free(p);
  });

  smartlist_free(*policy);
  *policy = tmp;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static unsigned int policy_hash ( policy_map_ent_t ent) [static]

Return a hashcode for ent

Definition at line 550 of file policies.c.

{
  addr_policy_t *a = ent->policy;
  unsigned int r;
  if (a->is_private)
    r = 0x1234abcd;
  else
    r = tor_addr_hash(&a->addr);
  r += a->prt_min << 8;
  r += a->prt_max << 16;
  r += a->maskbits;
  if (a->policy_type == ADDR_POLICY_REJECT)
    r ^= 0xffffffff;

  return r;
}

Here is the call graph for this function:

int policy_is_reject_star ( const smartlist_t policy)

Return false if policy might permit access to some addr:port; otherwise if we are certain it rejects everything, return true.

Definition at line 971 of file policies.c.

{
  if (!policy) /*XXXX disallow NULL policies? */
    return 1;
  SMARTLIST_FOREACH(policy, addr_policy_t *, p, {
    if (p->policy_type == ADDR_POLICY_ACCEPT)
      return 0;
    else if (p->policy_type == ADDR_POLICY_REJECT &&
             p->prt_min <= 1 && p->prt_max == 65535 &&
             p->maskbits == 0)
      return 1;
  });
  return 1;
}

Here is the caller graph for this function:

char* policy_summarize ( smartlist_t policy)

Create a string representing a summary for an exit policy.

The summary will either be an "accept" plus a comma-separated list of port ranges or a "reject" plus port-ranges, depending on which is shorter.

If no exits are allowed at all then NULL is returned, if no ports are blocked instead of "reject " we return "accept 1-65535" (this is an exception to the shorter-representation-wins rule).

Definition at line 1217 of file policies.c.

{
  smartlist_t *summary = policy_summary_create();
  smartlist_t *accepts, *rejects;
  int i, last, start_prt;
  size_t accepts_len, rejects_len;
  char *accepts_str = NULL, *rejects_str = NULL, *shorter_str, *result;
  const char *prefix;

  tor_assert(policy);

  /* Create the summary list */
  SMARTLIST_FOREACH(policy, addr_policy_t *, p, {
    policy_summary_add_item(summary, p);
  });

  /* Now create two lists of strings, one for accepted and one
   * for rejected ports.  We take care to merge ranges so that
   * we avoid getting stuff like "1-4,5-9,10", instead we want
   * "1-10"
   */
  i = 0;
  start_prt = 1;
  accepts = smartlist_new();
  rejects = smartlist_new();
  while (1) {
    last = i == smartlist_len(summary)-1;
    if (last ||
        AT(i)->accepted != AT(i+1)->accepted) {
      char buf[POLICY_BUF_LEN];

      if (start_prt == AT(i)->prt_max)
        tor_snprintf(buf, sizeof(buf), "%d", start_prt);
      else
        tor_snprintf(buf, sizeof(buf), "%d-%d", start_prt, AT(i)->prt_max);

      if (AT(i)->accepted)
        smartlist_add(accepts, tor_strdup(buf));
      else
        smartlist_add(rejects, tor_strdup(buf));

      if (last)
        break;

      start_prt = AT(i+1)->prt_min;
    };
    i++;
  };

  /* Figure out which of the two stringlists will be shorter and use
   * that to build the result
   */
  if (smartlist_len(accepts) == 0) { /* no exits at all */
    result = tor_strdup("reject 1-65535");
    goto cleanup;
  }
  if (smartlist_len(rejects) == 0) { /* no rejects at all */
    result = tor_strdup("accept 1-65535");
    goto cleanup;
  }

  accepts_str = smartlist_join_strings(accepts, ",", 0, &accepts_len);
  rejects_str = smartlist_join_strings(rejects, ",", 0, &rejects_len);

  if (rejects_len > MAX_EXITPOLICY_SUMMARY_LEN-strlen("reject")-1 &&
      accepts_len > MAX_EXITPOLICY_SUMMARY_LEN-strlen("accept")-1) {
    char *c;
    shorter_str = accepts_str;
    prefix = "accept";

    c = shorter_str + (MAX_EXITPOLICY_SUMMARY_LEN-strlen(prefix)-1);
    while (*c != ',' && c >= shorter_str)
      c--;
    tor_assert(c >= shorter_str);
    tor_assert(*c == ',');
    *c = '\0';

  } else if (rejects_len < accepts_len) {
    shorter_str = rejects_str;
    prefix = "reject";
  } else {
    shorter_str = accepts_str;
    prefix = "accept";
  }

  tor_asprintf(&result, "%s %s", prefix, shorter_str);

 cleanup:
  /* cleanup */
  SMARTLIST_FOREACH(summary, policy_summary_item_t *, s, tor_free(s));
  smartlist_free(summary);

  tor_free(accepts_str);
  SMARTLIST_FOREACH(accepts, char *, s, tor_free(s));
  smartlist_free(accepts);

  tor_free(rejects_str);
  SMARTLIST_FOREACH(rejects, char *, s, tor_free(s));
  smartlist_free(rejects);

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void policy_summary_accept ( smartlist_t summary,
uint16_t  prt_min,
uint16_t  prt_max 
) [static]

Mark port ranges as accepted if they are below the reject_count.

Definition at line 1137 of file policies.c.

{
  int i = policy_summary_split(summary, prt_min, prt_max);
  while (i < smartlist_len(summary) &&
         AT(i)->prt_max <= prt_max) {
    if (!AT(i)->accepted &&
        AT(i)->reject_count <= REJECT_CUTOFF_COUNT)
      AT(i)->accepted = 1;
    i++;
  }
  tor_assert(i < smartlist_len(summary) || prt_max==65535);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void policy_summary_add_item ( smartlist_t summary,
addr_policy_t p 
) [static]

Add a single exit policy item to our summary: If it is an accept ignore it unless it is for all IP addresses ("*"), i.e.

it's prefixlen/maskbits is 0, else call policy_summary_accept(). If it's a reject ignore it if it is about one of the private networks, else call policy_summary_reject().

Definition at line 1177 of file policies.c.

{
  if (p->policy_type == ADDR_POLICY_ACCEPT) {
    if (p->maskbits == 0) {
      policy_summary_accept(summary, p->prt_min, p->prt_max);
    }
  } else if (p->policy_type == ADDR_POLICY_REJECT) {

     int is_private = 0;
     int i;
     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) {
         tor_assert(0);
       }
       if (tor_addr_compare(&p->addr, &addr, CMP_EXACT) == 0 &&
           p->maskbits == maskbits) {
         is_private = 1;
         break;
       }
     }

     if (!is_private) {
       policy_summary_reject(summary, p->maskbits, p->prt_min, p->prt_max);
     }
  } else
    tor_assert(0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static smartlist_t* policy_summary_create ( void  ) [static]

Create a new exit policy summary, initially only with a single port 1-64k item.

Definition at line 1057 of file policies.c.

{
  smartlist_t *summary;
  policy_summary_item_t* item;

  item = tor_malloc_zero(sizeof(policy_summary_item_t));
  item->prt_min = 1;
  item->prt_max = 65535;
  item->reject_count = 0;
  item->accepted = 0;

  summary = smartlist_new();
  smartlist_add(summary, item);

  return summary;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static policy_summary_item_t* policy_summary_item_split ( policy_summary_item_t old,
uint16_t  new_starts 
) [static]

Split the summary item in item at the port new_starts.

The current item is changed to end at new-starts - 1, the new item copies reject_count and accepted from the old item, starts at new_starts and ends at the port where the original item previously ended.

Definition at line 1081 of file policies.c.

{
  policy_summary_item_t* new;

  new = tor_malloc_zero(sizeof(policy_summary_item_t));
  new->prt_min = new_starts;
  new->prt_max = old->prt_max;
  new->reject_count = old->reject_count;
  new->accepted = old->accepted;

  old->prt_max = new_starts-1;

  tor_assert(old->prt_min <= old->prt_max);
  tor_assert(new->prt_min <= new->prt_max);
  return new;
}

Here is the caller graph for this function:

static void policy_summary_reject ( smartlist_t summary,
maskbits_t  maskbits,
uint16_t  prt_min,
uint16_t  prt_max 
) [static]

Count the number of addresses in a network with prefixlen maskbits against the given portrange.

Definition at line 1154 of file policies.c.

{
  int i = policy_summary_split(summary, prt_min, prt_max);
  /* XXX: ipv4 specific */
  uint64_t count = (U64_LITERAL(1) << (32-maskbits));
  while (i < smartlist_len(summary) &&
         AT(i)->prt_max <= prt_max) {
    AT(i)->reject_count += count;
    i++;
  }
  tor_assert(i < smartlist_len(summary) || prt_max==65535);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int policy_summary_split ( smartlist_t summary,
uint16_t  prt_min,
uint16_t  prt_max 
) [static]

Split an exit policy summary so that prt_min and prt_max fall at exactly the start and end of an item respectively.

Definition at line 1107 of file policies.c.

{
  int start_at_index;

  int i = 0;

  while (AT(i)->prt_max < prt_min)
    i++;
  if (AT(i)->prt_min != prt_min) {
    policy_summary_item_t* new_item;
    new_item = policy_summary_item_split(AT(i), prt_min);
    smartlist_insert(summary, i+1, new_item);
    i++;
  }
  start_at_index = i;

  while (AT(i)->prt_max < prt_max)
    i++;
  if (AT(i)->prt_max != prt_max) {
    policy_summary_item_t* new_item;
    new_item = policy_summary_item_split(AT(i), prt_max+1);
    smartlist_insert(summary, i+1, new_item);
  }

  return start_at_index;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int policy_write_item ( char *  buf,
size_t  buflen,
addr_policy_t policy,
int  format_for_desc 
)

Write a single address policy to the buf_len byte buffer at buf.

Return the number of characters written, or -1 on failure.

Definition at line 989 of file policies.c.

{
  size_t written = 0;
  char addrbuf[TOR_ADDR_BUF_LEN];
  const char *addrpart;
  int result;
  const int is_accept = policy->policy_type == ADDR_POLICY_ACCEPT;
  const int is_ip6 = tor_addr_family(&policy->addr) == AF_INET6;

  tor_addr_to_str(addrbuf, &policy->addr, sizeof(addrbuf), 1);

  /* write accept/reject 1.2.3.4 */
  if (policy->is_private)
    addrpart = "private";
  else if (policy->maskbits == 0)
    addrpart = "*";
  else
    addrpart = addrbuf;

  result = tor_snprintf(buf, buflen, "%s%s%s %s",
                        (is_ip6&&format_for_desc)?"opt ":"",
                        is_accept ? "accept" : "reject",
                        (is_ip6&&format_for_desc)?"6":"",
                        addrpart);
  if (result < 0)
    return -1;
  written += strlen(buf);
  /* If the maskbits is 32 we don't need to give it.  If the mask is 0,
   * we already wrote "*". */
  if (policy->maskbits < 32 && policy->maskbits > 0) {
    if (tor_snprintf(buf+written, buflen-written, "/%d", policy->maskbits)<0)
      return -1;
    written += strlen(buf+written);
  }
  if (policy->prt_min <= 1 && policy->prt_max == 65535) {
    /* There is no port set; write ":*" */
    if (written+4 > buflen)
      return -1;
    strlcat(buf+written, ":*", buflen-written);
    written += 2;
  } else if (policy->prt_min == policy->prt_max) {
    /* There is only one port; write ":80". */
    result = tor_snprintf(buf+written, buflen-written, ":%d", policy->prt_min);
    if (result<0)
      return -1;
    written += result;
  } else {
    /* There is a range of ports; write ":79-80". */
    result = tor_snprintf(buf+written, buflen-written, ":%d-%d",
                          policy->prt_min, policy->prt_max);
    if (result<0)
      return -1;
    written += result;
  }
  if (written < buflen)
    buf[written] = '\0';
  else
    return -1;

  return (int)written;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void short_policy_free ( short_policy_t policy)

Release all storage held in policy.

Definition at line 1416 of file policies.c.

{
  tor_free(policy);
}

Here is the caller graph for this function:

Return true iff policy seems reject all ports.

Definition at line 1475 of file policies.c.

{
  /* 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);
}

Here is the caller graph for this function:

Return 1 if addr is permitted to connect to our socks port, based on socks_policy.

Else return 0.

Definition at line 312 of file policies.c.

Here is the call graph for this function:

Here is the caller graph for this function:

int validate_addr_policies ( const or_options_t options,
char **  msg 
)

Config helper: If there's any problem with the policy configuration options in options, return -1 and set msg to a newly allocated description of the error.

Else return 0.

Definition at line 382 of file policies.c.

{
  /* XXXX Maybe merge this into parse_policies_from_options, to make sure
   * that the two can't go out of sync. */

  smartlist_t *addr_policy=NULL;
  *msg = NULL;

  if (policies_parse_exit_policy(options->ExitPolicy, &addr_policy,
                                 options->ExitPolicyRejectPrivate, NULL,
                                 !options->BridgeRelay))
    REJECT("Error in ExitPolicy entry.");

  /* The rest of these calls *append* to addr_policy. So don't actually
   * use the results for anything other than checking if they parse! */
  if (parse_addr_policy(options->DirPolicy, &addr_policy, -1))
    REJECT("Error in DirPolicy entry.");
  if (parse_addr_policy(options->SocksPolicy, &addr_policy, -1))
    REJECT("Error in SocksPolicy entry.");
  if (parse_addr_policy(options->AuthDirReject, &addr_policy,
                        ADDR_POLICY_REJECT))
    REJECT("Error in AuthDirReject entry.");
  if (parse_addr_policy(options->AuthDirInvalid, &addr_policy,
                        ADDR_POLICY_REJECT))
    REJECT("Error in AuthDirInvalid entry.");
  if (parse_addr_policy(options->AuthDirBadDir, &addr_policy,
                        ADDR_POLICY_REJECT))
    REJECT("Error in AuthDirBadDir entry.");
  if (parse_addr_policy(options->AuthDirBadExit, &addr_policy,
                        ADDR_POLICY_REJECT))
    REJECT("Error in AuthDirBadExit entry.");

  if (parse_addr_policy(options->ReachableAddresses, &addr_policy,
                        ADDR_POLICY_ACCEPT))
    REJECT("Error in ReachableAddresses entry.");
  if (parse_addr_policy(options->ReachableORAddresses, &addr_policy,
                        ADDR_POLICY_ACCEPT))
    REJECT("Error in ReachableORAddresses entry.");
  if (parse_addr_policy(options->ReachableDirAddresses, &addr_policy,
                        ADDR_POLICY_ACCEPT))
    REJECT("Error in ReachableDirAddresses entry.");

 err:
  addr_policy_list_free(addr_policy);
  return *msg ? -1 : 0;
#undef REJECT
}

Here is the call graph for this function:


Variable Documentation

Policy that addresses for incoming router descriptors must not match in order to not be marked as BadDirectory.

Definition at line 32 of file policies.c.

Policy that addresses for incoming router descriptors must not match in order to not be marked as BadExit.

Definition at line 35 of file policies.c.

Policy that addresses for incoming router descriptors must match in order to be marked as valid in our networkstatus.

Definition at line 29 of file policies.c.

Policy that addresses for incoming router descriptors must match in order to be published by us.

Definition at line 26 of file policies.c.

smartlist_t* dir_policy = NULL [static]

Policy that addresses for incoming directory connections must match.

Definition at line 23 of file policies.c.

const char* private_nets[] [static]
Initial value:
 {
  "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 }

Private networks.

This list is used in two places, once to expand the "private" keyword when parsing our own exit policy, secondly to ignore just such networks when building exit policy summaries. It is important that all authorities agree on that list when creating summaries, so don't just change this without a proper migration plan and a proposal and stuff.

Definition at line 59 of file policies.c.

Parsed addr_policy_t describing which addresses we believe we can connect to directories at.

Definition at line 42 of file policies.c.

Parsed addr_policy_t describing which addresses we believe we can start circuits at.

Definition at line 39 of file policies.c.

smartlist_t* socks_policy = NULL [static]

Policy that addresses for incoming SOCKS connections must match.

Definition at line 21 of file policies.c.