Skip to content
Snippets Groups Projects
Commit cdf6ea20 authored by Roger Dingledine's avatar Roger Dingledine
Browse files

put most of the remaining exit policy stuff in

route selection still doesn't pay attention to exit policies though


svn:r227
parent 79b77b42
No related branches found
No related tags found
No related merge requests found
......@@ -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) {
......
......@@ -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;
}
......
......@@ -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)
{
......
......@@ -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
/*
......
......@@ -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
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment