Apply StrictNodes to hidden service directories early

Previously, we would sometimes decide in directory_get_from_hs_dir()
to connect to an excluded node, and then later in
directory_initiate_command_routerstatus_rend() notice that it was
excluded and strictnodes was set, and catch it as a stopgap.

Additionally, this patch preferentially tries to fetch from
non-excluded nodes even when StrictNodes is off.

Fix for bug #10722. Bugfix on 0.2.0.10-alpha (the v2 hidserv directory
system was introduced in e136f00ca). Reported by "mr-4".
This commit is contained in:
Nick Mathewson 2014-01-24 12:56:10 -05:00
parent 3511549651
commit bb21d14255
2 changed files with 31 additions and 4 deletions

8
changes/bug10722 Normal file
View File

@ -0,0 +1,8 @@
o Minor bugfixes:
- Consider non-excluded hidden service directory servers before
excluded ones. Do not consider excluded hidden service directory
servers at all if StrictNodes was set. (Previously, we would
sometimes decide to connect to those servers, and then realize
before we initiated a connection that we had excluded them.)
Fix for bug #10722. Bugfix on 0.2.0.10-alpha. Reported by
"mr-4".

View File

@ -617,11 +617,14 @@ static int
directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query) directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query)
{ {
smartlist_t *responsible_dirs = smartlist_new(); smartlist_t *responsible_dirs = smartlist_new();
smartlist_t *usable_responsible_dirs = smartlist_new();
const or_options_t *options = get_options();
routerstatus_t *hs_dir; routerstatus_t *hs_dir;
char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1]; char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
time_t now = time(NULL); time_t now = time(NULL);
char descriptor_cookie_base64[3*REND_DESC_COOKIE_LEN_BASE64]; char descriptor_cookie_base64[3*REND_DESC_COOKIE_LEN_BASE64];
int tor2web_mode = get_options()->Tor2webMode; const int tor2web_mode = options->Tor2webMode;
int excluded_some;
tor_assert(desc_id); tor_assert(desc_id);
tor_assert(rend_query); tor_assert(rend_query);
/* Determine responsible dirs. Even if we can't get all we want, /* Determine responsible dirs. Even if we can't get all we want,
@ -642,16 +645,32 @@ directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query)
dir, desc_id_base32, rend_query, 0, 0); dir, desc_id_base32, rend_query, 0, 0);
const node_t *node = node_get_by_id(dir->identity_digest); const node_t *node = node_get_by_id(dir->identity_digest);
if (last + REND_HID_SERV_DIR_REQUERY_PERIOD >= now || if (last + REND_HID_SERV_DIR_REQUERY_PERIOD >= now ||
!node || !node_has_descriptor(node)) !node || !node_has_descriptor(node)) {
SMARTLIST_DEL_CURRENT(responsible_dirs, dir); SMARTLIST_DEL_CURRENT(responsible_dirs, dir);
continue;
}
if (! routerset_contains_node(options->ExcludeNodes, node)) {
smartlist_add(usable_responsible_dirs, dir);
}
}); });
hs_dir = smartlist_choose(responsible_dirs); excluded_some =
smartlist_len(usable_responsible_dirs) < smartlist_len(responsible_dirs);
hs_dir = smartlist_choose(usable_responsible_dirs);
if (! hs_dir && ! options->StrictNodes)
hs_dir = smartlist_choose(responsible_dirs);
smartlist_free(responsible_dirs); smartlist_free(responsible_dirs);
smartlist_free(usable_responsible_dirs);
if (!hs_dir) { if (!hs_dir) {
log_info(LD_REND, "Could not pick one of the responsible hidden " log_info(LD_REND, "Could not pick one of the responsible hidden "
"service directories, because we requested them all " "service directories, because we requested them all "
"recently without success."); "recently without success.");
if (options->StrictNodes && excluded_some) {
log_info(LD_REND, "There are others that we could have tried, but "
"they are all excluded, and StrictNodes is set.");
}
return 0; return 0;
} }