summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2004-05-20 02:42:50 +0000
committerNick Mathewson <nickm@torproject.org>2004-05-20 02:42:50 +0000
commit80365b989749efbeca6202156197321706462e4d (patch)
tree1c221f99fd895bf540df162f8d7d2f2fa0950de9
parent80be19d9da9e02deac29c7fb685559446d881b0b (diff)
downloadtor-80365b989749efbeca6202156197321706462e4d.tar.gz
tor-80365b989749efbeca6202156197321706462e4d.zip
Allow multiple exit policy lines; mostly add support for AP policies
svn:r1905
-rw-r--r--doc/TODO4
-rw-r--r--src/or/config.c76
-rw-r--r--src/or/connection.c74
-rw-r--r--src/or/connection_edge.c36
-rw-r--r--src/or/or.h21
-rw-r--r--src/or/router.c57
-rw-r--r--src/or/routerlist.c9
-rw-r--r--src/or/routerparse.c63
8 files changed, 215 insertions, 125 deletions
diff --git a/doc/TODO b/doc/TODO
index cc6ed1d353..f8223da8c3 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -16,9 +16,9 @@ For 0.0.7:
o the keep-trying-to-build-intropoints-always bug.
- *bindaddress
o include the port
- - allow multiple of them
+ o allow multiple of them
- have an allow/deny series for them
- - break exitpolicy into multiple config lines
+ o break exitpolicy into multiple config lines
- have the OP forget routers it hasn't heard about in 24 hours
- rename/rearrange functions for what file they're in
- try to break apart the main clump of functions better.
diff --git a/src/or/config.c b/src/or/config.c
index 7658550ce2..046a716ffd 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -195,7 +195,7 @@ static int config_assign(or_options_t *options, struct config_line_t *list) {
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 @@ static int config_assign(or_options_t *options, struct config_line_t *list) {
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 @@ static int config_assign(or_options_t *options, struct config_line_t *list) {
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 @@ static void free_options(or_options_t *options) {
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 @@ static void init_options(or_options_t *options) {
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_init_logs(or_options_t *options)
}
}
+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
diff --git a/src/or/connection.c b/src/or/connection.c
index 64b0632d0e..49576eba33 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -74,6 +74,8 @@ char *conn_state_to_string[][_CONN_TYPE_MAX+1] = {
/********* 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 @@ void connection_expire_held_open(void)
* 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,54 +490,64 @@ int connection_connect(connection_t *conn, char *address, uint32_t addr, uint16_
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.
* - Connect to all ORs if you're an OR.
* - 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;
}
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index c20b0cc2ec..8de0d6d9ba 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -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 @@ int connection_ap_can_use_exit(connection_t *conn, routerinfo_t *exit)
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. */
diff --git a/src/or/or.h b/src/or/or.h
index 3422f8adbb..db1f58173f 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -777,13 +777,14 @@ typedef struct {
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 @@ struct config_line_t {
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 @@ int _connection_mark_for_close(connection_t *conn);
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 @@ int router_parse_routerlist_from_directory(const char *s,
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
diff --git a/src/or/router.c b/src/or/router.c
index a7957864f8..aa9134b33b 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -324,41 +324,6 @@ void router_upload_dir_desc_to_dirservers(void) {
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 @@ static void router_add_exit_policy_from_config_helper(const char *s, routerinfo_
* 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
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index 7c0fbaf337..17ba4a1fcc 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -232,8 +232,6 @@ void router_get_routerlist(routerlist_t **prouterlist) {
/** 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 @@ void routerinfo_free(routerinfo_t *router)
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);
}
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index ef6c601ec4..6b227fcddf 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -115,6 +115,7 @@ static struct {
/* 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 @@ routerinfo_t *router_parse_entry_from_string(const char *s,
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 @@ router_add_exit_policy_from_string(routerinfo_t *router, const char *s)
}
/* 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 @@ router_add_exit_policy(routerinfo_t *router, directory_token_t *tok) {
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 @@ router_add_exit_policy(routerinfo_t *router, directory_token_t *tok) {
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;
}
/*