Merge remote-tracking branch 'origin/maint-0.2.2' into release-0.2.2
This commit is contained in:
commit
68a169ec55
|
@ -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.
|
|
@ -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.
|
||||
|
||||
|
|
@ -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.
|
|
@ -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.
|
||||
|
|
@ -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.
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue