Merge remote-tracking branch 'origin/maint-0.2.2' into release-0.2.2

This commit is contained in:
Nick Mathewson 2011-04-28 22:08:53 -04:00
commit 68a169ec55
28 changed files with 387 additions and 109 deletions

5
changes/bug2475 Normal file
View File

@ -0,0 +1,5 @@
o Minor bugfixes:
- Avoid signed/unsigned comparisons by making SIZE_T_CEILING unsigned.
(None of the cases where we did this before were wrong, but by making
this change we can avoid warnings.) Fixes bug2475; bugfix on
Tor 0.2.1.28.

11
changes/bug2722 Normal file
View File

@ -0,0 +1,11 @@
o Minor bugfixes
- Ignore the TunnelDirConns option when determining which HSDir
relays are responsible for a hidden service descriptor ID.
Currently, clients and hidden services with TunnelDirConns off
will skip over HSDir relays which do not advertise a DirPort
when making a list of HSDirs responsible for a descriptor ID,
even though they would never try to use a HSDir's DirPort to
upload or fetch a hidden service descriptor. Fixes bug 2722;
bugfix on 0.2.1.6-alpha.

5
changes/bug3012 Normal file
View File

@ -0,0 +1,5 @@
o Minor features:
- Relays can go for weeks without writing out their state file. A
relay that crashes would lose its bandwidth history (including
capacity estimate), client country statistics, and so on. Now relays
checkpoint the file at least every 12 hours. Addresses bug 3012.

7
changes/bug3020 Normal file
View File

@ -0,0 +1,7 @@
o Minor bugfixes:
- When checking whether a hibernation period has fully elapsed, use
the amount of seconds we expect for that period instead of using
the new period that just started. This would cause an issue because
February is a really short month. Bugfix on 0.2.2.17-alpha;
fixes bug 3020.

5
changes/bug3039 Normal file
View File

@ -0,0 +1,5 @@
o Minor bugfixes:
- Write the current time into the LastWritten line in our state file,
rather than the time from the previous write attempt. Also, stop
trying to use a time of -1 in our log statements. Fixes bug 3039;
bugfix on 0.2.2.14-alpha.

View File

@ -0,0 +1,5 @@
o Minor bugfixes:
- Fix a bug in the code where we could keep trying to use a
TrackHostExits-based mapping after we failed to reach the intended
destination node. Fixes bug 2999. Bugfix on 0.2.0.20-rc.

View File

@ -0,0 +1,21 @@
o Security fixes:
- Forget all hidden service descriptors cached as a client when
processing a SIGNAL NEWNYM command. Fixes bug 3000. Bugfix on
0.0.6.
o Major bugfixes:
- When we find that we have extended a hidden service's introduction
circuit to a relay which isn't listed as an introduction point in
the HS descriptor we currently have for the service, we now retry
one of the introduction points in the current HS descriptor.
Previously we would just give up. Bugfix on 0.2.0.10-alpha; fixes
bugs 1024 and 1930.
o Minor bugfixes:
- Don't allow v0 hidden service authorities to act as clients.
Required by fix for bug 3000.
- Ignore SIGNAL NEWNYM commands on relay-only Tor instances.
Required by fix for bug 3000.
o Code simplifications and refactoring:
- Allow rend_client_send_introduction to fail without closing the
AP connection permanently.

6
changes/gmtime_null Normal file
View File

@ -0,0 +1,6 @@
o Minor bugfixes
- On some platforms, gmtime and localtime can return NULL under
certain circumstances even for well-defined values of time_t.
Try to detect and make up for this deficiency. Possible fix for
bug 2077. Bugfix on all versions of Tor. Found by boboper.

4
changes/ticket2497 Normal file
View File

@ -0,0 +1,4 @@
o Minor features:
- Ensure that no empty [dirreq-](read|write)-history lines are added
to an extrainfo document. Implements ticket 2497.

View File

