diff options
author | Roger Dingledine <arma@torproject.org> | 2007-09-21 06:14:36 +0000 |
---|---|---|
committer | Roger Dingledine <arma@torproject.org> | 2007-09-21 06:14:36 +0000 |
commit | 193a144c9fc069f230a4e1cd14815b0514731253 (patch) | |
tree | 47abaa6cf3c80d3276dd8e89a742d83df55bf93f | |
parent | 6aadc6071e1eace36920fee7ae79dd53c2cc6811 (diff) | |
download | tor-193a144c9fc069f230a4e1cd14815b0514731253.tar tor-193a144c9fc069f230a4e1cd14815b0514731253.tar.gz |
Make "UpdateBridgesFromAuthority" torrc option work: when bridge
users configure that and specify a bridge with an identity
fingerprint, now they will lookup the bridge descriptor at the
default bridge authority via a one-hop tunnel, but once circuits
are established they will switch to a three-hop tunnel for later
connections to the bridge authority.
svn:r11550
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | src/or/circuitbuild.c | 5 | ||||
-rw-r--r-- | src/or/directory.c | 96 | ||||
-rw-r--r-- | src/or/or.h | 4 | ||||
-rw-r--r-- | src/or/routerlist.c | 32 |
5 files changed, 92 insertions, 53 deletions
@@ -3,6 +3,14 @@ Changes in version 0.2.0.7-alpha - 2007-09-21 - Set up moria1 and tor26 as the first v3 directory authorities. See doc/spec/dir-spec.txt for details on the new directory design. + o Major features (bridges): + - Make "UpdateBridgesFromAuthority" torrc option work: when bridge + users configure that and specify a bridge with an identity + fingerprint, now they will lookup the bridge descriptor at the + default bridge authority via a one-hop tunnel, but once circuits + are established they will switch to a three-hop tunnel for later + connections to the bridge authority. + o Minor features (security): - As a client, do not believe any server that tells us that any address maps to an internal address space. diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 2f88c85e8..32077a452 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -2927,6 +2927,9 @@ fetch_bridge_descriptors(time_t now) ask_bridge_directly = tor_digest_is_zero(bridge->identity) || !options->UpdateBridgesFromAuthority || !num_bridge_auths; + log_debug(LD_DIR, "ask_bridge_directly=%d (%d, %d, %d)", + ask_bridge_directly, tor_digest_is_zero(bridge->identity), + !options->UpdateBridgesFromAuthority, !num_bridge_auths); if (ask_bridge_directly && !fascist_firewall_allows_address_or(bridge->addr, bridge->port)) { @@ -2961,7 +2964,7 @@ fetch_bridge_descriptors(time_t now) log_info(LD_DIR, "Fetching bridge info '%s' from bridge authority.", resource); directory_get_from_dirserver(DIR_PURPOSE_FETCH_SERVERDESC, - ROUTER_PURPOSE_BRIDGE, resource, 1); + ROUTER_PURPOSE_BRIDGE, resource, 0); } }); } diff --git a/src/or/directory.c b/src/or/directory.c index 05b68b677..28612a941 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -49,7 +49,8 @@ static void dir_networkstatus_download_failed(smartlist_t *failed, int status_code); static void dir_routerdesc_download_failed(smartlist_t *failed, int status_code, - int was_extrainfo); + int was_extrainfo, + int was_descriptor_digests); static void note_request(const char *key, size_t bytes); /********* START VARIABLES **********/ @@ -78,8 +79,8 @@ purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose) { if (get_options()->AllDirActionsPrivate) return 1; - if (router_purpose == ROUTER_PURPOSE_BRIDGE) - return 1; /* if we have to ask, better make it anonymous */ + if (router_purpose == ROUTER_PURPOSE_BRIDGE && has_completed_circuit) + return 1; /* if no circuits yet, we may need this info to bootstrap. */ if (dir_purpose == DIR_PURPOSE_FETCH_DIR || dir_purpose == DIR_PURPOSE_UPLOAD_DIR || dir_purpose == DIR_PURPOSE_UPLOAD_VOTE || @@ -307,37 +308,39 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose, if (!options->FetchServerDescriptors && type != HIDSERV_AUTHORITY) return; - if (!get_via_tor && options->UseBridges) { - /* want to ask a running bridge for which we have a descriptor. */ - routerinfo_t *ri = choose_random_entry(NULL); - if (ri) { - directory_initiate_command(ri->address, ri->addr, - ri->or_port, 0, - 1, ri->cache_info.identity_digest, - dir_purpose, - router_purpose, - 0, resource, NULL, 0); - } else - log_notice(LD_DIR, "Ignoring directory request, since no bridge " - "nodes are available yet."); - return; - } else if (!get_via_tor) { - if (prefer_authority) { - /* only ask authdirservers, and don't ask myself */ - rs = router_pick_trusteddirserver(type, 1, 1, - retry_if_no_servers); - } - if (!rs) { - /* anybody with a non-zero dirport will do */ - rs = router_pick_directory_server(1, 1, type, - retry_if_no_servers); - if (!rs) { - log_info(LD_DIR, "No router found for %s; falling back to " - "dirserver list.", dir_conn_purpose_to_string(dir_purpose)); + if (!get_via_tor) { + if (options->UseBridges && type != BRIDGE_AUTHORITY) { + /* want to ask a running bridge for which we have a descriptor. */ + routerinfo_t *ri = choose_random_entry(NULL); + if (ri) { + directory_initiate_command(ri->address, ri->addr, + ri->or_port, 0, + 1, ri->cache_info.identity_digest, + dir_purpose, + router_purpose, + 0, resource, NULL, 0); + } else + log_notice(LD_DIR, "Ignoring directory request, since no bridge " + "nodes are available yet."); + return; + } else { + if (prefer_authority || type == BRIDGE_AUTHORITY) { + /* only ask authdirservers, and don't ask myself */ rs = router_pick_trusteddirserver(type, 1, 1, retry_if_no_servers); - if (!rs) - get_via_tor = 1; /* last resort: try routing it via Tor */ + } + if (!rs && type != BRIDGE_AUTHORITY) { + /* anybody with a non-zero dirport will do */ + rs = router_pick_directory_server(1, 1, type, + retry_if_no_servers); + if (!rs) { + log_info(LD_DIR, "No router found for %s; falling back to " + "dirserver list.", dir_conn_purpose_to_string(dir_purpose)); + rs = router_pick_trusteddirserver(type, 1, 1, + retry_if_no_servers); + if (!rs) + get_via_tor = 1; /* last resort: try routing it via Tor */ + } } } } else { /* get_via_tor */ @@ -1342,6 +1345,8 @@ connection_dir_client_reached_eof(dir_connection_t *conn) int was_ei = conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO; smartlist_t *which = NULL; int n_asked_for = 0; + int descriptor_digests = conn->requested_resource && + !strcmpstart(conn->requested_resource,"d/"); log_info(LD_DIR,"Received %s (size %d) from server '%s:%d'", was_ei ? "extra server info" : "server info", (int)body_len, conn->_base.address, conn->_base.port); @@ -1350,9 +1355,11 @@ connection_dir_client_reached_eof(dir_connection_t *conn) else note_request(was_compressed?"dl/server.z":"dl/server", orig_len); if (conn->requested_resource && - !strcmpstart(conn->requested_resource,"d/")) { + (!strcmpstart(conn->requested_resource,"d/") || + !strcmpstart(conn->requested_resource,"fp/"))) { which = smartlist_create(); - dir_split_resource_into_fingerprints(conn->requested_resource+2, + dir_split_resource_into_fingerprints(conn->requested_resource + + (descriptor_digests ? 2 : 3), which, NULL, 0, 0); n_asked_for = smartlist_len(which); } @@ -1370,7 +1377,8 @@ connection_dir_client_reached_eof(dir_connection_t *conn) if (!which) { connection_dir_download_routerdesc_failed(conn); } else { - dir_routerdesc_download_failed(which, status_code, was_ei); + dir_routerdesc_download_failed(which, status_code, + was_ei, descriptor_digests); SMARTLIST_FOREACH(which, char *, cp, tor_free(cp)); smartlist_free(which); } @@ -1391,10 +1399,11 @@ connection_dir_client_reached_eof(dir_connection_t *conn) get_options()->UseBridges)))) { /* as we learn from them, we remove them from 'which' */ if (was_ei) { - router_load_extrainfo_from_string(body, NULL, SAVED_NOWHERE, which); + router_load_extrainfo_from_string(body, NULL, SAVED_NOWHERE, which, + descriptor_digests); } else { router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which, - conn->router_purpose); + descriptor_digests, conn->router_purpose); directory_info_has_arrived(now, 0); } } @@ -1403,7 +1412,8 @@ connection_dir_client_reached_eof(dir_connection_t *conn) n_asked_for-smartlist_len(which), n_asked_for, conn->_base.address, (int)conn->_base.port); if (smartlist_len(which)) { - dir_routerdesc_download_failed(which, status_code, was_ei); + dir_routerdesc_download_failed(which, status_code, + was_ei, descriptor_digests); } SMARTLIST_FOREACH(which, char *, cp, tor_free(cp)); smartlist_free(which); @@ -2527,15 +2537,19 @@ dir_networkstatus_download_failed(smartlist_t *failed, int status_code) } /** Called when one or more routerdesc (or extrainfo, if <b>was_extrainfo</b>) - * fetches have failed (with uppercase fingerprints listed in - * <b>failed</b>). */ + * fetches have failed (with uppercase fingerprints listed in <b>failed</b>, + * either as descriptor digests or as identity digests based on + * <b>was_descriptor_digests</b>). + */ static void dir_routerdesc_download_failed(smartlist_t *failed, int status_code, - int was_extrainfo) + int was_extrainfo, int was_descriptor_digests) { char digest[DIGEST_LEN]; time_t now = time(NULL); int server = server_mode(get_options()) && get_options()->DirPort; + if (!was_descriptor_digests) + return; /* FFFF should implement this someday */ SMARTLIST_FOREACH(failed, const char *, cp, { download_status_t *dls = NULL; diff --git a/src/or/or.h b/src/or/or.h index df2b716ae..317439dff 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -3514,10 +3514,12 @@ int router_load_single_router(const char *s, uint8_t purpose, void router_load_routers_from_string(const char *s, const char *eos, saved_location_t saved_location, smartlist_t *requested_fingerprints, + int descriptor_digests, uint8_t purpose); void router_load_extrainfo_from_string(const char *s, const char *eos, saved_location_t saved_location, - smartlist_t *requested_fps); + smartlist_t *requested_fps, + int descriptor_digests); typedef enum { NS_FROM_CACHE, NS_FROM_DIR_BY_FP, NS_FROM_DIR_ALL, NS_GENERATED diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 33ce08117..fbb99834e 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -724,11 +724,11 @@ router_reload_router_list_impl(desc_store_t *store) if (extrainfo) router_load_extrainfo_from_string(store->mmap->data, store->mmap->data+store->mmap->size, - SAVED_IN_CACHE, NULL); + SAVED_IN_CACHE, NULL, 0); else router_load_routers_from_string(store->mmap->data, store->mmap->data+store->mmap->size, - SAVED_IN_CACHE, NULL, + SAVED_IN_CACHE, NULL, 0, ROUTER_PURPOSE_GENERAL); } @@ -738,10 +738,11 @@ router_reload_router_list_impl(desc_store_t *store) contents = read_file_to_str(fname, RFTS_BIN|RFTS_IGNORE_MISSING, &st); if (contents) { if (extrainfo) - router_load_extrainfo_from_string(contents, NULL,SAVED_IN_JOURNAL, NULL); + router_load_extrainfo_from_string(contents, NULL,SAVED_IN_JOURNAL, + NULL, 0); else - router_load_routers_from_string(contents, NULL, SAVED_IN_JOURNAL, NULL, - ROUTER_PURPOSE_GENERAL); + router_load_routers_from_string(contents, NULL, SAVED_IN_JOURNAL, + NULL, 0, ROUTER_PURPOSE_GENERAL); store->journal_len = (size_t) st.st_size; tor_free(contents); } @@ -3128,14 +3129,18 @@ router_load_single_router(const char *s, uint8_t purpose, const char **msg) * the journal. * * If <b>requested_fingerprints</b> is provided, it must contain a list of - * uppercased identity fingerprints. Do not update any router whose + * uppercased fingerprints. Do not update any router whose * fingerprint is not on the list; after updating a router, remove its * fingerprint from the list. + * + * If <b>descriptor_digests</b> is non-zero, then the requested_fingerprints + * are descriptor digests. Otherwise they are identity digests. */ void router_load_routers_from_string(const char *s, const char *eos, saved_location_t saved_location, smartlist_t *requested_fingerprints, + int descriptor_digests, uint8_t purpose) { smartlist_t *routers = smartlist_create(), *changed = smartlist_create(); @@ -3151,9 +3156,11 @@ router_load_routers_from_string(const char *s, const char *eos, SMARTLIST_FOREACH(routers, routerinfo_t *, ri, { - base16_encode(fp, sizeof(fp), ri->cache_info.signed_descriptor_digest, - DIGEST_LEN); if (requested_fingerprints) { + base16_encode(fp, sizeof(fp), descriptor_digests ? + ri->cache_info.signed_descriptor_digest : + ri->cache_info.identity_digest, + DIGEST_LEN); if (smartlist_string_isin(requested_fingerprints, fp)) { smartlist_string_remove(requested_fingerprints, fp); } else { @@ -3195,7 +3202,8 @@ router_load_routers_from_string(const char *s, const char *eos, void router_load_extrainfo_from_string(const char *s, const char *eos, saved_location_t saved_location, - smartlist_t *requested_fingerprints) + smartlist_t *requested_fingerprints, + int descriptor_digests) { smartlist_t *extrainfo_list = smartlist_create(); const char *msg; @@ -3208,9 +3216,13 @@ router_load_extrainfo_from_string(const char *s, const char *eos, SMARTLIST_FOREACH(extrainfo_list, extrainfo_t *, ei, { if (requested_fingerprints) { char fp[HEX_DIGEST_LEN+1]; - base16_encode(fp, sizeof(fp), ei->cache_info.signed_descriptor_digest, + base16_encode(fp, sizeof(fp), descriptor_digests ? + ei->cache_info.signed_descriptor_digest : + ei->cache_info.identity_digest, DIGEST_LEN); smartlist_string_remove(requested_fingerprints, fp); + /* XXX020 We silently let people stuff us with extrainfos we + * didn't ask for. Is this a problem? -RD */ } router_add_extrainfo_to_routerlist(ei, &msg, from_cache, !from_cache); }); |