diff --git a/src/common/test.h b/src/common/test.h index 3a1215fe04..e80a964fca 100644 --- a/src/common/test.h +++ b/src/common/test.h @@ -63,7 +63,7 @@ char *v1=(expr1), *v2=(expr2); \ if(!strcmp(v1,v2)) { printf("."); } else { \ printf("\nFile %s: line %d (%s): Assertion failed: (%s==%s)\n"\ - " (%s != %s)\n", \ + " (\"%s\" != \"%s\")\n", \ __FILE__, \ __LINE__, \ __PRETTY_FUNCTION__, \ @@ -77,7 +77,7 @@ char *v1=(expr1), *v2=(expr2); \ if(strcmp(v1,v2)) { printf("."); } else { \ printf("\nFile %s: line %d (%s): Assertion failed: (%s!=%s)\n"\ - " (%s == %s)\n", \ + " (\"%s\" == \"%s\")\n", \ __FILE__, \ __LINE__, \ __PRETTY_FUNCTION__, \ diff --git a/src/config/dirservers b/src/config/dirservers index 72392507c6..f8224cd6ed 100644 --- a/src/config/dirservers +++ b/src/config/dirservers @@ -7,7 +7,7 @@ # DirPort is where the router listens for directory download requests # Router 1 -moria.mit.edu 9001 9011 9021 9031 1000000 +router moria.mit.edu 9001 9011 9021 9031 1000000 -----BEGIN RSA PUBLIC KEY----- MIGJAoGBAMBBuk1sYxEg5jLAJy86U3GGJ7EGMSV7yoA6mmcsEVU3pwTUrpbpCmwS 7BvovoY3z4zk63NZVBErgKQUDkn3pp8n83xZgEf4GI27gdWIIwaBjEimuJlEY+7K @@ -15,7 +15,7 @@ nZ7kVMRoiXCbjL6VAtNa4Zy1Af/GOm0iCIDpholeujQ95xew7rQnAgMA//8= -----END RSA PUBLIC KEY----- # Router 2 -moria.mit.edu 9002 9012 9022 9032 1000000 +router moria.mit.edu 9002 9012 9022 9032 1000000 -----BEGIN RSA PUBLIC KEY----- MIGJAoGBANX/HHRuudz274MFSQ4manX8DhtsIuogNUyco9/0dr+XsfioTGd3RgMj aSWlD87arkZO4hHBPHe0q89Z3s1UtUsyQ/VmsxSv9g2OCnF/dU2Nz4h6+Al3iNJF @@ -23,7 +23,7 @@ aSWlD87arkZO4hHBPHe0q89Z3s1UtUsyQ/VmsxSv9g2OCnF/dU2Nz4h6+Al3iNJF -----END RSA PUBLIC KEY----- # Router 3 -moria.mit.edu 9003 9013 9023 9033 1000000 +router moria.mit.edu 9003 9013 9023 9033 1000000 -----BEGIN RSA PUBLIC KEY----- MIGJAoGBAJfkNWCaNkYIRwfHT06KBU6dz8W1xDpW5ezGJwAOoxCX3/ZNoUicb/1V oB3OzW6VxWIiht3da/3K0ywiBOOCcf6BabKoMdiPpH7NIeu6XRmBYK2uqW13gBgh diff --git a/src/config/routers.or b/src/config/routers.or index 5908ded0e4..e28deed98c 100644 --- a/src/config/routers.or +++ b/src/config/routers.or @@ -7,7 +7,7 @@ # DirPort is where the router listens for directory download requests # Router 1 -moria.mit.edu 9001 9011 9021 9031 1000000 +router moria.mit.edu 9001 9011 9021 9031 1000000 -----BEGIN RSA PUBLIC KEY----- MIGJAoGBAMBBuk1sYxEg5jLAJy86U3GGJ7EGMSV7yoA6mmcsEVU3pwTUrpbpCmwS 7BvovoY3z4zk63NZVBErgKQUDkn3pp8n83xZgEf4GI27gdWIIwaBjEimuJlEY+7K @@ -15,7 +15,7 @@ nZ7kVMRoiXCbjL6VAtNa4Zy1Af/GOm0iCIDpholeujQ95xew7rQnAgMA//8= -----END RSA PUBLIC KEY----- # Router 2 -moria.mit.edu 9002 9012 9022 9032 1000000 +router moria.mit.edu 9002 9012 9022 9032 1000000 -----BEGIN RSA PUBLIC KEY----- MIGJAoGBANX/HHRuudz274MFSQ4manX8DhtsIuogNUyco9/0dr+XsfioTGd3RgMj aSWlD87arkZO4hHBPHe0q89Z3s1UtUsyQ/VmsxSv9g2OCnF/dU2Nz4h6+Al3iNJF @@ -23,28 +23,28 @@ aSWlD87arkZO4hHBPHe0q89Z3s1UtUsyQ/VmsxSv9g2OCnF/dU2Nz4h6+Al3iNJF -----END RSA PUBLIC KEY----- # Router 3 -moria.mit.edu 9003 9013 9023 9033 1000000 +router moria.mit.edu 9003 9013 9023 9033 1000000 -----BEGIN RSA PUBLIC KEY----- MIGJAoGBAJfkNWCaNkYIRwfHT06KBU6dz8W1xDpW5ezGJwAOoxCX3/ZNoUicb/1V oB3OzW6VxWIiht3da/3K0ywiBOOCcf6BabKoMdiPpH7NIeu6XRmBYK2uqW13gBgh xJbQBb58Nx8Fr05XkvLG6i+vTDY3MZOW3E2/DwSe/jFzuHSD5b3nAgMA//8= -----END RSA PUBLIC KEY----- -moria.mit.edu 9004 9014 9024 0 1000000 +router moria.mit.edu 9004 9014 9024 0 1000000 -----BEGIN RSA PUBLIC KEY----- MIGJAoGBAKD2BDZQpGq/aAbZ7t+/7qktZVEbhUGe097gIjWH9gXcIOIm0CJMe3rN MsBJsQMi5Uwqrz+Invb5n6bswrNlJp/bCKBhGTvUCfxg7c8xZy71PPSIPnTg1qXl p5fyAkgCYkZNgEEZzQDHv1GRvLCs92kURjSJE5y8QU0dXfbzms8PAgMA//8= -----END RSA PUBLIC KEY----- -mosg.cl.cam.ac.uk 9005 9015 9025 0 1000000 +router mosg.cl.cam.ac.uk 9005 9015 9025 0 1000000 -----BEGIN RSA PUBLIC KEY----- MIGJAoGBAMMHEjhhawM6S14ETFVcvByU7D/baN2JMcCweKKJ7zcSurDnpgRH/Uo7 05+bZE3BCy4OkAqQbGlKd/ejBOuXjEtS0mJo5xwDX9StKguhgFRk60hhrF2OFJm4 VLItXA6U2NLOrc+FBCv/9laLpBrxOb8Wuct0l/lyZ2/OfE9yYhC3AgMA//8= -----END RSA PUBLIC KEY----- -66.17.17.207 9006 9016 9026 0 1000000 +router 66.17.17.207 9006 9016 9026 0 1000000 -----BEGIN RSA PUBLIC KEY----- MIGJAoGBAL5cpmH34kVfmHd+A00vMton3pLGHAVf7BYkSMif8e/O5zXTUXRi4w78 jDcGNo2yFM3htTpT5/tWs/Z2+B/mx8Kz+AhHzZ9z0PdQreDSqxXjF+jmfCyx9Teq diff --git a/src/or/main.c b/src/or/main.c index 4201c9d297..234030e1ef 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -565,7 +565,7 @@ int dump_router_to_string(char *s, int maxlen, routerinfo_t *router) { return 0; } - result = snprintf(s, maxlen, "%s %d %d %d %d %d\n%s", + result = snprintf(s, maxlen, "router %s %d %d %d %d %d\n%s", router->address, router->or_port, router->op_port, diff --git a/src/or/onion.c b/src/or/onion.c index 915532468d..db9acf5d02 100644 --- a/src/or/onion.c +++ b/src/or/onion.c @@ -347,6 +347,7 @@ crypt_path_t *onion_generate_cpath(routerinfo_t **firsthop) { int routelen; /* length of the route */ unsigned int *route; /* hops in the route as an array of indexes into rarray */ crypt_path_t *cpath=NULL; + directory_t *dir; routerinfo_t **rarray; int rarray_len; int i; @@ -354,7 +355,9 @@ crypt_path_t *onion_generate_cpath(routerinfo_t **firsthop) { routerinfo_t *router; struct in_addr netaddr; - router_get_rarray(&rarray, &rarray_len); + router_get_directory(&dir); + rarray = dir->routers; + rarray_len = dir->n_routers; /* choose a route */ route = new_route(options.CoinWeight, rarray, rarray_len, &routelen); diff --git a/src/or/or.h b/src/or/or.h index c48edd87f9..65db958954 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -328,6 +328,11 @@ typedef struct { void *next; } routerinfo_t; +typedef struct { + routerinfo_t **routers; + int n_routers; +} directory_t; + struct crypt_path_t { /* crypto environments */ @@ -779,11 +784,13 @@ int learn_my_address(struct sockaddr_in *me); void router_retry_connections(void); routerinfo_t *router_pick_directory_server(void); routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port); -void router_get_rarray(routerinfo_t ***prouter_array, int *prarray_len); +void router_get_directory(directory_t **pdirectory); int router_is_me(uint32_t addr, uint16_t port); 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_get_list_from_string_impl(char *s, directory_t **dest); +routerinfo_t *router_get_entry_from_string(char **s); int router_compare_to_exit_policy(connection_t *conn); diff --git a/src/or/routers.c b/src/or/routers.c index 4447aa0bb4..49a66cbeb2 100644 --- a/src/or/routers.c +++ b/src/or/routers.c @@ -9,8 +9,7 @@ /****************************************************************************/ /* router array */ -static routerinfo_t **router_array = NULL; -static int rarray_len = 0; +static directory_t *directory = NULL; extern or_options_t options; /* command-line and config-file options */ extern routerinfo_t *my_routerinfo; /* from main.c */ @@ -22,7 +21,7 @@ static void routerlist_free(routerinfo_t *list); static routerinfo_t **make_rarray(routerinfo_t* list, int *len); static char *eat_whitespace(char *s); static char *find_whitespace(char *s); -static routerinfo_t *router_get_entry_from_string(char **s); +static int router_resolve(routerinfo_t *router); static void router_add_exit_policy(routerinfo_t *router, char *string); static void router_free_exit_policy(routerinfo_t *router); @@ -57,8 +56,8 @@ void router_retry_connections(void) { int i; routerinfo_t *router; - for (i=0;in_routers;i++) { + router = directory->routers[i]; if(!connection_exact_get_by_addr_port(router->addr,router->or_port)) { /* not in the list */ log(LOG_DEBUG,"retry_all_connections(): connecting to OR %s:%u.",router->address,router->or_port); connection_or_connect_as_or(router); @@ -71,11 +70,11 @@ routerinfo_t *router_pick_directory_server(void) { int i; routerinfo_t *router; - if(!router_array) + if(!directory) return NULL; - for(i=0;in_routers;i++) { + router = directory->routers[i]; if(router->dir_port > 0) return router; } @@ -87,10 +86,10 @@ routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port) { int i; routerinfo_t *router; - assert(router_array); + assert(directory); - for(i=0;in_routers;i++) { + router = directory->routers[i]; if ((router->addr == addr) && (router->or_port == port)) return router; } @@ -98,9 +97,8 @@ routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port) { return NULL; } -void router_get_rarray(routerinfo_t ***prouter_array, int *prarray_len) { - *prouter_array = router_array; - *prarray_len = rarray_len; +void router_get_directory(directory_t **pdirectory) { + *pdirectory = directory; } /* return 1 if addr and port corresponds to my addr and my or_listenport. else 0, @@ -129,6 +127,7 @@ int router_is_me(uint32_t addr, uint16_t port) static void routerlist_free(routerinfo_t *list) { routerinfo_t *tmp = NULL; + struct exit_policy_t *e = NULL, *etmp = NULL; if (!list) return; @@ -136,8 +135,19 @@ static void routerlist_free(routerinfo_t *list) do { tmp=list->next; - free((void *)list->address); - crypto_free_pk_env(list->pkey); + if (list->address) + free((void *)list->address); + if (list->pkey) + crypto_free_pk_env(list->pkey); + e = list->exit_policy; + while (e) { + etmp = e->next; + if (e->string) free(e->string); + if (e->address) free(e->address); + if (e->port) free(e->port); + free(e); + e = etmp; + } free((void *)list); list = tmp; } @@ -153,6 +163,12 @@ void rarray_free(routerinfo_t **list) { free(list); } +void directory_free(directory_t *directory) +{ + rarray_free(directory->routers); + free(directory); +} + void router_forget_router(uint32_t addr, uint16_t port) { int i; routerinfo_t *router; @@ -162,17 +178,17 @@ void router_forget_router(uint32_t addr, uint16_t port) { return; /* now walk down router_array until we get to router */ - for(i=0;in_routers;i++) + if(directory->routers[i] == router) break; - assert(i != rarray_len); /* if so then router_get_by_addr_port should have returned null */ + assert(i != directory->n_routers); /* if so then router_get_by_addr_port should have returned null */ // free(router); /* don't actually free; we'll free it when we free the whole thing */ // log(LOG_DEBUG,"router_forget_router(): Forgot about router %d:%d",addr,port); - for(; in_routers-1;i++) + directory->routers[i] = directory->routers[i+1]; } /* create a NULL-terminated array of pointers pointing to elements of a router list */ @@ -272,7 +288,13 @@ int router_get_list_from_file(char *routerfile) return 0; } -int router_get_list_from_string(char *s) { +int router_get_list_from_string(char *s) +{ + return router_get_list_from_string_impl(s, &directory); +} + +int router_get_list_from_string_impl(char *s, directory_t **dest) +{ routerinfo_t *routerlist=NULL; routerinfo_t *router; routerinfo_t **new_router_array; @@ -286,6 +308,11 @@ int router_get_list_from_string(char *s) { routerlist_free(routerlist); return -1; } + if (router_resolve(router)) { + routerlist_free(router); + routerlist_free(routerlist); + return -1; + } switch(router_is_me(router->addr, router->or_port)) { case 0: /* it's not me */ router->next = routerlist; @@ -307,9 +334,11 @@ int router_get_list_from_string(char *s) { new_router_array = make_rarray(routerlist, &new_rarray_len); if(new_router_array) { /* success! replace the old one */ - rarray_free(router_array); /* free the old one first */ - router_array = new_router_array; - rarray_len = new_rarray_len; + if (*dest) + directory_free(*dest); + *dest = (directory_t*) malloc(sizeof(directory_t)); + (*dest)->routers = new_router_array; + (*dest)->n_routers = new_rarray_len; return 0; } return -1; @@ -342,14 +371,38 @@ static char *find_whitespace(char *s) { return s; } +static int +router_resolve(routerinfo_t *router) +{ + struct hostent *rent; + + rent = (struct hostent *)gethostbyname(router->address); + if (!rent) { + log(LOG_ERR,"router_resolve(): Could not get address for router %s.",router->address); + return -1; + } + assert(rent->h_length == 4); + memcpy(&router->addr, rent->h_addr,rent->h_length); + router->addr = ntohl(router->addr); /* get it back into host order */ + + return 0; +} + /* reads a single router entry from s. * updates s so it points to after the router it just read. * mallocs a new router, returns it if all goes well, else returns NULL. */ -static routerinfo_t *router_get_entry_from_string(char **s) { +routerinfo_t *router_get_entry_from_string(char **s) { routerinfo_t *router; char *next; - struct hostent *rent; + + /* Make sure that this string really starts with a router entry. */ + *s = eat_whitespace(*s); + if (strncasecmp(*s, "router ", 7)) { + log(LOG_ERR,"router_get_entry_from_string(): Entry does not start with \"router\""); + return NULL; + } + puts("X"); router = malloc(sizeof(routerinfo_t)); if (!router) { @@ -357,6 +410,7 @@ static routerinfo_t *router_get_entry_from_string(char **s) { return NULL; } memset(router,0,sizeof(routerinfo_t)); /* zero it out first */ + router->next = NULL; /* Bug: if find_whitespace returns a '#', we'll squish it. */ #define NEXT_TOKEN(s, next) \ @@ -367,19 +421,17 @@ static routerinfo_t *router_get_entry_from_string(char **s) { } \ *next = 0; + /* Skip the "router" */ + NEXT_TOKEN(s, next); + *s = next+1; + /* read router->address */ NEXT_TOKEN(s, next); router->address = strdup(*s); *s = next+1; - rent = (struct hostent *)gethostbyname(router->address); - if (!rent) { - log(LOG_ERR,"router_get_entry_from_string(): Could not get address for router %s.",router->address); - goto router_read_failed; - } - assert(rent->h_length == 4); - memcpy(&router->addr, rent->h_addr,rent->h_length); - router->addr = ntohl(router->addr); /* get it back into host order */ + /* Don't resolve address till later. */ + router->addr = 0; /* read router->or_port */ NEXT_TOKEN(s, next); diff --git a/src/or/test.c b/src/or/test.c index 99dd9c9f43..ae1a94b65d 100644 --- a/src/or/test.c +++ b/src/or/test.c @@ -462,8 +462,6 @@ test_util() { void test_onion_handshake() { - int i; - /* client-side */ crypto_dh_env_t *c_dh = NULL; char c_buf[DH_ONIONSKIN_LEN]; @@ -500,6 +498,114 @@ test_onion_handshake() { test_memneq(c_keys, s_buf, 40); } +/* from main.c */ +int dump_router_to_string(char *s, int maxlen, routerinfo_t *router); +void dump_directory_to_string(char *s, int maxlen); + +void +test_dir_format() +{ + + char buf[2048], buf2[512]; + char *pk1_str, *pk2_str, *cp; + int pk1_str_len, pk2_str_len; + routerinfo_t r1, r2; + crypto_pk_env_t *pk1 = NULL, *pk2 = NULL; + routerinfo_t *rp1, *rp2; + struct exit_policy_t ex1, ex2, ex3; + + int i; + + test_assert( (pk1 = crypto_new_pk_env(CRYPTO_PK_RSA)) ); + test_assert( (pk2 = crypto_new_pk_env(CRYPTO_PK_RSA)) ); + test_assert(! crypto_pk_generate_key(pk1)); + test_assert(! crypto_pk_generate_key(pk2)); + + r1.address = "testaddr1.foo.bar"; + r1.addr = 0xc0a80001u; /* 192.168.0.1 */ + r1.or_port = 9000; + r1.op_port = 9001; + r1.ap_port = 9002; + r1.dir_port = 9003; + r1.pkey = pk1; + r1.bandwidth = 1000; + r1.exit_policy = NULL; + r1.next = &r2; + + ex1.policy_type = EXIT_POLICY_ACCEPT; + ex1.string = NULL; + ex1.address = "*"; + ex1.port = "80"; + ex1.next = &ex2; + ex2.policy_type = EXIT_POLICY_REJECT; + ex2.address = "18.*"; + ex2.port = "24"; + ex2.next = NULL; + r2.address = "tor.tor.tor"; + r2.addr = 0x0a030201u; /* 10.3.2.1 */ + r2.or_port = 9005; + r2.op_port = 0; + r2.ap_port = 0; + r2.dir_port = 0; + r2.pkey = pk2; + r2.bandwidth = 3000; + r2.exit_policy = &ex1; + r2.next = NULL; + + test_assert(!crypto_pk_write_public_key_to_string(pk1, &pk1_str, + &pk1_str_len)); + test_assert(!crypto_pk_write_public_key_to_string(pk2 , &pk2_str, + &pk2_str_len)); + strcpy(buf2, "router testaddr1.foo.bar 9000 9001 9002 9003 1000\n"); + strcat(buf2, pk1_str); + strcat(buf2, "\n"); + + memset(buf, 0, 2048); + test_assert(dump_router_to_string(buf, 2048, &r1)>0); + test_streq(buf, buf2); + + cp = buf; + rp1 = router_get_entry_from_string(&cp); + test_assert(rp1); + test_streq(rp1->address, r1.address); + test_eq(rp1->or_port, r1.or_port); + test_eq(rp1->op_port, r1.op_port); + test_eq(rp1->ap_port, r1.ap_port); + test_eq(rp1->dir_port, r1.dir_port); + test_eq(rp1->bandwidth, r1.bandwidth); + test_assert(crypto_pk_cmp_keys(rp1->pkey, pk1) == 0); + test_assert(rp1->exit_policy == NULL); + + strcpy(buf2, "router tor.tor.tor 9005 0 0 0 3000\n"); + strcat(buf2, pk2_str); + strcat(buf2, "accept *:80\nreject 18.*:24\n\n"); + test_assert(dump_router_to_string(buf, 2048, &r2)>0); + test_streq(buf, buf2); + + cp = buf; + rp2 = router_get_entry_from_string(&cp); + test_assert(rp2); + test_streq(rp2->address, r2.address); + test_eq(rp2->or_port, r2.or_port); + test_eq(rp2->op_port, r2.op_port); + test_eq(rp2->ap_port, r2.ap_port); + test_eq(rp2->dir_port, r2.dir_port); + test_eq(rp2->bandwidth, r2.bandwidth); + test_assert(crypto_pk_cmp_keys(rp2->pkey, pk2) == 0); + test_eq(rp2->exit_policy->policy_type, EXIT_POLICY_ACCEPT); + test_streq(rp2->exit_policy->string, "accept *:80"); + test_streq(rp2->exit_policy->address, "*"); + test_streq(rp2->exit_policy->port, "80"); + test_eq(rp2->exit_policy->next->policy_type, EXIT_POLICY_REJECT); + test_streq(rp2->exit_policy->next->string, "reject 18.*:24"); + test_streq(rp2->exit_policy->next->address, "18.*"); + test_streq(rp2->exit_policy->next->port, "24"); + test_assert(rp2->exit_policy->next->next == NULL); + + + /* XXXX free everything*/ +} + int main(int c, char**v) { #if 0 @@ -511,6 +617,7 @@ main(int c, char**v) { log(LOG_ERR,NULL); /* make logging quieter */ setup_directory(); +#if 1 puts("========================== Buffers ========================="); test_buffers(); puts("========================== Crypto =========================="); @@ -518,8 +625,11 @@ main(int c, char**v) { test_crypto(); puts("\n========================= Util ============================"); test_util(); - puts("\n========================= Onion Skins======================"); + puts("\n========================= Onion Skins ====================="); test_onion_handshake(); +#endif + puts("\n========================= Directory Formats ==============="); + test_dir_format(); puts(""); return 0; }