[or-cvs] Allow multiple exit policy lines; mostly add support for AP...

Nick Mathewson nickm at seul.org
Thu May 20 02:42:53 UTC 2004


Update of /home/or/cvsroot/src/or
In directory moria.mit.edu:/tmp/cvs-serv28361/src/or

Modified Files:
	config.c connection.c connection_edge.c or.h router.c 
	routerlist.c routerparse.c 
Log Message:
Allow multiple exit policy lines; mostly add support for AP policies

Index: config.c
===================================================================
RCS file: /home/or/cvsroot/src/or/config.c,v
retrieving revision 1.115
retrieving revision 1.116
diff -u -d -r1.115 -r1.116
--- config.c	19 May 2004 21:40:44 -0000	1.115
+++ config.c	20 May 2004 02:42:49 -0000	1.116
@@ -195,7 +195,7 @@
     config_compare(list, "DebugLogFile",   CONFIG_TYPE_STRING, &options->DebugLogFile) ||
     config_compare(list, "DataDirectory",  CONFIG_TYPE_STRING, &options->DataDirectory) ||
     config_compare(list, "DirPort",        CONFIG_TYPE_INT, &options->DirPort) ||
-    config_compare(list, "DirBindAddress", CONFIG_TYPE_STRING, &options->DirBindAddress) ||
+    config_compare(list, "DirBindAddress", CONFIG_TYPE_LINELIST, &options->DirBindAddress) ||
     config_compare(list, "DirFetchPostPeriod",CONFIG_TYPE_INT, &options->DirFetchPostPeriod) ||
 
     config_compare(list, "ExitNodes",      CONFIG_TYPE_STRING, &options->ExitNodes) ||
@@ -221,7 +221,7 @@
     config_compare(list, "NumCpus",        CONFIG_TYPE_INT, &options->NumCpus) ||
 
     config_compare(list, "ORPort",         CONFIG_TYPE_INT, &options->ORPort) ||
-    config_compare(list, "ORBindAddress",  CONFIG_TYPE_STRING, &options->ORBindAddress) ||
+    config_compare(list, "ORBindAddress",  CONFIG_TYPE_LINELIST, &options->ORBindAddress) ||
 
     config_compare(list, "PidFile",        CONFIG_TYPE_STRING, &options->PidFile) ||
     config_compare(list, "PathlenCoinWeight",CONFIG_TYPE_DOUBLE, &options->PathlenCoinWeight) ||
@@ -233,7 +233,8 @@
     config_compare(list, "RendExcludeNodes",CONFIG_TYPE_STRING, &options->RendExcludeNodes) ||
 
     config_compare(list, "SocksPort",      CONFIG_TYPE_INT, &options->SocksPort) ||
-    config_compare(list, "SocksBindAddress",CONFIG_TYPE_STRING,&options->SocksBindAddress) ||
+    config_compare(list, "SocksBindAddress",CONFIG_TYPE_LINELIST,&options->SocksBindAddress) ||
+    config_compare(list, "SocksPolicy",     CONFIG_TYPE_LINELIST,&options->SocksPolicy) ||
 
     config_compare(list, "TrafficShaping", CONFIG_TYPE_BOOL, &options->TrafficShaping) ||
 
@@ -477,14 +478,15 @@
   tor_free(options->ExcludeNodes);
   tor_free(options->RendNodes);
   tor_free(options->RendExcludeNodes);
-  tor_free(options->ExitPolicy);
-  tor_free(options->SocksBindAddress);
-  tor_free(options->ORBindAddress);
-  tor_free(options->DirBindAddress);
   tor_free(options->RecommendedVersions);
   tor_free(options->User);
   tor_free(options->Group);
   config_free_lines(options->RendConfigLines);
+  config_free_lines(options->SocksBindAddress);
+  config_free_lines(options->ORBindAddress);
+  config_free_lines(options->DirBindAddress);
+  config_free_lines(options->ExitPolicy);
+  config_free_lines(options->SocksPolicy);
 }
 
 /** Set <b>options</b> to hold reasonable defaults for most options. */
