summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Dingledine <arma@torproject.org>2007-09-21 06:14:36 +0000
committerRoger Dingledine <arma@torproject.org>2007-09-21 06:14:36 +0000
commit193a144c9fc069f230a4e1cd14815b0514731253 (patch)
tree47abaa6cf3c80d3276dd8e89a742d83df55bf93f
parent6aadc6071e1eace36920fee7ae79dd53c2cc6811 (diff)
downloadtor-193a144c9fc069f230a4e1cd14815b0514731253.tar.gz
tor-193a144c9fc069f230a4e1cd14815b0514731253.zip
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--ChangeLog8
-rw-r--r--src/or/circuitbuild.c5
-rw-r--r--src/or/directory.c96
-rw-r--r--src/or/or.h4
-rw-r--r--src/or/routerlist.c32
5 files changed, 92 insertions, 53 deletions
diff --git a/ChangeLog b/ChangeLog
index 05e653dca0..39970eea52 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 2f88c85e88..32077a4525 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 05b68b6777..28612a9415 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 df2b716ae3..317439dfff 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 33ce081173..fbb99834e8 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);
});