diff options
-rw-r--r-- | changes/bug10722 | 8 | ||||
-rw-r--r-- | src/or/channeltls.c | 26 | ||||
-rw-r--r-- | src/or/directory.h | 2 | ||||
-rw-r--r-- | src/or/rendclient.c | 27 |
4 files changed, 58 insertions, 5 deletions
diff --git a/changes/bug10722 b/changes/bug10722 new file mode 100644 index 000000000..dd4711f11 --- /dev/null +++ b/changes/bug10722 @@ -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". diff --git a/src/or/channeltls.c b/src/or/channeltls.c index 42d6874d8..959ec4744 100644 --- a/src/or/channeltls.c +++ b/src/or/channeltls.c @@ -53,6 +53,7 @@ static void channel_tls_common_init(channel_tls_t *tlschan); static void channel_tls_close_method(channel_t *chan); static const char * channel_tls_describe_transport_method(channel_t *chan); +static void channel_tls_free_method(channel_t *chan); static int channel_tls_get_remote_addr_method(channel_t *chan, tor_addr_t *addr_out); static int @@ -114,6 +115,7 @@ channel_tls_common_init(channel_tls_t *tlschan) chan->state = CHANNEL_STATE_OPENING; chan->close = channel_tls_close_method; chan->describe_transport = channel_tls_describe_transport_method; + chan->free = channel_tls_free_method; chan->get_remote_addr = channel_tls_get_remote_addr_method; chan->get_remote_descr = channel_tls_get_remote_descr_method; chan->get_transport_name = channel_tls_get_transport_name_method; @@ -387,6 +389,30 @@ channel_tls_describe_transport_method(channel_t *chan) } /** + * Free a channel_tls_t + * + * This is called by the generic channel layer when freeing a channel_tls_t; + * this happens either on a channel which has already reached + * CHANNEL_STATE_CLOSED or CHANNEL_STATE_ERROR from channel_run_cleanup() or + * on shutdown from channel_free_all(). In the latter case we might still + * have an orconn active (which connection_free_all() will get to later), + * so we should null out its channel pointer now. + */ + +static void +channel_tls_free_method(channel_t *chan) +{ + channel_tls_t *tlschan = BASE_CHAN_TO_TLS(chan); + + tor_assert(tlschan); + + if (tlschan->conn) { + tlschan->conn->chan = NULL; + tlschan->conn = NULL; + } +} + +/** * Get the remote address of a channel_tls_t * * This implements the get_remote_addr method for channel_tls_t; copy the diff --git a/src/or/directory.h b/src/or/directory.h index 0453160f7..3de69329a 100644 --- a/src/or/directory.h +++ b/src/or/directory.h @@ -30,7 +30,7 @@ typedef enum { DIRIND_ONEHOP=0, /** Connect over a multi-hop anonymizing Tor circuit */ DIRIND_ANONYMOUS=1, - /** Conncet to the DirPort directly */ + /** Connect to the DirPort directly */ DIRIND_DIRECT_CONN, /** Connect over a multi-hop anonymizing Tor circuit to our dirport */ DIRIND_ANON_DIRPORT, diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 4de010182..2327a547c 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -619,11 +619,14 @@ static int directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query) { smartlist_t *responsible_dirs = smartlist_new(); + smartlist_t *usable_responsible_dirs = smartlist_new(); + const or_options_t *options = get_options(); routerstatus_t *hs_dir; char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1]; time_t now = time(NULL); 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(rend_query); /* Determine responsible dirs. Even if we can't get all we want, @@ -644,16 +647,32 @@ directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query) dir, desc_id_base32, rend_query, 0, 0); const node_t *node = node_get_by_id(dir->identity_digest); if (last + REND_HID_SERV_DIR_REQUERY_PERIOD >= now || - !node || !node_has_descriptor(node)) - SMARTLIST_DEL_CURRENT(responsible_dirs, dir); + !node || !node_has_descriptor(node)) { + 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(usable_responsible_dirs); if (!hs_dir) { log_info(LD_REND, "Could not pick one of the responsible hidden " "service directories, because we requested them all " "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; } |