@@ -497,10 +499,11 @@
   options->ExcludeNodes = tor_strdup("");
   options->RendNodes = tor_strdup("");
   options->RendExcludeNodes = tor_strdup("");
-  options->ExitPolicy = tor_strdup("");
-  options->SocksBindAddress = tor_strdup("127.0.0.1");
-  options->ORBindAddress = tor_strdup("0.0.0.0");
-  options->DirBindAddress = tor_strdup("0.0.0.0");
+  options->ExitPolicy = NULL;
+  options->SocksPolicy = NULL;
+  options->SocksBindAddress = NULL;
+  options->ORBindAddress = NULL;
+  options->DirBindAddress = NULL;
   options->RecommendedVersions = NULL;
   options->PidFile = NULL; // tor_strdup("tor.pid");
   options->DataDirectory = NULL;
@@ -808,6 +811,57 @@
   }
 }
 
+void
+config_parse_exit_policy(struct config_line_t *cfg,
+                         struct exit_policy_t **dest)
+{
+  struct exit_policy_t **nextp;
+  char *e, *s;
+  int last=0;
+  char line[1024];
+
+  if (!cfg)
+    return;
+  nextp = dest;
+  while (*nextp)
+    nextp = &((*nextp)->next);
+
+  for (; cfg; cfg = cfg->next) {
+    s = cfg->value;
+    for (;;) {
+      e = strchr(s,',');
+      if(!e) {
+        last = 1;
+        strncpy(line,s,1023);
+      } else {
+        memcpy(line,s, ((e-s)<1023)?(e-s):1023);
+      line[e-s] = 0;
+      }
+      line[1023]=0;
+      log_fn(LOG_DEBUG,"Adding new entry '%s'",line);
+      *nextp = router_parse_exit_policy_from_string(line);
+      if(*nextp) {
+        nextp = &((*nextp)->next);
+      } else {
+        log_fn(LOG_WARN,"Malformed exit policy %s; skipping.", line);
+      }
+      if (last)
+        break;
+      s = e+1;
+    }
+  }
+}
+
+void exit_policy_free(struct exit_policy_t *p) {
+  struct exit_policy_t *e;
+  while (p) {
+    e = p;
+    p = p->next;
+    tor_free(e->string);
+    tor_free(e);
+  }
+}
+
 /*
   Local Variables:
   mode:c

Index: connection.c
===================================================================
RCS file: /home/or/cvsroot/src/or/connection.c,v
retrieving revision 1.226
retrieving revision 1.227
diff -u -d -r1.226 -r1.227
--- connection.c	19 May 2004 23:32:20 -0000	1.226
+++ connection.c	20 May 2004 02:42:49 -0000	1.227
@@ -74,6 +74,8 @@
 
 /********* END VARIABLES ************/
 
+static int connection_create_listener(const char *bindaddress,
+                                      uint16_t bindport, int type);
 static int connection_init_accepted_conn(connection_t *conn);
 static int connection_handle_listener_read(connection_t *conn, int new_type);
 static int connection_receiver_bucket_should_increase(connection_t *conn);
@@ -307,7 +309,7 @@
  * If <b>bindaddress</b> includes a port, we bind on that port; otherwise, we
  * use bindport.
  */
-int connection_create_listener(char *bindaddress, uint16_t bindport, int type) {
+static int connection_create_listener(const char *bindaddress, uint16_t bindport, int type) {
   struct sockaddr_in bindaddr; /* where to bind */
   connection_t *conn;
   char *hostname, *cp;
@@ -488,19 +490,44 @@
   return 1;
 }
 
-/** If there exists a listener of type <b>type</b> in the connection
- * array, mark it for close.
+/** If there exist any listeners of type <b>type</b> in the connection
+ * array, mark them for close.
  */
 static void listener_close_if_present(int type) {
   connection_t *conn;
+  connection_t **carray;
+  int i,n;
   tor_assert(type == CONN_TYPE_OR_LISTENER ||
              type == CONN_TYPE_AP_LISTENER ||
              type == CONN_TYPE_DIR_LISTENER);
-  conn = connection_get_by_type(type);
-  if (conn) {
-    connection_close_immediate(conn);
-    connection_mark_for_close(conn);
+  get_connection_array(&carray,&n);
+  for(i=0;i<n;i++) {
+    conn = carray[i];
+    if (conn->type == type && !conn->marked_for_close) {
+      connection_close_immediate(conn);
+      connection_mark_for_close(conn);
+    }
+  }
+}
+
+static int retry_listeners(int type, struct config_line_t *cfg,
+                           int port_option, const char *default_addr)
+{
+  listener_close_if_present(type);
+  if (port_option) {
+    if (!cfg) {
+      if (connection_create_listener(default_addr, (uint16_t) port_option,
+                                     type)<0)
+        return -1;
+    } else {
+      for ( ; cfg; cfg = cfg->next) {
+        if (connection_create_listener(cfg->value, (uint16_t) port_option,
+                                       type)<0)
+          return -1;
+      }
+    }
   }
+  return 0;
 }
 
 /** Start all connections that should be up but aren't.
@@ -508,34 +535,19 @@
  *  - Relaunch listeners for each port you have open.
  */
 int retry_all_connections(void) {
-
   if(options.ORPort) {
     router_retry_connections();
   }
 
-  if(options.ORPort) {
-    listener_close_if_present(CONN_TYPE_OR_LISTENER);
-    if(connection_create_listener(options.ORBindAddress,
-                                  (uint16_t) options.ORPort,
-                                  CONN_TYPE_OR_LISTENER) < 0)
-      return -1;
-  }
-
-  if(options.DirPort) {
-    listener_close_if_present(CONN_TYPE_DIR_LISTENER);
-    if(connection_create_listener(options.DirBindAddress,
-                                  (uint16_t) options.DirPort,
-                                  CONN_TYPE_DIR_LISTENER) < 0)
-      return -1;
-  }
-
-  if(options.SocksPort) {
-    listener_close_if_present(CONN_TYPE_AP_LISTENER);
-    if(connection_create_listener(options.SocksBindAddress,
-                                  (uint16_t) options.SocksPort,
-                                  CONN_TYPE_AP_LISTENER) < 0)
-      return -1;
-  }
+  if (retry_listeners(CONN_TYPE_OR_LISTENER, options.ORBindAddress,
+                      options.ORPort, "0.0.0.0")<0)
+    return -1;
+  if (retry_listeners(CONN_TYPE_DIR_LISTENER, options.DirBindAddress,
+                      options.DirPort, "0.0.0.0")<0)
+    return -1;
+  if (retry_listeners(CONN_TYPE_AP_LISTENER, options.SocksBindAddress,
+                      options.SocksPort, "127.0.0.1")<0)
+    return -1;
 
   return 0;
 }

Index: connection_edge.c
===================================================================
RCS file: /home/or/cvsroot/src/or/connection_edge.c,v
retrieving revision 1.189
retrieving revision 1.190
diff -u -d -r1.189 -r1.190
--- connection_edge.c	13 May 2004 07:24:49 -0000	1.189
+++ connection_edge.c	20 May 2004 02:42:49 -0000	1.190
@@ -13,7 +13,11 @@
 extern or_options_t options; /* command-line and config-file options */
 extern char *conn_state_to_string[][_CONN_TYPE_MAX+1]; /* from connection.c */
 
+static struct exit_policy_t *socks_policy = NULL;
+
 static int connection_ap_handshake_process_socks(connection_t *conn);
+static void parse_socks_policy(void);
+static int socks_policy_permits_address(uint32_t addr);
 
 /** Handle new bytes on conn->inbuf, or notification of eof.
  *
@@ -781,6 +785,38 @@
            conn->socks_request->port, exit->exit_policy);
 }
 
+static void parse_socks_policy(void)
+{
+  struct exit_policy_t *n;
+  if (socks_policy) {
+    exit_policy_free(socks_policy);
+    socks_policy = NULL;
+  }
+  config_parse_exit_policy(options.SocksPolicy, &socks_policy);
+  /* ports aren't used. */
+  for (n=socks_policy; n; n = n->next) {
+    n->prt_min = 1;
+    n->prt_max = 65535;
+  }
+}
+
+int socks_policy_permits_address(uint32_t addr)
+{
+  int a;
+  if (options.SocksPolicy && !socks_policy)
+    parse_socks_policy();
+
+  a = router_compare_addr_to_exit_policy(addr, 1, socks_policy);
+  if (a==-1)
+    return 0;
+  else if (a==0)
+    return 1;
+  else if (a==1) {
+    log_fn(LOG_WARN, "Got unexpected 'maybe' answer from socks policy");
+    return 1;
+  }
+}
+
 /* ***** Client DNS code ***** */
 
 /* XXX Perhaps this should get merged with the dns.c code somehow. */

Index: or.h
===================================================================
RCS file: /home/or/cvsroot/src/or/or.h,v
retrieving revision 1.351
retrieving revision 1.352
diff -u -d -r1.351 -r1.352
--- or.h	19 May 2004 20:07:08 -0000	1.351
+++ or.h	20 May 2004 02:42:49 -0000	1.352
@@ -777,13 +777,14 @@
   char *RendExcludeNodes; /**< Comma-separated list of nicknames not to use
                            * as introduction points. */
 
-  char *ExitPolicy; /**< Comma-separated list of exit policy components. */
-  char *SocksBindAddress; /**< Address to bind for listening for SOCKS
-                           * connections. */
-  char *ORBindAddress; /**< Address to bind for listening for OR
-                        * connections. */
-  char *DirBindAddress; /**< Address to bind for listening for directory
-                         * connections. */
+  struct config_line_t *ExitPolicy; /**< Lists of exit policy components. */
+  struct config_line_t *SocksPolicy; /**< Lists of socks policy components */
+  struct config_line_t *SocksBindAddress;
+  /**< Addresses to bind for listening for SOCKS connections. */
+  struct config_line_t *ORBindAddress;
+  /**< Addresses to bind for listening for OR connections. */
+  struct config_line_t *DirBindAddress;
+  /**< Addresses to bind for listening for directory connections. */
   char *RecommendedVersions; /**< Directory server only: which versions of
                               * Tor should we tell users to run? */
   char *User; /**< Name of user to run Tor as. */
@@ -953,6 +954,9 @@
 int config_assign_default_dirservers(void);
 int getconfig(int argc, char **argv, or_options_t *options);
 void config_init_logs(or_options_t *options);
+void config_parse_exit_policy(struct config_line_t *cfg,
+                              struct exit_policy_t **dest);
+void exit_policy_free(struct exit_policy_t *p);
 
 /********************************* connection.c ***************************/
 
@@ -982,8 +986,6 @@
 
 void connection_expire_held_open(void);
 
-int connection_create_listener(char *bindaddress, uint16_t bindport, int type);
-
 int connection_connect(connection_t *conn, char *address, uint32_t addr, uint16_t port);
 int retry_all_connections(void);
 
@@ -1318,6 +1320,7 @@
                                            crypto_pk_env_t *pkey);
 routerinfo_t *router_parse_entry_from_string(const char *s, const char *end);
 int router_add_exit_policy_from_string(routerinfo_t *router, const char *s);
