diff options
-rw-r--r-- | src/or/connection_exit.c | 5 | ||||
-rw-r--r-- | src/or/main.c | 40 | ||||
-rw-r--r-- | src/or/onion.c | 53 | ||||
-rw-r--r-- | src/or/or.h | 2 | ||||
-rw-r--r-- | src/or/routers.c | 41 |
5 files changed, 112 insertions, 29 deletions
diff --git a/src/or/connection_exit.c b/src/or/connection_exit.c index 45f8c6de7..f2fb7b0d2 100644 --- a/src/or/connection_exit.c +++ b/src/or/connection_exit.c @@ -339,6 +339,11 @@ int connection_exit_connect(connection_t *conn) { int s; /* for the new socket */ struct sockaddr_in dest_addr; + if(router_compare_to_exit_policy(conn) < 0) { + log(LOG_INFO,"connection_exit_connect(): %s:%d failed exit policy. Closing.", conn->address, conn->port); + return -1; + } + /* all the necessary info is here. Start the connect() */ s=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP); if (s < 0) { diff --git a/src/or/main.c b/src/or/main.c index 3aaeb5b59..446603627 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -547,12 +547,15 @@ int dump_router_to_string(char *s, int maxlen, routerinfo_t *router) { char *pkey; int pkeylen; int written; + int result=0; + struct exit_policy_t *tmpe; if(crypto_pk_write_public_key_to_string(router->pkey,&pkey,&pkeylen)<0) { log(LOG_ERR,"dump_router_to_string(): write pkey to string failed!"); return 0; } - written = snprintf(s, maxlen, "%s %d %d %d %d %d\n%s\n", + + result = snprintf(s, maxlen, "%s %d %d %d %d %d\n%s", router->address, router->or_port, router->op_port, @@ -563,7 +566,35 @@ int dump_router_to_string(char *s, int maxlen, routerinfo_t *router) { free(pkey); - return written; + if(result < 0 || result > maxlen) { + /* apparently different glibcs do different things on snprintf error.. so check both */ + return -1; + } + written = result; + + for(tmpe=router->exit_policy; tmpe; tmpe=tmpe->next) { + result = snprintf(s+written, maxlen-written, "%s %s:%s\n", + tmpe->policy_type == EXIT_POLICY_ACCEPT ? "accept" : "reject", + tmpe->address, tmpe->port); + if(result < 0 || result+written > maxlen) { + /* apparently different glibcs do different things on snprintf error.. so check both */ + return -1; + } + written += result; + } + + if(written > maxlen-2) { + return -1; /* not enough space for \n\0 */ + } + /* XXX count fenceposts here. They're probably wrong. In general, + * we need a better way to handle overruns in building the directory + * string, and a better way to handle directory string size in general. */ + + /* include a last '\n' */ + s[written] = '\n'; + s[written+1] = 0; + return written+1; + } void dump_directory_to_string(char *s, int maxlen) { @@ -595,13 +626,12 @@ void dump_directory_to_string(char *s, int maxlen) { written = dump_router_to_string(s, maxlen, router); - if(written < 0 || written > maxlen) { - /* apparently different glibcs do different things on error.. so check both */ + if(written < 0) { log(LOG_ERR,"dump_directory_to_string(): tried to exceed string length."); s[maxlen-1] = 0; /* make sure it's null terminated */ return; } - + maxlen -= written; s += written; } diff --git a/src/or/onion.c b/src/or/onion.c index e86553311..6d920052a 100644 --- a/src/or/onion.c +++ b/src/or/onion.c @@ -8,6 +8,7 @@ extern or_options_t options; /* command-line and config-file options */ static int onion_process(circuit_t *circ); static int onion_deliver_to_conn(aci_t aci, unsigned char *onion, uint32_t onionlen, connection_t *conn); +static int count_acceptable_routers(routerinfo_t **rarray, int rarray_len); static int find_tracked_onion(unsigned char *onion, uint32_t onionlen); int decide_aci_type(uint32_t local_addr, uint16_t local_port, @@ -335,7 +336,7 @@ int chooselen(double cw) unsigned int *new_route(double cw, routerinfo_t **rarray, int rarray_len, int *routelen) { int i, j; - int num_acceptable_routers = 0; + int num_acceptable_routers; unsigned int *route = NULL; unsigned int oldchoice, choice; @@ -348,26 +349,8 @@ unsigned int *new_route(double cw, routerinfo_t **rarray, int rarray_len, int *r } log(LOG_DEBUG,"new_route(): Chosen route length %d.",*routelen); - for(i=0;i<rarray_len;i++) { - log(LOG_DEBUG,"Contemplating whether router %d is a new option...",i); - if(options.ORPort && - !connection_exact_get_by_addr_port(rarray[i]->addr, rarray[i]->or_port)) { - log(LOG_DEBUG,"Nope, %d is not connected.",i); - goto next_i_loop; - } - for(j=0;j<i;j++) { - if(!crypto_pk_cmp_keys(rarray[i]->pkey, rarray[j]->pkey)) { - /* these guys are twins. so we've already counted him. */ - log(LOG_DEBUG,"Nope, %d is a twin of %d.",i,j); - goto next_i_loop; - } - } - num_acceptable_routers++; - log(LOG_DEBUG,"I like %d. num_acceptable_routers now %d.",i, num_acceptable_routers); - next_i_loop: - ; /* our compiler may need an explicit statement after the label */ - } - + num_acceptable_routers = count_acceptable_routers(rarray, rarray_len); + if(num_acceptable_routers < *routelen) { log(LOG_DEBUG,"new_route(): Cutting routelen from %d to %d.",*routelen, num_acceptable_routers); *routelen = num_acceptable_routers; @@ -413,6 +396,34 @@ unsigned int *new_route(double cw, routerinfo_t **rarray, int rarray_len, int *r return route; } +static int count_acceptable_routers(routerinfo_t **rarray, int rarray_len) { + int i, j; + int num=0; + + for(i=0;i<rarray_len;i++) { + log(LOG_DEBUG,"Contemplating whether router %d is a new option...",i); + if(options.ORPort && + !connection_exact_get_by_addr_port(rarray[i]->addr, rarray[i]->or_port)) { + log(LOG_DEBUG,"Nope, %d is not connected.",i); + goto next_i_loop; + } + for(j=0;j<i;j++) { + if(!crypto_pk_cmp_keys(rarray[i]->pkey, rarray[j]->pkey)) { + /* these guys are twins. so we've already counted him. */ + log(LOG_DEBUG,"Nope, %d is a twin of %d.",i,j); + goto next_i_loop; + } + } + num++; + log(LOG_DEBUG,"I like %d. num_acceptable_routers now %d.",i, num); + next_i_loop: + ; /* our compiler may need an explicit statement after the label */ + } + + return num; +} + + crypto_cipher_env_t * create_onion_cipher(int cipher_type, char *key, char *iv, int encrypt_mode) { diff --git a/src/or/or.h b/src/or/or.h index 0487d5b93..80105f38b 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -779,6 +779,8 @@ void router_forget_router(uint32_t addr, uint16_t port); int router_get_list_from_file(char *routerfile); int router_get_list_from_string(char *s); +int router_compare_to_exit_policy(connection_t *conn); + #endif /* diff --git a/src/or/routers.c b/src/or/routers.c index b3613a24a..8adda7c9a 100644 --- a/src/or/routers.c +++ b/src/or/routers.c @@ -563,15 +563,18 @@ static void router_add_exit_policy(routerinfo_t *router, char *string) { memset(newe,0,sizeof(struct exit_policy_t)); newe->string = strdup(string); - if(!strncasecmp(string,"reject ",strlen("reject "))) { + n = find_whitespace(string); + *n = 0; + + if(!strcasecmp(string,"reject")) { newe->policy_type = EXIT_POLICY_REJECT; - } else if(!strncasecmp(string,"accept ",strlen("accept "))) { + } else if(!strcasecmp(string,"accept")) { newe->policy_type = EXIT_POLICY_ACCEPT; } else { goto policy_read_failed; } - string = eat_whitespace(string + strlen("reject ")); + string = eat_whitespace(n+1); if(!*string) { goto policy_read_failed; } @@ -615,6 +618,38 @@ policy_read_failed: } +/* Return 0 if my exit policy says to allow connection to conn. + * Else return -1. + */ +int router_compare_to_exit_policy(connection_t *conn) { + struct exit_policy_t *tmpe; + + if(!my_routerinfo) { + log(LOG_WARNING, "router_compare_to_exit_policy(): my_routerinfo undefined! Rejected."); + return -1; + } + + for(tmpe=my_routerinfo->exit_policy; tmpe; tmpe=tmpe->next) { + assert(tmpe->address); + assert(tmpe->port); + + /* Totally ignore the address field of the exit policy, for now. */ + + if(!strcmp(tmpe->port,"*") || atoi(tmpe->port) == conn->port) { + log(LOG_INFO,"router_compare_to_exit_policy(): Port '%s' matches '%d'. %s.", + tmpe->port, conn->port, + tmpe->policy_type == EXIT_POLICY_ACCEPT ? "Accepting" : "Rejecting"); + if(tmpe->policy_type == EXIT_POLICY_ACCEPT) + return 0; + else + return -1; + } + } + + return 0; /* accept all by default. */ + +} + /* Local Variables: mode:c |