From 22df330f144292f43de419d2f839af4f9f55ef04 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 8 May 2003 21:35:11 +0000 Subject: [PATCH] Get directories working. Or at least, directories get generated, signed, download, and checked, with nobody seeming to crash. In config/*, added 'signing-key' blocks to dirservers and routers.or, so that everyone will know about the directories' signing keys. In or/directory.c, refrained from using a dirserver's signing key when no such key is known; added more debugging output. In or/main.c, added debugging output and fixed a few logic errors. In or/routers.c, added debugging output and prevented a segfault on routers_resolve_directory. The interleaving of arrays and lists on routerinfo_t is still messy, but at least it seems to work again. svn:r278 --- src/config/dirservers | 20 ++++++++++++- src/config/routers.or | 18 ++++++++++++ src/or/directory.c | 11 +++++++- src/or/main.c | 45 +++++++++++++++++++---------- src/or/routers.c | 66 +++++++++++++++++++++++++++++++++---------- 5 files changed, 128 insertions(+), 32 deletions(-) diff --git a/src/config/dirservers b/src/config/dirservers index f8224cd6ed..6bb9a61dab 100644 --- a/src/config/dirservers +++ b/src/config/dirservers @@ -13,6 +13,13 @@ MIGJAoGBAMBBuk1sYxEg5jLAJy86U3GGJ7EGMSV7yoA6mmcsEVU3pwTUrpbpCmwS 7BvovoY3z4zk63NZVBErgKQUDkn3pp8n83xZgEf4GI27gdWIIwaBjEimuJlEY+7K nZ7kVMRoiXCbjL6VAtNa4Zy1Af/GOm0iCIDpholeujQ95xew7rQnAgMA//8= -----END RSA PUBLIC KEY----- +signing-key +-----BEGIN RSA PUBLIC KEY----- +MIGJAoGBAMBBuk1sYxEg5jLAJy86U3GGJ7EGMSV7yoA6mmcsEVU3pwTUrpbpCmwS +7BvovoY3z4zk63NZVBErgKQUDkn3pp8n83xZgEf4GI27gdWIIwaBjEimuJlEY+7K +nZ7kVMRoiXCbjL6VAtNa4Zy1Af/GOm0iCIDpholeujQ95xew7rQnAgMA//8= +-----END RSA PUBLIC KEY----- + # Router 2 router moria.mit.edu 9002 9012 9022 9032 1000000 @@ -21,6 +28,12 @@ MIGJAoGBANX/HHRuudz274MFSQ4manX8DhtsIuogNUyco9/0dr+XsfioTGd3RgMj aSWlD87arkZO4hHBPHe0q89Z3s1UtUsyQ/VmsxSv9g2OCnF/dU2Nz4h6+Al3iNJF 1UlWR4eiqBx3djxdIl/t+Nidw++YGc8QqRqkg0EhQCJ2fnOtHn9bAgMA//8= -----END RSA PUBLIC KEY----- +signing-key +-----BEGIN RSA PUBLIC KEY----- +MIGJAoGBANX/HHRuudz274MFSQ4manX8DhtsIuogNUyco9/0dr+XsfioTGd3RgMj +aSWlD87arkZO4hHBPHe0q89Z3s1UtUsyQ/VmsxSv9g2OCnF/dU2Nz4h6+Al3iNJF +1UlWR4eiqBx3djxdIl/t+Nidw++YGc8QqRqkg0EhQCJ2fnOtHn9bAgMA//8= +-----END RSA PUBLIC KEY----- # Router 3 router moria.mit.edu 9003 9013 9023 9033 1000000 @@ -29,4 +42,9 @@ MIGJAoGBAJfkNWCaNkYIRwfHT06KBU6dz8W1xDpW5ezGJwAOoxCX3/ZNoUicb/1V oB3OzW6VxWIiht3da/3K0ywiBOOCcf6BabKoMdiPpH7NIeu6XRmBYK2uqW13gBgh xJbQBb58Nx8Fr05XkvLG6i+vTDY3MZOW3E2/DwSe/jFzuHSD5b3nAgMA//8= -----END RSA PUBLIC KEY----- - +signing-key +-----BEGIN RSA PUBLIC KEY----- +MIGJAoGBAJfkNWCaNkYIRwfHT06KBU6dz8W1xDpW5ezGJwAOoxCX3/ZNoUicb/1V +oB3OzW6VxWIiht3da/3K0ywiBOOCcf6BabKoMdiPpH7NIeu6XRmBYK2uqW13gBgh +xJbQBb58Nx8Fr05XkvLG6i+vTDY3MZOW3E2/DwSe/jFzuHSD5b3nAgMA//8= +-----END RSA PUBLIC KEY----- diff --git a/src/config/routers.or b/src/config/routers.or index e28deed98c..614b9fb7ca 100644 --- a/src/config/routers.or +++ b/src/config/routers.or @@ -13,6 +13,12 @@ MIGJAoGBAMBBuk1sYxEg5jLAJy86U3GGJ7EGMSV7yoA6mmcsEVU3pwTUrpbpCmwS 7BvovoY3z4zk63NZVBErgKQUDkn3pp8n83xZgEf4GI27gdWIIwaBjEimuJlEY+7K nZ7kVMRoiXCbjL6VAtNa4Zy1Af/GOm0iCIDpholeujQ95xew7rQnAgMA//8= -----END RSA PUBLIC KEY----- +signing-key +-----BEGIN RSA PUBLIC KEY----- +MIGJAoGBAMBBuk1sYxEg5jLAJy86U3GGJ7EGMSV7yoA6mmcsEVU3pwTUrpbpCmwS +7BvovoY3z4zk63NZVBErgKQUDkn3pp8n83xZgEf4GI27gdWIIwaBjEimuJlEY+7K +nZ7kVMRoiXCbjL6VAtNa4Zy1Af/GOm0iCIDpholeujQ95xew7rQnAgMA//8= +-----END RSA PUBLIC KEY----- # Router 2 router moria.mit.edu 9002 9012 9022 9032 1000000 @@ -21,6 +27,12 @@ MIGJAoGBANX/HHRuudz274MFSQ4manX8DhtsIuogNUyco9/0dr+XsfioTGd3RgMj aSWlD87arkZO4hHBPHe0q89Z3s1UtUsyQ/VmsxSv9g2OCnF/dU2Nz4h6+Al3iNJF 1UlWR4eiqBx3djxdIl/t+Nidw++YGc8QqRqkg0EhQCJ2fnOtHn9bAgMA//8= -----END RSA PUBLIC KEY----- +signing-key +-----BEGIN RSA PUBLIC KEY----- +MIGJAoGBANX/HHRuudz274MFSQ4manX8DhtsIuogNUyco9/0dr+XsfioTGd3RgMj +aSWlD87arkZO4hHBPHe0q89Z3s1UtUsyQ/VmsxSv9g2OCnF/dU2Nz4h6+Al3iNJF +1UlWR4eiqBx3djxdIl/t+Nidw++YGc8QqRqkg0EhQCJ2fnOtHn9bAgMA//8= +-----END RSA PUBLIC KEY----- # Router 3 router moria.mit.edu 9003 9013 9023 9033 1000000 @@ -29,6 +41,12 @@ MIGJAoGBAJfkNWCaNkYIRwfHT06KBU6dz8W1xDpW5ezGJwAOoxCX3/ZNoUicb/1V oB3OzW6VxWIiht3da/3K0ywiBOOCcf6BabKoMdiPpH7NIeu6XRmBYK2uqW13gBgh xJbQBb58Nx8Fr05XkvLG6i+vTDY3MZOW3E2/DwSe/jFzuHSD5b3nAgMA//8= -----END RSA PUBLIC KEY----- +signing-key +-----BEGIN RSA PUBLIC KEY----- +MIGJAoGBAJfkNWCaNkYIRwfHT06KBU6dz8W1xDpW5ezGJwAOoxCX3/ZNoUicb/1V +oB3OzW6VxWIiht3da/3K0ywiBOOCcf6BabKoMdiPpH7NIeu6XRmBYK2uqW13gBgh +xJbQBb58Nx8Fr05XkvLG6i+vTDY3MZOW3E2/DwSe/jFzuHSD5b3nAgMA//8= +-----END RSA PUBLIC KEY----- router moria.mit.edu 9004 9014 9024 0 1000000 -----BEGIN RSA PUBLIC KEY----- diff --git a/src/or/directory.c b/src/or/directory.c index db154ab345..060dc15617 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -43,7 +43,12 @@ void directory_initiate_fetch(routerinfo_t *router) { conn->address = strdup(router->address); conn->receiver_bucket = -1; /* edge connections don't do receiver buckets */ conn->bandwidth = -1; - conn->pkey = crypto_pk_dup_key(router->signing_pkey); + if (router->signing_pkey) + conn->pkey = crypto_pk_dup_key(router->signing_pkey); + else { + log(LOG_ERR, "No signing key known for directory %s; signature won\'t be checked", conn->address); + conn->pkey = NULL; + } s=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP); if(s < 0) { @@ -148,7 +153,11 @@ int connection_dir_process_inbuf(connection_t *conn) { } if(router_get_dir_from_string(the_directory, conn->pkey) < 0) { log(LOG_DEBUG,"connection_dir_process_inbuf(): ...but parsing failed. Ignoring."); + } else { + log(LOG_DEBUG,"connection_dir_process_inbuf(): and got a %s directory; updated routers.", + conn->pkey ? "authenticated" : "unauthenticated"); } + if(options.ORPort) { /* connect to them all */ router_retry_connections(); } diff --git a/src/or/main.c b/src/or/main.c index b5199e3511..0b32c8fc42 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -654,7 +654,7 @@ build_directory(directory_t *dir) { routers = (routerinfo_t**) malloc(sizeof(routerinfo_t*) * (nfds+1)); if (!routers) { - /* freak out XXX */ + log(LOG_ERR, "build_directory(): couldn\'t allocate space for routerinfo"); return -1; } if (my_routerinfo) { @@ -669,7 +669,8 @@ build_directory(directory_t *dir) { continue; /* we only want to list ones that successfully handshaked */ router = router_get_by_addr_port(conn->addr,conn->port); if(!router) { - log(LOG_ERR,"dump_directory_to_string(): couldn't find router %d:%d!",conn->addr,conn->port); + log(LOG_ERR,"dump_directory_to_string(): couldn\'t find router %d:%d!", + conn->addr,conn->port); continue; } routers[n++] = router; @@ -684,9 +685,11 @@ dump_signed_directory_to_string(char *s, int maxlen, crypto_pk_env_t *private_key) { directory_t dir; - if (!build_directory(&dir)) + if (build_directory(&dir)) { + log(LOG_ERR,"dump_signed_directory_to_string(): build_directory failed."); return -1; - return dump_signed_directory_to_string_impl(s, maxlen, &dir, private_key); + } + return dump_signed_directory_to_string_impl(s, maxlen, &dir, private_key); } int @@ -703,21 +706,22 @@ dump_signed_directory_to_string_impl(char *s, int maxlen, directory_t *dir, "client-software x y z\n" /* XXX make this real */ "server-software a b c\n\n" /* XXX make this real */ , maxlen); + + i = strlen(s); + cp = s+i; for (i = 0; i < dir->n_routers; ++i) { router = dir->routers[i]; - written = dump_router_to_string(s, maxlen, router); + written = dump_router_to_string(cp, maxlen-i, router); 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 */ + log(LOG_ERR,"dump_signed_directory_to_string(): tried to exceed string length."); + cp[maxlen-1] = 0; /* make sure it's null terminated */ return -1; } - - maxlen -= written; - s += written; + i += written; + cp += written; } - /* These multiple strlen calls are inefficient, but dwarfed by the RSA signature. */ @@ -726,22 +730,33 @@ dump_signed_directory_to_string_impl(char *s, int maxlen, directory_t *dir, i = strlen(s); cp = s + i; - if (crypto_SHA_digest(s, i, digest)) + if (crypto_SHA_digest(s, i, digest)) { + log(LOG_ERR,"dump_signed_directory_to_string(): couldn\'t compute digest"); return -1; - if (crypto_pk_private_sign(get_signing_privatekey(), digest, 20, signature) < 0) + } + if (crypto_pk_private_sign(private_key, digest, 20, signature) < 0) { + log(LOG_ERR,"dump_signed_directory_to_string(): couldn\'t sign digest"); return -1; + } strncpy(cp, "-----BEGIN SIGNATURE-----\n", maxlen-i); i = strlen(s); cp = s+i; - if (base64_encode(cp, maxlen-i, signature, 128) < 0) + if (base64_encode(cp, maxlen-i, signature, 128) < 0) { + log(LOG_ERR,"dump_signed_directory_to_string(): couldn\'t base64-encode signature %d/%d"); return -1; + } i = strlen(s); cp = s+i; - strcat(cp, "-----END SIGNATURE-----\n"); + strncat(cp, "-----END SIGNATURE-----\n", maxlen-i); + i = strlen(s); + if (i == maxlen) { + log(LOG_ERR,"dump_signed_directory_to_string(): tried to exceed string length."); + return -1; + } return 0; } diff --git a/src/or/routers.c b/src/or/routers.c index 11156dcecd..ab9c8b8827 100644 --- a/src/or/routers.c +++ b/src/or/routers.c @@ -518,15 +518,21 @@ static char *find_whitespace(char *s) { int router_get_list_from_string(char *s) { - int i; - i = router_get_list_from_string_impl(s, &directory); - router_resolve_directory(directory); - return i; + if (router_get_list_from_string_impl(s, &directory)) { + log(LOG_ERR, "Error parsing router file"); + return -1; + } + if (router_resolve_directory(directory)) { + log(LOG_ERR, "Error resolving directory"); + return -1; + } + return 0; } int router_get_list_from_string_impl(char *s, directory_t **dest) { directory_token_t tok; if (router_get_next_token(&s, &tok)) { + log(LOG_ERR, "Error reading routers: %s", tok.val.error); return -1; } return router_get_list_from_string_tok(&s, dest, &tok); @@ -536,25 +542,41 @@ static int router_get_dir_hash(char *s, char *digest) { char *start, *end; start = strstr(s, "signed-directory"); - if (!start) return -1; + if (!start) { + log(LOG_ERR,"router_get_dir_hash(): couldn't find \"signed-directory\""); + return -1; + } end = strstr(start, "directory-signature"); - if (!end) return -1; + if (!end) { + log(LOG_ERR,"router_get_dir_hash(): couldn't find \"directory-signature\""); + return -1; + } end = strchr(end, '\n'); - if (!end) return -1; + if (!end) { + log(LOG_ERR,"router_get_dir_hash(): couldn't find EOL"); + return -1; + } ++end; - if (crypto_SHA_digest(start, end-start, digest)) + if (crypto_SHA_digest(start, end-start, digest)) { + log(LOG_ERR,"router_get_dir_hash(): couldn't compute digest"); return -1; + } return 0; } int router_get_dir_from_string(char *s, crypto_pk_env_t *pkey) { - int i; - i = router_get_dir_from_string_impl(s, &directory, pkey); - router_resolve_directory(directory); - return i; + if (router_get_dir_from_string_impl(s, &directory, pkey)) { + log(LOG_ERR, "router_get_dir_from_string: Couldn\'t parse directory."); + return -1; + } + if (router_resolve_directory(directory)) { + log(LOG_ERR, "Error resolving directory"); + return -1; + } + return 0; } int router_get_dir_from_string_impl(char *s, directory_t **dest, @@ -578,8 +600,10 @@ int router_get_dir_from_string_impl(char *s, directory_t **dest, return -1; \ } } while(0) - if (router_get_dir_hash(s, digest)) + if (router_get_dir_hash(s, digest)) { + log(LOG_ERR, "Unable to compute digest of directory"); return -1; + } NEXT_TOK(); TOK_IS(K_SIGNED_DIRECTORY, "signed-directory"); @@ -591,8 +615,10 @@ int router_get_dir_from_string_impl(char *s, directory_t **dest, TOK_IS(K_SERVER_SOFTWARE, "server-software"); NEXT_TOK(); - if (router_get_list_from_string_tok(&s, &new_dir, &tok)) + if (router_get_list_from_string_tok(&s, &new_dir, &tok)) { + log(LOG_ERR, "Error reading routers from directory"); return -1; + } TOK_IS(K_DIRECTORY_SIGNATURE, "directory-signature"); NEXT_TOK(); @@ -637,6 +663,10 @@ static int router_get_list_from_string_tok(char **s, directory_t **dest, while (tok->tp == K_ROUTER) { router = router_get_entry_from_string_tok(s, tok); + if (!router) { + log(LOG_ERR, "Error reading router"); + return -1; + } switch(router_is_me(router->addr, router->or_port)) { case 0: /* it's not me */ router->next = routerlist; @@ -694,7 +724,8 @@ router_resolve_directory(directory_t *dir) max = dir->n_routers; for (i = 0; i < max; ++i) { if (router_resolve(dir->routers[i])) { - /* ARMA: Is this the right way to remove a router from the directory? */ + log(LOG_INFO, "Couldn\'t resolve router %s; removing", + dir->routers[i]->address); dir->routers[i]->next = NULL; routerlist_free(dir->routers[i]); dir->routers[i] = dir->routers[--max]; @@ -702,6 +733,11 @@ router_resolve_directory(directory_t *dir) --dir->n_routers; } } + /* This is quick-and-dirty, but it keeps stuff consistant. */ + for (i = 0; i < dir->n_routers-1; ++i) { + dir->routers[i]->next = dir->routers[i+1]; + } + dir->routers[dir->n_routers-1]->next=NULL; return 0; }