+struct exit_policy_t *router_parse_exit_policy_from_string(const char *s);
 
 #endif
 

Index: router.c
===================================================================
RCS file: /home/or/cvsroot/src/or/router.c,v
retrieving revision 1.43
retrieving revision 1.44
diff -u -d -r1.43 -r1.44
--- router.c	12 May 2004 23:48:57 -0000	1.43
+++ router.c	20 May 2004 02:42:50 -0000	1.44
@@ -324,41 +324,6 @@
   directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_DIR, s, strlen(s));
 }
 
-/** Append the comma-separated sequence of exit policies in <b>s</b> to the
- * exit policy in <b>router</b>. */
-static void router_add_exit_policy_from_config_helper(const char *s, routerinfo_t *router) {
-  char *e;
-  int last=0;
-  char line[1024];
-
-  if(!s) {
-    log_fn(LOG_INFO,"No exit policy configured. Ok.");
-    return; /* nothing to see here */
-  }
-  if(!*s) {
-    log_fn(LOG_INFO,"Exit policy is empty. Ok.");
-    return; /* nothing to see here */
-  }
-
-  for(;;) {
-    e = strchr(s,',');
-    if(!e) {
-      last = 1;
-      strncpy(line,s,1023);
-    } else {
-      memcpy(line,s, ((e-s)<1023)?(e-s):1023);
-      line[e-s] = 0;
-    }
-    line[1023]=0;
-    log_fn(LOG_DEBUG,"Adding new entry '%s'",line);
-    if(router_add_exit_policy_from_string(router,line) < 0)
-      log_fn(LOG_WARN,"Malformed exit policy %s; skipping.", line);
-    if(last)
-      return;
-    s = e+1;
-  }
-}
-
 #define DEFAULT_EXIT_POLICY "reject 0.0.0.0/8,reject 169.254.0.0/16,reject 127.0.0.0/8,reject 192.168.0.0/16,reject 10.0.0.0/8,reject 172.16.0.0/12,accept *:20-22,accept *:53,accept *:79-81,accept *:110,accept *:143,accept *:443,accept *:873,accept *:993,accept *:995,accept *:1024-65535,reject *:*"
 
 /** Set the exit policy on <b>router</b> to match the exit policy in the
@@ -366,14 +331,22 @@
  * rule, then append the default exit policy as well.
  */
 static void router_add_exit_policy_from_config(routerinfo_t *router) {
-  router_add_exit_policy_from_config_helper(options.ExitPolicy, router);
-  /* XXXX This is wrong; you can spell *:* many ways. -NM
-   * So? If they spell it sneakily, then their exit policy is bulkier. -RD */
-  if(strstr(options.ExitPolicy," *:*") == NULL) {
-    /* if exitpolicy includes a *:* line, then we're done. Else, append
-     * the default exitpolicy. */
-    router_add_exit_policy_from_config_helper(DEFAULT_EXIT_POLICY, router);
+  struct exit_policy_t *ep;
+  struct config_line_t default_policy;
+  config_parse_exit_policy(options.ExitPolicy, &router->exit_policy);
+
+  for (ep = router->exit_policy; ep; ep = ep->next) {
+    if (ep->msk == 0 && ep->prt_min <= 1 && ep->prt_max >= 65535) {
+      /* if exitpolicy includes a *:* line, then we're done. */
+      return;
+    }
   }
+
+  /* Else, append the default exitpolicy. */
+  default_policy.key = NULL;
+  default_policy.value = DEFAULT_EXIT_POLICY;
+  default_policy.next = NULL;
+  config_parse_exit_policy(&default_policy, &router->exit_policy);
 }
 
 /** OR only: Return false if my exit policy says to allow connection to

Index: routerlist.c
===================================================================
RCS file: /home/or/cvsroot/src/or/routerlist.c,v
retrieving revision 1.78
retrieving revision 1.79
diff -u -d -r1.78 -r1.79
--- routerlist.c	18 May 2004 16:54:04 -0000	1.78
+++ routerlist.c	20 May 2004 02:42:50 -0000	1.79
@@ -232,8 +232,6 @@
 /** Free all storage held by <b>router</b>. */
 void routerinfo_free(routerinfo_t *router)
 {
-  struct exit_policy_t *e;
-
   if (!router)
     return;
 
@@ -244,12 +242,7 @@
     crypto_free_pk_env(router->onion_pkey);
   if (router->identity_pkey)
     crypto_free_pk_env(router->identity_pkey);
-  while (router->exit_policy) {
-    e = router->exit_policy;
-    router->exit_policy = e->next;
-    tor_free(e->string);
-    free(e);
-  }
+  exit_policy_free(router->exit_policy);
   free(router);
 }
 

Index: routerparse.c
===================================================================
RCS file: /home/or/cvsroot/src/or/routerparse.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- routerparse.c	18 May 2004 15:35:21 -0000	1.2
+++ routerparse.c	20 May 2004 02:42:50 -0000	1.3
@@ -115,6 +115,7 @@
 
 /* static function prototypes */
 static int router_add_exit_policy(routerinfo_t *router,directory_token_t *tok);
+static struct exit_policy_t *router_parse_exit_policy(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);
@@ -590,15 +591,15 @@
   return router;
 }
 
-/** Parse the exit policy in the string <b>s</b> and add it to <b>router</b>.
+/** Parse the exit policy in the string <b>s</b> and return it.
  */
-int
-router_add_exit_policy_from_string(routerinfo_t *router, const char *s)
+struct exit_policy_t *
+router_parse_exit_policy_from_string(const char *s)
 {
   directory_token_t *tok = NULL;
   const char *cp;
   char *tmp;
-  int r;
+  struct exit_policy_t *r;
   int len, idx;
 
   /* *s might not end with \n, so we need to extend it with one. */
@@ -620,22 +621,49 @@
   }
 
   /* Now that we've gotten an exit policy, add it to the router. */
-  r = router_add_exit_policy(router, tok);
+  r = router_parse_exit_policy(tok);
   goto done;
  err:
-  r = -1;
+  r = NULL;
  done:
   free(tmp);
   token_free(tok);
   return r;
 }
 
+int router_add_exit_policy_from_string(routerinfo_t *router, const char *s)
+{
+  struct exit_policy_t *newe, *tmpe;
+  newe = router_parse_exit_policy_from_string(s);
+  if (!newe)
+    return -1;
+  for (tmpe = router->exit_policy; tmpe; tmpe=tmpe->next)
+    ;
+  tmpe->next = newe;
+
+  return 0;
+}
+
+
+static int router_add_exit_policy(routerinfo_t *router,directory_token_t *tok)
+{
+  struct exit_policy_t *newe, **tmpe;
+  newe = router_parse_exit_policy(tok);
+  if (!newe)
+    return -1;
+  for (tmpe = &router->exit_policy; *tmpe; tmpe=&((*tmpe)->next))
+    ;
+  *tmpe = newe;
+
+  return 0;
+}
+
 /** Given a K_ACCEPT or K_REJECT token and a router, create a new exit_policy_t
  * corresponding to the token, and add it to <b>router</b> */
