diff --git a/doc/TODO b/doc/TODO index 96ee668777..924ba81a6b 100644 --- a/doc/TODO +++ b/doc/TODO @@ -56,9 +56,12 @@ Things we'd like to do in 0.2.0.x: - 101: Voting on the Tor Directory System . 104: Long and Short Router Descriptors (by Jun 1) . Finalize proposal - - Implement parsing for extra-info documents; have authorities - accept them and serve them from specified URLs - - Have routers generate and upload extra-info documents. + o Implement parsing for extra-info documents + o Have routers generate extra-info documents. + . Have have authorities accept them and serve them from specified URLs + o Implement directory-protocol side. + - Implement storage. + - Have routers upload extra-info documents. - Implement option to download and cache extra-info documents. - Drop bandwidth history from router-descriptors - 105: Version negotiation for the Tor protocol (finalize by Jun 1) diff --git a/src/or/directory.c b/src/or/directory.c index 5188fa3ccc..e76108f9b2 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -1683,31 +1683,34 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, return 0; } - if (!strcmpstart(url,"/tor/server/")) { + if (!strcmpstart(url,"/tor/server/") || + !strcmpstart(url,"/tor/extra/")) { size_t url_len = strlen(url); int deflated = !strcmp(url+url_len-2, ".z"); int res; const char *msg; const char *request_type = NULL; int cache_lifetime = 0; + int is_extra = !strcmpstart(url,"/tor/extra/"); if (deflated) url[url_len-2] = '\0'; + url += is_extra ? strlen("/tor/extra/") : strlen("/tor/server/"); conn->fingerprint_stack = smartlist_create(); res = dirserv_get_routerdesc_fingerprints(conn->fingerprint_stack, url, &msg); - if (!strcmpstart(url, "/tor/server/fp/")) { + if (!strcmpstart(url, "fp/")) { request_type = deflated?"/tor/server/fp.z":"/tor/server/fp"; if (smartlist_len(conn->fingerprint_stack) == 1) cache_lifetime = ROUTERDESC_CACHE_LIFETIME; - } else if (!strcmpstart(url, "/tor/server/authority")) { + } else if (!strcmpstart(url, "authority")) { request_type = deflated?"/tor/server/authority.z": "/tor/server/authority"; cache_lifetime = ROUTERDESC_CACHE_LIFETIME; - } else if (!strcmpstart(url, "/tor/server/all")) { + } else if (!strcmpstart(url, "all")) { request_type = deflated?"/tor/server/all.z":"/tor/server/all"; cache_lifetime = FULL_DIR_CACHE_LIFETIME; - } else if (!strcmpstart(url, "/tor/server/d/")) { + } else if (!strcmpstart(url, "d/")) { request_type = deflated?"/tor/server/d.z":"/tor/server/d"; if (smartlist_len(conn->fingerprint_stack) == 1) cache_lifetime = ROUTERDESC_BY_DIGEST_CACHE_LIFETIME; @@ -1715,10 +1718,12 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, request_type = "/tor/server/?"; } (void) request_type; /* usable for note_request. */ - if (!strcmpstart(url, "/tor/server/d/")) - conn->dir_spool_src = DIR_SPOOL_SERVER_BY_DIGEST; + if (!strcmpstart(url, "d/")) + conn->dir_spool_src = + is_extra ? DIR_SPOOL_EXTRA_BY_DIGEST : DIR_SPOOL_SERVER_BY_DIGEST; else - conn->dir_spool_src = DIR_SPOOL_SERVER_BY_FP; + conn->dir_spool_src = + is_extra ? DIR_SPOOL_EXTRA_BY_FP : DIR_SPOOL_SERVER_BY_FP; tor_free(url); if (res < 0) write_http_status_line(conn, 404, msg); diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 048f7f7b63..e8811c0d01 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -537,8 +537,36 @@ dirserv_add_descriptor(const char *desc, const char **msg) { int r; routerinfo_t *ri = NULL, *ri_old = NULL; + extrainfo_t *ei = NULL; tor_assert(msg); *msg = NULL; + desc = eat_whitespace(desc); + + if (!strcmpstart(desc, "extra-info")) { + /* It's an extra-info thingie. */ + routerlist_t *rl = router_get_routerlist(); + ei = extrainfo_parse_entry_from_string(desc, NULL, 1, rl->identity_map); + if (!ei) { + log_warn(LD_DIRSERV, "Couldn't parse uploaded extra-info descriptor"); + *msg = "Rejected: couldn't parse extra-info descriptor"; + return -2; + } + ri = router_get_by_digest(ei->cache_info.identity_digest); + if (!ri) { + *msg = "No corresponding router descriptor for extra-info descriptor"; + extrainfo_free(ei); + return -1; + } + if (routerinfo_incompatible_with_extrainfo(ri, ei)) { + *msg = "Router descriptor incompatible with extra-info descriptor"; + extrainfo_free(ei); + return -1; + } + /* XXXX020 Eventually, we should store this. For now, we'll just + * discard it. */ + extrainfo_free(ei); + return 2; + } /* Check: is the descriptor syntactically valid? */ ri = router_parse_entry_from_string(desc, NULL, 1); @@ -1815,8 +1843,9 @@ dirserv_get_networkstatus_v2(smartlist_t *result, } /** As dirserv_get_routerdescs(), but instead of getting signed_descriptor_t - * pointers, adds copies of digests to fps_out. For a /tor/server/d/ request, - * adds descriptor digests; for other requests, adds identity digests. + * pointers, adds copies of digests to fps_out, and doesn't use the + * /tor/server/ prefix. For a /d/ request, adds descriptor digests; for other + * requests, adds identity digests. */ int dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key, @@ -1824,21 +1853,21 @@ dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key, { *msg = NULL; - if (!strcmp(key, "/tor/server/all")) { + if (!strcmp(key, "all")) { routerlist_t *rl = router_get_routerlist(); SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r, smartlist_add(fps_out, tor_memdup(r->cache_info.identity_digest, DIGEST_LEN))); - } else if (!strcmp(key, "/tor/server/authority")) { + } else if (!strcmp(key, "authority")) { routerinfo_t *ri = router_get_my_routerinfo(); if (ri) smartlist_add(fps_out, tor_memdup(ri->cache_info.identity_digest, DIGEST_LEN)); - } else if (!strcmpstart(key, "/tor/server/d/")) { - key += strlen("/tor/server/d/"); + } else if (!strcmpstart(key, "d/")) { + key += strlen("d/"); dir_split_resource_into_fingerprints(key, fps_out, NULL, 1, 1); - } else if (!strcmpstart(key, "/tor/server/fp/")) { - key += strlen("/tor/server/fp/"); + } else if (!strcmpstart(key, "fp/")) { + key += strlen("fp/"); dir_split_resource_into_fingerprints(key, fps_out, NULL, 1, 1); } else { *msg = "Key not recognized"; @@ -2065,7 +2094,11 @@ connection_dirserv_finish_spooling(dir_connection_t *conn) static int connection_dirserv_add_servers_to_outbuf(dir_connection_t *conn) { - int by_fp = conn->dir_spool_src == DIR_SPOOL_SERVER_BY_FP; + int by_fp = (conn->dir_spool_src == DIR_SPOOL_SERVER_BY_FP || + conn->dir_spool_src == DIR_SPOOL_EXTRA_BY_FP); + int extra = (conn->dir_spool_src == DIR_SPOOL_EXTRA_BY_FP || + conn->dir_spool_src == DIR_SPOOL_EXTRA_BY_DIGEST); + time_t publish_cutoff = time(NULL)-ROUTER_MAX_AGE_TO_PUBLISH; while (smartlist_len(conn->fingerprint_stack) && buf_datalen(conn->_base.outbuf) < DIRSERV_BUFFER_MIN) { @@ -2074,15 +2107,25 @@ connection_dirserv_add_servers_to_outbuf(dir_connection_t *conn) signed_descriptor_t *sd = NULL; if (by_fp) { if (router_digest_is_me(fp)) { - sd = &(router_get_my_routerinfo()->cache_info); + if (extra) + sd = &(router_get_my_extrainfo()->cache_info); + else + sd = &(router_get_my_routerinfo()->cache_info); } else { routerinfo_t *ri = router_get_by_digest(fp); if (ri && - ri->cache_info.published_on > time(NULL)-ROUTER_MAX_AGE_TO_PUBLISH) - sd = &ri->cache_info; + ri->cache_info.published_on > publish_cutoff) { + if (extra) { + sd = extrainfo_get_by_descriptor_digest(ri->extra_info_digest); + } else { + sd = &ri->cache_info; + } + } } - } else - sd = router_get_by_descriptor_digest(fp); + } else { + sd = extra ? extrainfo_get_by_descriptor_digest(fp) + : router_get_by_descriptor_digest(fp); + } tor_free(fp); if (!sd) continue; @@ -2216,6 +2259,8 @@ connection_dirserv_flushed_some(dir_connection_t *conn) return 0; switch (conn->dir_spool_src) { + case DIR_SPOOL_EXTRA_BY_DIGEST: + case DIR_SPOOL_EXTRA_BY_FP: case DIR_SPOOL_SERVER_BY_DIGEST: case DIR_SPOOL_SERVER_BY_FP: return connection_dirserv_add_servers_to_outbuf(conn); diff --git a/src/or/or.h b/src/or/or.h index fabecde0a3..ff9dfe397f 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -907,6 +907,7 @@ typedef struct dir_connection_t { /** What exactly are we spooling right now? */ enum { DIR_SPOOL_NONE=0, DIR_SPOOL_SERVER_BY_DIGEST, DIR_SPOOL_SERVER_BY_FP, + DIR_SPOOL_EXTRA_BY_DIGEST, DIR_SPOOL_EXTRA_BY_FP, DIR_SPOOL_CACHED_DIR, DIR_SPOOL_NETWORKSTATUS } dir_spool_src : 3; /** List of fingerprints for networkstatuses or desriptors to be spooled. */ @@ -2892,7 +2893,7 @@ void check_descriptor_ipaddress_changed(time_t now); void router_new_address_suggestion(const char *suggestion); int router_compare_to_my_exit_policy(edge_connection_t *conn); routerinfo_t *router_get_my_routerinfo(void); -const char *router_get_my_extrainfo(void); +extrainfo_t *router_get_my_extrainfo(void); const char *router_get_my_descriptor(void); int router_digest_is_me(const char *digest); int router_is_me(routerinfo_t *router); @@ -2993,6 +2994,7 @@ routerinfo_t *router_get_by_nickname(const char *nickname, routerinfo_t *router_get_by_hexdigest(const char *hexdigest); routerinfo_t *router_get_by_digest(const char *digest); signed_descriptor_t *router_get_by_descriptor_digest(const char *digest); +signed_descriptor_t *extrainfo_get_by_descriptor_digest(const char *digest); const char *signed_descriptor_get_body(signed_descriptor_t *desc); int router_digest_version_as_new_as(const char *digest, const char *cutoff); int router_digest_is_trusted_dir(const char *digest); diff --git a/src/or/router.c b/src/or/router.c index c7d3b4aac4..c93f40bca6 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -815,14 +815,14 @@ router_get_my_descriptor(void) } /** DOCDOC */ -const char * +extrainfo_t * router_get_my_extrainfo(void) { if (!server_mode(get_options())) return NULL; if (router_rebuild_descriptor(0)) return NULL; - return desc_extrainfo->cache_info.signed_descriptor_body; + return desc_extrainfo; } /** A list of nicknames that we've warned about including in our family diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 9b1f60e422..9b77e3801f 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -1442,6 +1442,15 @@ router_get_by_descriptor_digest(const char *digest) return digestmap_get(routerlist->desc_digest_map, digest); } +/** DOCDOC */ +signed_descriptor_t * +extrainfo_get_by_descriptor_digest(const char *digest) +{ + /* XXXX020 implement me. */ + (void)digest; + return NULL; +} + /** Return a pointer to the signed textual representation of a descriptor. * The returned string is not guaranteed to be NUL-terminated: the string's * length will be in desc-\>signed_descriptor_len. */