@ -1996,14 +1996,88 @@ tor_gettimeofday(struct timeval *timeval)
#define TIME_FNS_NEED_LOCKS
#endif
static struct tm *
correct_tm(int islocal, const time_t *timep, struct tm *resultbuf,
struct tm *r)
{
const char *outcome;
if (PREDICT_LIKELY(r)) {
if (r->tm_year > 8099) { /* We can't strftime dates after 9999 CE. */
r->tm_year = 8099;
r->tm_mon = 11;
r->tm_mday = 31;
r->tm_yday = 365;
r->tm_hour = 23;
r->tm_min = 59;
r->tm_sec = 59;
}
return r;
}
/* If we get here, gmtime or localtime returned NULL. It might have done
* this because of overrun or underrun, or it might have done it because of
* some other weird issue. */
if (timep) {
if (*timep < 0) {
r = resultbuf;
r->tm_year = 70; /* 1970 CE */
r->tm_mon = 0;
r->tm_mday = 1;
r->tm_yday = 1;
r->tm_hour = 0;
r->tm_min = 0 ;
r->tm_sec = 0;
outcome = "Rounding up to 1970";
goto done;
} else if (*timep >= INT32_MAX) {
/* Rounding down to INT32_MAX isn't so great, but keep in mind that we
* only do it if gmtime/localtime tells us NULL. */
r = resultbuf;
r->tm_year = 137; /* 2037 CE */
r->tm_mon = 11;
r->tm_mday = 31;
r->tm_yday = 365;
r->tm_hour = 23;
r->tm_min = 59;
r->tm_sec = 59;
outcome = "Rounding down to 2037";
goto done;
}
}
/* If we get here, then gmtime/localtime failed without getting an extreme
* value for *timep */
tor_fragile_assert();
r = resultbuf;
memset(resultbuf, 0, sizeof(struct tm));
outcome="can't recover";
done:
log_warn(LD_BUG, "%s("I64_FORMAT") failed with error %s: %s",
islocal?"localtime":"gmtime",
timep?I64_PRINTF_ARG(*timep):0,
strerror(errno),
outcome);
return r;
}
/** @{ */
/** As localtime_r, but defined for platforms that don't have it:
*
* Convert *<b>timep</b> to a struct tm in local time, and store the value in
* *<b>result</b>. Return the result on success, or NULL on failure.
*/
#ifndef HAVE_LOCALTIME_R
#ifdef TIME_FNS_NEED_LOCKS
#ifdef HAVE_LOCALTIME_R
struct tm *
tor_localtime_r(const time_t *timep, struct tm *result)
{
struct tm *r;
r = localtime_r(timep, result);
return correct_tm(1, timep, result, r);
}
#elif defined(TIME_FNS_NEED_LOCKS)
struct tm *
tor_localtime_r(const time_t *timep, struct tm *result)
{
@ -2013,9 +2087,10 @@ tor_localtime_r(const time_t *timep, struct tm *result)
tor_assert(result);
tor_mutex_acquire(m);
r = localtime(timep);
memcpy(result, r, sizeof(struct tm));
if (r)
memcpy(result, r, sizeof(struct tm));
tor_mutex_release(m);
return result;
return correct_tm(1, timep, result, r);
}
#else
struct tm *
@ -2024,11 +2099,11 @@ tor_localtime_r(const time_t *timep, struct tm *result)
struct tm *r;
tor_assert(result);
r = localtime(timep);
memcpy(result, r, sizeof(struct tm));
return result;
if (r)
memcpy(result, r, sizeof(struct tm));
return correct_tm(1, timep, result, r);
}
#endif
#endif
/** @} */
/** @{ */
@ -2037,8 +2112,15 @@ tor_localtime_r(const time_t *timep, struct tm *result)
* Convert *<b>timep</b> to a struct tm in UTC, and store the value in
* *<b>result</b>. Return the result on success, or NULL on failure.
*/
#ifndef HAVE_GMTIME_R
#ifdef TIME_FNS_NEED_LOCKS
#ifdef HAVE_GMTIME_R
struct tm *
tor_gmtime_r(const time_t *timep, struct tm *result)
{
struct tm *r;
r = gmtime_r(timep, result);
return correct_tm(0, timep, result, r);
}
#elif defined(TIME_FNS_NEED_LOCKS)
struct tm *
tor_gmtime_r(const time_t *timep, struct tm *result)
{
@ -2048,9 +2130,10 @@ tor_gmtime_r(const time_t *timep, struct tm *result)
tor_assert(result);
tor_mutex_acquire(m);
r = gmtime(timep);
memcpy(result, r, sizeof(struct tm));
if (r)
memcpy(result, r, sizeof(struct tm));
tor_mutex_release(m);
return result;
return correct_tm(0, timep, result, r);
}
#else
struct tm *
@ -2059,12 +2142,11 @@ tor_gmtime_r(const time_t *timep, struct tm *result)
struct tm *r;
tor_assert(result);
r = gmtime(timep);
memcpy(result, r, sizeof(struct tm));
return result;
if (r)
memcpy(result, r, sizeof(struct tm));
return correct_tm(0, timep, result, r);
}
#endif
#endif
/** @} */
#if defined(USE_WIN32_THREADS)
void

View File

@ -321,17 +321,8 @@ struct timeval {
void tor_gettimeofday(struct timeval *timeval);
#ifdef HAVE_LOCALTIME_R
#define tor_localtime_r localtime_r
#else
struct tm *tor_localtime_r(const time_t *timep, struct tm *result);
#endif
#ifdef HAVE_GMTIME_R
#define tor_gmtime_r gmtime_r
#else
struct tm *tor_gmtime_r(const time_t *timep, struct tm *result);
#endif
#ifndef timeradd
/** Replacement for timeradd on platforms that do not have it: sets tvout to

View File

@ -523,7 +523,7 @@ crypto_pk_read_private_key_from_string(crypto_pk_env_t *env,
tor_assert(env);
tor_assert(s);
tor_assert(len < INT_MAX && len < SIZE_T_CEILING);
tor_assert(len < INT_MAX && len < SSIZE_T_CEILING);
/* Create a read-only memory BIO, backed by the string 's' */
b = BIO_new_mem_buf((char*)s, (int)len);

View File

@ -329,8 +329,10 @@ typedef uint32_t uintptr_t;
#endif
#endif
/** Any ssize_t larger than this amount is likely to be an underflow. */
#define SSIZE_T_CEILING ((ssize_t)(SSIZE_T_MAX-16))
/** Any size_t larger than this amount is likely to be an underflow. */
#define SIZE_T_CEILING (SSIZE_T_MAX-16)
#define SIZE_T_CEILING ((size_t)(SSIZE_T_MAX-16))
#endif /* __TORINT_H */

View File

@ -119,7 +119,7 @@ circuit_build_times_disabled(void)
0, 0, 1);
int config_disabled = !get_options()->LearnCircuitBuildTimeout;
int dirauth_disabled = get_options()->AuthoritativeDir;
int state_disabled = (get_or_state()->LastWritten == -1);
int state_disabled = did_last_state_file_write_fail() ? 1 : 0;
if (consensus_disabled || config_disabled || dirauth_disabled ||
state_disabled) {
@ -4584,8 +4584,7 @@ find_bridge_by_digest(const char *digest)
return NULL;
}
/** We need to ask <b>bridge</b> for its server descriptor. <b>address</b>
* is a helpful string describing this bridge. */
/** We need to ask <b>bridge</b> for its server descriptor. */
static void
launch_direct_bridge_descriptor_fetch(bridge_info_t *bridge)
{

View File

@ -1744,14 +1744,21 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
"introduction. (stream %d sec old)",
introcirc->_base.n_circ_id, rendcirc->_base.n_circ_id,
conn_age);
if (rend_client_send_introduction(introcirc, rendcirc) < 0) {
switch (rend_client_send_introduction(introcirc, rendcirc)) {
case 0: /* success */
rendcirc->_base.timestamp_dirty = time(NULL);
introcirc->_base.timestamp_dirty = time(NULL);
assert_circuit_ok(TO_CIRCUIT(rendcirc));
assert_circuit_ok(TO_CIRCUIT(introcirc));
return 0;
case -1: /* transient error */
return 0;
case -2: /* permanent error */
return -1;
default: /* oops */
tor_fragile_assert();
return -1;
}
rendcirc->_base.timestamp_dirty = time(NULL);
introcirc->_base.timestamp_dirty = time(NULL);
assert_circuit_ok(TO_CIRCUIT(rendcirc));
assert_circuit_ok(TO_CIRCUIT(introcirc));
return 0;
}
}

View File

@ -3078,6 +3078,10 @@ options_validate(or_options_t *old_options, or_options_t *options,
REJECT("FetchDirInfoExtraEarly requires that you also set "
"FetchDirInfoEarly");
if (options->HSAuthoritativeDir && proxy_mode(options))
REJECT("Running as authoritative v0 HS directory, but also configured "
"as a client.");
if (options->ConnLimit <= 0) {
tor_asprintf(msg,
"ConnLimit must be greater than 0, but was set to %d",
@ -5115,9 +5119,26 @@ or_state_load(void)
return r;
}
/** Did the last time we tried to write the state file fail? If so, we
* should consider disabling such features as preemptive circuit generation
* to compute circuit-build-time. */
static int last_state_file_write_failed = 0;
/** Return whether the state file failed to write last time we tried. */
int
did_last_state_file_write_fail(void)
{
return last_state_file_write_failed;
}
/** If writing the state to disk fails, try again after this many seconds. */
#define STATE_WRITE_RETRY_INTERVAL 3600
/** If we're a relay, how often should we checkpoint our state file even
* if nothing else dirties it? This will checkpoint ongoing stats like
* bandwidth used, per-country user stats, etc. */
#define STATE_RELAY_CHECKPOINT_INTERVAL (12*60*60)
/** Write the persistent state to disk. Return 0 for success, <0 on failure. */
int
or_state_save(time_t now)
@ -5139,11 +5160,13 @@ or_state_save(time_t now)
if (accounting_is_enabled(get_options()))
accounting_run_housekeeping(now);
global_state->LastWritten = now;
tor_free(global_state->TorVersion);
tor_asprintf(&global_state->TorVersion, "Tor %s", get_version());
state = config_dump(&state_format, global_state, 1, 0);
format_local_iso_time(tbuf, time(NULL));
format_local_iso_time(tbuf, now);
tor_asprintf(&contents,
"# Tor state file last generated on %s local time\n"
"# Other times below are in GMT\n"
@ -5154,7 +5177,7 @@ or_state_save(time_t now)
if (write_str_to_file(fname, contents, 0)<0) {
log_warn(LD_FS, "Unable to write state to file \"%s\"; "
"will try again later", fname);
global_state->LastWritten = -1;
last_state_file_write_failed = 1;
tor_free(fname);
tor_free(contents);
/* Try again after STATE_WRITE_RETRY_INTERVAL (or sooner, if the state
@ -5163,12 +5186,16 @@ or_state_save(time_t now)
return -1;
}
global_state->LastWritten = time(NULL);
last_state_file_write_failed = 0;
log_info(LD_GENERAL, "Saved state to \"%s\"", fname);
tor_free(fname);
tor_free(contents);
global_state->next_write = TIME_MAX;
if (server_mode(get_options()))
global_state->next_write = now + STATE_RELAY_CHECKPOINT_INTERVAL;
else
global_state->next_write = TIME_MAX;
return 0;
}

View File

@ -58,6 +58,7 @@ char *options_get_datadir_fname2_suffix(or_options_t *options,
get_datadir_fname2_suffix((sub1), NULL, (suffix))
or_state_t *get_or_state(void);
int did_last_state_file_write_fail(void);
int or_state_save(time_t now);
int options_need_geoip_info(or_options_t *options, const char **reason_out);

View File

@ -799,8 +799,8 @@ clear_trackexithost_mappings(const char *exitname)
tor_strlower(suffix);
STRMAP_FOREACH_MODIFY(addressmap, address, addressmap_entry_t *, ent) {
/* XXXX022 HEY! Shouldn't this look at ent->new_address? */
if (ent->source == ADDRMAPSRC_TRACKEXIT && !strcmpend(address, suffix)) {
if (ent->source == ADDRMAPSRC_TRACKEXIT &&
!strcmpend(ent->new_address, suffix)) {
addressmap_ent_remove(address, ent);
MAP_DEL_CURRENT(address);
}

View File

@ -1811,6 +1811,9 @@ dirserv_thinks_router_is_hs_dir(routerinfo_t *router, time_t now)
* bug 1693. In the future, once relays set wants_to_be_hs_dir
* correctly, we can revert to only checking dir_port if router's
* version is too old. */
/* XXX Unfortunately, we need to keep checking dir_port until all
* *clients* suffering from bug 2722 are obsolete. The first version
* to fix the bug was 0.2.2.25-alpha. */
return (router->wants_to_be_hs_dir && router->dir_port &&
uptime > get_options()->MinUptimeHidServDirectoryV2 &&
router->is_running);

View File

@ -378,7 +378,8 @@ configure_accounting(time_t now)
/* We are in the interval we thought we were in. Do nothing.*/
interval_end_time = start_of_accounting_period_after(interval_start_time);
} else {
long duration = length_of_accounting_period_containing(now);
long duration =
length_of_accounting_period_containing(interval_start_time);
double delta = ((double)(s_now - interval_start_time)) / duration;
if (-0.50 <= delta && delta <= 0.50) {
/* The start of the period is now a little later or earlier than we

View File

@ -842,8 +842,17 @@ run_connection_housekeeping(int i, time_t now)
static void
signewnym_impl(time_t now)
{
or_options_t *options = get_options();
if (!proxy_mode(options)) {
log_info(LD_CONTROL, "Ignoring SIGNAL NEWNYM because client functionality "
"is disabled.");
return;
}
circuit_expire_all_dirty_circs();
addressmap_clear_transient();
rend_cache_purge();
rend_client_cancel_descriptor_fetches();
time_of_last_signewnym = now;
signewnym_is_pending = 0;
}

View File

@ -66,6 +66,50 @@ rend_client_send_establish_rendezvous(origin_circuit_t *circ)
return 0;
}
/** Extend the introduction circuit <b>circ</b> to another valid
* introduction point for the hidden service it is trying to connect
* to, or mark it and launch a new circuit if we can't extend it.
* Return 0 on success. Return -1 and mark the introduction
* circuit on failure.
*
* On failure, the caller is responsible for marking the associated
* rendezvous circuit for close. */
static int
rend_client_reextend_intro_circuit(origin_circuit_t *circ)
{
extend_info_t *extend_info;
int result;
extend_info = rend_client_get_random_intro(circ->rend_data);
if (!extend_info) {
log_warn(LD_REND,
"No usable introduction points left for %s. Closing.",
safe_str_client(circ->rend_data->onion_address));
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
return -1;
}
if (circ->remaining_relay_early_cells) {
log_info(LD_REND,
"Re-extending circ %d, this time to %s.",
circ->_base.n_circ_id, extend_info->nickname);
result = circuit_extend_to_new_exit(circ, extend_info);
} else {
log_info(LD_REND,
"Building a new introduction circuit, this time to %s.",
extend_info->nickname);
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_FINISHED);
if (!circuit_launch_by_extend_info(CIRCUIT_PURPOSE_C_INTRODUCING,
extend_info,
CIRCLAUNCH_IS_INTERNAL)) {
log_warn(LD_REND, "Building introduction circuit failed.");
result = -1;
} else {
result = 0;
}
}
extend_info_free(extend_info);
return result;
}
/** Called when we're trying to connect an ap conn; sends an INTRODUCE1 cell
* down introcirc if possible.
*/
@ -91,13 +135,25 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
if (rend_cache_lookup_entry(introcirc->rend_data->onion_address, -1,
&entry) < 1) {
log_warn(LD_REND,
"query %s didn't have valid rend desc in cache. Failing.",
escaped_safe_str_client(introcirc->rend_data->onion_address));
goto err;
log_info(LD_REND,
"query %s didn't have valid rend desc in cache. "
"Refetching descriptor.",
safe_str_client(introcirc->rend_data->onion_address));
rend_client_refetch_v2_renddesc(introcirc->rend_data);
{
connection_t *conn;
while ((conn = connection_get_by_type_state_rendquery(CONN_TYPE_AP,
AP_CONN_STATE_CIRCUIT_WAIT,
introcirc->rend_data->onion_address))) {
conn->state = AP_CONN_STATE_RENDDESC_WAIT;
}
}
return -1;
}
/* first 20 bytes of payload are the hash of the intro key */
/* first 20 bytes of payload are the hash of Bob's pk */
intro_key = NULL;
SMARTLIST_FOREACH(entry->parsed->intro_nodes, rend_intro_point_t *,
intro, {
@ -108,15 +164,22 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
}
});
if (!intro_key) {
log_info(LD_REND, "Our introduction point knowledge changed in "
"mid-connect! Could not find intro key; we only have a "
"v2 rend desc with %d intro points. Giving up.",
log_info(LD_REND, "Could not find intro key for %s at %s; we "
"have a v2 rend desc with %d intro points. "
"Trying a different intro point...",
safe_str_client(introcirc->rend_data->onion_address),
introcirc->build_state->chosen_exit->nickname,
smartlist_len(entry->parsed->intro_nodes));
goto err;
if (rend_client_reextend_intro_circuit(introcirc)) {
goto perm_err;
} else {
return -1;
}
}
if (crypto_pk_get_digest(intro_key, payload)<0) {
log_warn(LD_BUG, "Internal error: couldn't hash public key.");
goto err;
goto perm_err;
}
/* Initialize the pending_final_cpath and start the DH handshake. */
@ -127,11 +190,11 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
cpath->magic = CRYPT_PATH_MAGIC;
if (!(cpath->dh_handshake_state = crypto_dh_new(DH_TYPE_REND))) {
log_warn(LD_BUG, "Internal error: couldn't allocate DH.");
goto err;
goto perm_err;
}
if (crypto_dh_generate_public(cpath->dh_handshake_state)<0) {
log_warn(LD_BUG, "Internal error: couldn't generate g^x.");
goto err;
goto perm_err;
}
}
@ -181,7 +244,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
if (crypto_dh_get_public(cpath->dh_handshake_state, tmp+dh_offset,
DH_KEY_LEN)<0) {
log_warn(LD_BUG, "Internal error: couldn't extract g^x.");
goto err;
goto perm_err;
}
note_crypto_pk_op(REND_CLIENT);
@ -194,7 +257,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
PK_PKCS1_OAEP_PADDING, 0);
if (r<0) {
log_warn(LD_BUG,"Internal error: hybrid pk encrypt failed.");
goto err;
goto perm_err;
}
payload_len = DIGEST_LEN + r;
@ -207,17 +270,18 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
introcirc->cpath->prev)<0) {
/* introcirc is already marked for close. leave rendcirc alone. */
log_warn(LD_BUG, "Couldn't send INTRODUCE1 cell");
return -1;
return -2;
}
/* Now, we wait for an ACK or NAK on this circuit. */
introcirc->_base.purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT;
return 0;
err:
circuit_mark_for_close(TO_CIRCUIT(introcirc), END_CIRC_REASON_INTERNAL);
perm_err:
if (!introcirc->_base.marked_for_close)
circuit_mark_for_close(TO_CIRCUIT(introcirc), END_CIRC_REASON_INTERNAL);
circuit_mark_for_close(TO_CIRCUIT(rendcirc), END_CIRC_REASON_INTERNAL);
return -1;
return -2;
}
/** Called when a rendezvous circuit is open; sends a establish
@ -278,45 +342,16 @@ rend_client_introduction_acked(origin_circuit_t *circ,
* points. If any remain, extend to a new one and try again.
* If none remain, refetch the service descriptor.
*/
log_info(LD_REND, "Got nack for %s from %s...",
safe_str_client(circ->rend_data->onion_address),
circ->build_state->chosen_exit->nickname);
if (rend_client_remove_intro_point(circ->build_state->chosen_exit,
circ->rend_data) > 0) {
/* There are introduction points left. Re-extend the circuit to
* another intro point and try again. */
extend_info_t *extend_info;
int result;
extend_info = rend_client_get_random_intro(circ->rend_data);
if (!extend_info) {
log_warn(LD_REND, "No introduction points left for %s. Closing.",
escaped_safe_str_client(circ->rend_data->onion_address));
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
return -1;
}
if (circ->remaining_relay_early_cells) {
log_info(LD_REND,
"Got nack for %s from %s. Re-extending circ %d, "
"this time to %s.",
escaped_safe_str_client(circ->rend_data->onion_address),
circ->build_state->chosen_exit->nickname,
circ->_base.n_circ_id, extend_info->nickname);
result = circuit_extend_to_new_exit(circ, extend_info);
} else {
log_info(LD_REND,
"Got nack for %s from %s. Building a new introduction "
"circuit, this time to %s.",
escaped_safe_str_client(circ->rend_data->onion_address),
circ->build_state->chosen_exit->nickname,
extend_info->nickname);
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_FINISHED);
if (!circuit_launch_by_extend_info(CIRCUIT_PURPOSE_C_INTRODUCING,
extend_info,
CIRCLAUNCH_IS_INTERNAL)) {
log_warn(LD_REND, "Building introduction circuit failed.");
result = -1;
} else {
result = 0;
}
}
extend_info_free(extend_info);
int result = rend_client_reextend_intro_circuit(circ);
/* XXXX If that call failed, should we close the rend circuit,
* too? */
return result;
}
}
@ -526,8 +561,44 @@ rend_client_refetch_v2_renddesc(const rend_data_t *rend_query)
return;
}
/** Cancel all rendezvous descriptor fetches currently in progress.
*/
void
rend_client_cancel_descriptor_fetches(void)
{
smartlist_t *connection_array = get_connection_array();
SMARTLIST_FOREACH_BEGIN(connection_array, connection_t *, conn) {
if (conn->type == CONN_TYPE_DIR &&
(conn->purpose == DIR_PURPOSE_FETCH_RENDDESC ||
conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2)) {
/* It's a rendezvous descriptor fetch in progress -- cancel it
* by marking the connection for close.
*
* Even if this connection has already reached EOF, this is
* enough to make sure that if the descriptor hasn't been
* processed yet, it won't be. See the end of
* connection_handle_read; connection_reached_eof (indirectly)
* processes whatever response the connection received. */
const rend_data_t *rd = (TO_DIR_CONN(conn))->rend_data;
if (!rd) {
log_warn(LD_BUG | LD_REND,
"Marking for close dir conn fetching rendezvous "
"descriptor for unknown service!");
} else {
log_debug(LD_REND, "Marking for close dir conn fetching "
"rendezvous descriptor for service %s",
safe_str(rd->onion_address));
}
connection_mark_for_close(conn);
}
} SMARTLIST_FOREACH_END(conn);
}
/** Remove failed_intro from ent. If ent now has no intro points, or
* service is unrecognized, then launch a new renddesc fetch.
*
* Return -1 if error, 0 if no intro points remain or service
* unrecognized, 1 if recognized and some intro points remain.

View File

@ -18,6 +18,7 @@ int rend_client_introduction_acked(origin_circuit_t *circ,
const uint8_t *request,
size_t request_len);
void rend_client_refetch_v2_renddesc(const rend_data_t *rend_query);
void rend_client_cancel_descriptor_fetches(void);
int rend_client_remove_intro_point(extend_info_t *failed_intro,
const rend_data_t *rend_query);
int rend_client_rendezvous_acked(origin_circuit_t *circ,

View File

@ -834,6 +834,16 @@ rend_cache_clean(void)
}
}
/** Remove ALL entries from the rendezvous service descriptor cache.
*/
void
rend_cache_purge(void)
{
if (rend_cache)
strmap_free(rend_cache, _rend_cache_entry_free);
rend_cache = strmap_new();
}
/** Remove all old v2 descriptors and those for which this hidden service
* directory is not responsible for any more. */
void

View File

@ -36,6 +36,7 @@ void rend_intro_point_free(rend_intro_point_t *intro);
void rend_cache_init(void);
void rend_cache_clean(void);
void rend_cache_clean_v2_descs_as_dir(void);
void rend_cache_purge(void);
void rend_cache_free_all(void);
int rend_valid_service_id(const char *query);
int rend_cache_lookup_desc(const char *query, int version, const char **desc,

View File

@ -1525,10 +1525,15 @@ rep_hist_get_bandwidth_lines(void)
size_t len;
/* opt [dirreq-](read|write)-history yyyy-mm-dd HH:MM:SS (n s) n,n,n... */
len = (67+21*NUM_TOTALS)*4;
/* The n,n,n part above. Largest representation of a uint64_t is 20 chars
* long, plus the comma. */
#define MAX_HIST_VALUE_LEN 21*NUM_TOTALS
len = (67+MAX_HIST_VALUE_LEN)*4;
buf = tor_malloc_zero(len);
cp = buf;
for (r=0;r<4;++r) {
char tmp[MAX_HIST_VALUE_LEN];
size_t slen;
switch (r) {
case 0:
b = write_array;
@ -1548,11 +1553,16 @@ rep_hist_get_bandwidth_lines(void)
break;
}
tor_assert(b);
slen = rep_hist_fill_bandwidth_history(tmp, MAX_HIST_VALUE_LEN, b);
/* If we don't have anything to write, skip to the next entry. */
if (slen == 0)
continue;
format_iso_time(t, b->next_period-NUM_SECS_BW_SUM_INTERVAL);
tor_snprintf(cp, len-(cp-buf), "%s %s (%d s) ",
desc, t, NUM_SECS_BW_SUM_INTERVAL);
cp += strlen(cp);
cp += rep_hist_fill_bandwidth_history(cp, len-(cp-buf), b);
strlcat(cp, tmp, len-(cp-buf));
cp += slen;
strlcat(cp, "\n", len-(cp-buf));
++cp;
}

View File

@ -1107,10 +1107,10 @@ set_server_advertised(int s)
int
proxy_mode(or_options_t *options)
{
return (options->SocksPort != 0 || options->SocksListenAddress ||
options->TransPort != 0 || options->TransListenAddress ||
options->NATDPort != 0 || options->NATDListenAddress ||
options->DNSPort != 0 || options->DNSListenAddress);
return (options->SocksPort != 0 ||
options->TransPort != 0 ||
options->NATDPort != 0 ||
options->DNSPort != 0);
}
/** Decide if we're a publishable server. We are a publishable server if:

View File

@ -5727,7 +5727,6 @@ hid_serv_get_responsible_directories(smartlist_t *responsible_dirs,
{
int start, found, n_added = 0, i;
networkstatus_t *c = networkstatus_get_latest_consensus();
int use_begindir = get_options()->TunnelDirConns;
if (!c || !smartlist_len(c->routerstatus_list)) {
log_warn(LD_REND, "We don't have a consensus, so we can't perform v2 "
"rendezvous operations.");
@ -5740,14 +5739,9 @@ hid_serv_get_responsible_directories(smartlist_t *responsible_dirs,
do {
routerstatus_t *r = smartlist_get(c->routerstatus_list, i);
if (r->is_hs_dir) {
if (r->dir_port || use_begindir)
smartlist_add(responsible_dirs, r);
else
log_info(LD_REND, "Not adding router '%s' to list of responsible "
"hidden service directories, because we have no way of "
"reaching it.", r->nickname);
smartlist_add(responsible_dirs, r);
if (++n_added == REND_NUMBER_OF_CONSECUTIVE_REPLICAS)
break;
return 0;
}
if (++i == smartlist_len(c->routerstatus_list))
i = 0;