-static int
-router_add_exit_policy(routerinfo_t *router, directory_token_t *tok) {
+static struct exit_policy_t *
+router_parse_exit_policy(directory_token_t *tok) {
 
-  struct exit_policy_t *tmpe, *newe;
+  struct exit_policy_t*newe;
   struct in_addr in;
   char *arg, *address, *mask, *port, *endptr;
   int bits;
@@ -643,7 +671,7 @@
   tor_assert(tok->tp == K_REJECT || tok->tp == K_ACCEPT);
 
   if (tok->n_args != 1)
-    return -1;
+    return NULL;
   arg = tok->args[0];
 
   newe = tor_malloc_zero(sizeof(struct exit_policy_t));
@@ -728,24 +756,15 @@
          address, inet_ntoa(in), newe->prt_min, newe->prt_max);
   tor_free(address);
 
-  /* now link newe onto the end of exit_policy */
-
-  if(!router->exit_policy) {
-    router->exit_policy = newe;
-    return 0;
-  }
-
-  for(tmpe=router->exit_policy; tmpe->next; tmpe=tmpe->next) ;
-  tmpe->next = newe;
-
-  return 0;
+  newe->next = NULL;
+  return newe;
 
 policy_read_failed:
   tor_assert(newe->string);
   log_fn(LOG_WARN,"Couldn't parse line '%s'. Dropping", newe->string);
   tor_free(newe->string);
   free(newe);
-  return -1;
+  return NULL;
 }
 
 /*



More information about the tor-commits mailing list