mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-09-20 04:56:21 +02:00
Merge remote-tracking branch 'origin/maint-0.2.3' into release-0.2.3
This commit is contained in:
commit
43836f6f0a
6
changes/bug10849_023
Normal file
6
changes/bug10849_023
Normal file
@ -0,0 +1,6 @@
|
||||
o Major bugfixes:
|
||||
- When running a hidden service, do not allow TunneledDirConns 0;
|
||||
this will keep the hidden service from running, and also
|
||||
make it publish its descriptors directly over HTTP. Fixes bug 10849;
|
||||
bugfix on 0.2.1.1-alpha.
|
||||
|
5
changes/bug11464_023
Normal file
5
changes/bug11464_023
Normal file
@ -0,0 +1,5 @@
|
||||
o Major features (security):
|
||||
- Block authority signing keys that were used on an authorities
|
||||
vulnerable to the "heartbleed" bug in openssl (CVE-2014-0160).
|
||||
(We don't have any evidence that these keys _were_ compromised;
|
||||
we're doing this to be prudent.) Resolves ticket 11464.
|
3
changes/bug11519
Normal file
3
changes/bug11519
Normal file
@ -0,0 +1,3 @@
|
||||
o Minor bugfixes:
|
||||
- Avoid sending an garbage value to the controller when a circuit is
|
||||
cannibalized. Fixes bug 11519; bugfix on 0.2.3.11-alpha.
|
3
changes/bug13100
Normal file
3
changes/bug13100
Normal file
@ -0,0 +1,3 @@
|
||||
o Directory authority changes:
|
||||
- Change IP address for gabelmoo (v3 directory authority).
|
||||
|
5
changes/bug5650
Normal file
5
changes/bug5650
Normal file
@ -0,0 +1,5 @@
|
||||
o Major bugfixes:
|
||||
- Avoid a bug where our response to TLS renegotation under certain
|
||||
network conditions could lead to a busy-loop, with 100% CPU
|
||||
consumption. Fixes bug 5650; bugfix on 0.2.0.16-alpha.
|
||||
|
4
changes/bug6979
Normal file
4
changes/bug6979
Normal file
@ -0,0 +1,4 @@
|
||||
o Minor bugfixes:
|
||||
- Fix an assertion failure that would occur when disabling the
|
||||
ORPort setting on a running Tor process while accounting was
|
||||
enabled. Fixes bug 6979; bugfix on 0.2.2.18-alpha.
|
6
changes/bug7164_downgrade
Normal file
6
changes/bug7164_downgrade
Normal file
@ -0,0 +1,6 @@
|
||||
o Minor bugfixes:
|
||||
- Downgrade the warning severity for the the "md was still referenced 1
|
||||
node(s)" warning. Tor 0.2.5.4-alpha has better code for trying to
|
||||
diagnose this bug, and the current warning in earlier versions of
|
||||
tor achieves nothing useful. Addresses warning from bug 7164.
|
||||
|
6
changes/bug8844
Normal file
6
changes/bug8844
Normal file
@ -0,0 +1,6 @@
|
||||
o Major bugfixes:
|
||||
- Prevent the get_freelists() function from running off the end of
|
||||
the list of freelists if it somehow gets an unrecognized
|
||||
allocation. Fixes bug 8844; bugfix on 0.2.0.16-alpha. Reported by
|
||||
eugenis.
|
||||
|
4
changes/bug9002
Normal file
4
changes/bug9002
Normal file
@ -0,0 +1,4 @@
|
||||
o Major bugfixes:
|
||||
- Limit hidden service descriptors to at most ten introduction
|
||||
points, to slow one kind of guard enumeration. Fixes bug 9002;
|
||||
bugfix on 0.1.1.11-alpha.
|
6
changes/bug9017
Normal file
6
changes/bug9017
Normal file
@ -0,0 +1,6 @@
|
||||
o Major bugfixes:
|
||||
- Avoid an assertion failure on OpenBSD (and perhaps other BSDs)
|
||||
when an exit connection with optimistic data succeeds immediately
|
||||
rather than returning EINPROGRESS. Fixes bug 9017; bugfix on
|
||||
0.2.3.1-alpha.
|
||||
|
3
changes/bug9063
Normal file
3
changes/bug9063
Normal file
@ -0,0 +1,3 @@
|
||||
o Normal bugfixes:
|
||||
- Close any circuit that has more cells queued than the spec permits.
|
||||
Fixes bug #9063; bugfix on 0.2.3.25.
|
15
changes/bug9063_redux
Normal file
15
changes/bug9063_redux
Normal file
@ -0,0 +1,15 @@
|
||||
o Major bugfixes:
|
||||
- When we have too much memory queued in circuits (according to a new
|
||||
MaxMemInCellQueues option), close the circuits consuming the most
|
||||
memory. This prevents us from running out of memory as a relay if
|
||||
circuits fill up faster than they can be drained. Fixes
|
||||
bug 9063; bugfix on the 54th commit of Tor. This bug is a further
|
||||
fix beyond bug 6252, whose fix was merged into 0.2.3.21-rc.
|
||||
|
||||
Also fixes an earlier approach taken in 0.2.4.13-alpha, where we
|
||||
tried to solve this issue simply by imposing an upper limit on the
|
||||
number of queued cells for a single circuit. That approach proved to
|
||||
be problematic, since there are ways to provoke clients to send a
|
||||
number of cells in excess of any such reasonable limit.
|
||||
Fixes bug 9072; bugfix on 0.2.4.13-alpha.
|
||||
|
3
changes/bug9072
Normal file
3
changes/bug9072
Normal file
@ -0,0 +1,3 @@
|
||||
o Critical bugfixes:
|
||||
- Disable middle relay queue overfill detection code due to possible
|
||||
guard discovery attack, pending further analysis. Fixes bug #9072.
|
7
changes/bug9093
Normal file
7
changes/bug9093
Normal file
@ -0,0 +1,7 @@
|
||||
o Minor features:
|
||||
- Improve the circuit queue out-of-memory handler. Previously, when
|
||||
we ran low on memory, we'd close whichever circuits had the most
|
||||
queued cells. Now, we close those that have the *oldest* queued
|
||||
cells, on the theory that those are most responsible for us
|
||||
running low on memory. Based on analysis from a forthcoming paper
|
||||
by Jansen, Tschorsch, Johnson, and Scheuermann. Fixes bug 9093.
|
11
changes/bug9546
Normal file
11
changes/bug9546
Normal file
@ -0,0 +1,11 @@
|
||||
o Major bugfixes:
|
||||
|
||||
- When a relay is extending a circuit to a bridge, it needs to send a
|
||||
NETINFO cell, even when the bridge hasn't sent an AUTH_CHALLENGE
|
||||
cell. Fixes bug 9546; bugfix on 0.2.3.6-alpha.
|
||||
|
||||
- Bridges send AUTH_CHALLENGE cells during their handshakes; previously
|
||||
they did not, which prevented relays from successfully connecting
|
||||
to a bridge for self-test or bandwidth testing. Fixes bug 9546;
|
||||
bugfix on 0.2.3.6-alpha.
|
||||
|
5
changes/bug9564
Normal file
5
changes/bug9564
Normal file
@ -0,0 +1,5 @@
|
||||
o Minor bugfixes:
|
||||
- If the time to download the next old-style networkstatus is in
|
||||
the future, do not decline to consider whether to download the
|
||||
next microdescriptor networkstatus. Fixes bug 9564. Bugfix on
|
||||
0.2.3.14-alpha.
|
5
changes/bug9671_023
Normal file
5
changes/bug9671_023
Normal file
@ -0,0 +1,5 @@
|
||||
o Major bugfixes:
|
||||
- If the circuit build timeout logic is disabled (via the consensus,
|
||||
or because we are an authority), then don't build testing circuits.
|
||||
Fixes bug 9657; bugfix on 0.2.2.14-alpha.
|
||||
|
6
changes/bug9928
Normal file
6
changes/bug9928
Normal file
@ -0,0 +1,6 @@
|
||||
o Minor bugfixes:
|
||||
- Avoid an off-by-one error when checking buffer boundaries when
|
||||
formatting the exit status of a pluggable transport helper.
|
||||
This is probably not an exploitable bug, but better safe than
|
||||
sorry. Fixes bug 9928; bugfix on 0.2.3.18-rc. Bug found by
|
||||
Pedro Ribeiro.
|
4
changes/disable_sslv3
Normal file
4
changes/disable_sslv3
Normal file
@ -0,0 +1,4 @@
|
||||
o Major security fixes:
|
||||
- Disable support for SSLv3. All versions of OpenSSL in use with
|
||||
Tor today support TLS 1.0 or later, so we can safely turn off
|
||||
support for this old (and insecure) protocol. Fixes bug 13426.
|
3
changes/geoip-august2013
Normal file
3
changes/geoip-august2013
Normal file
@ -0,0 +1,3 @@
|
||||
o Minor features:
|
||||
- Update to the August 7 2013 Maxmind GeoLite Country database.
|
||||
|
3
changes/geoip-august2014
Normal file
3
changes/geoip-august2014
Normal file
@ -0,0 +1,3 @@
|
||||
o Minor features:
|
||||
- Update geoip to the August 7 2014 Maxmind GeoLite2 Country database.
|
||||
|
3
changes/geoip-february2014
Normal file
3
changes/geoip-february2014
Normal file
@ -0,0 +1,3 @@
|
||||
o Minor features:
|
||||
- Update to the February 7 2014 Maxmind GeoLite2 Country database.
|
||||
|
3
changes/geoip-february2014-regcountry
Normal file
3
changes/geoip-february2014-regcountry
Normal file
@ -0,0 +1,3 @@
|
||||
o Minor features:
|
||||
- Fix our version of the February 7 2014 Maxmind GeoLite2 Country database.
|
||||
|
3
changes/geoip-july2013
Normal file
3
changes/geoip-july2013
Normal file
@ -0,0 +1,3 @@
|
||||
o Minor features:
|
||||
- Update to the July 3 2013 Maxmind GeoLite Country database.
|
||||
|
3
changes/geoip-july2014
Normal file
3
changes/geoip-july2014
Normal file
@ -0,0 +1,3 @@
|
||||
o Minor features:
|
||||
- Update geoip to the July 10 2014 Maxmind GeoLite2 Country database.
|
||||
|
3
changes/geoip-june2013
Normal file
3
changes/geoip-june2013
Normal file
@ -0,0 +1,3 @@
|
||||
o Minor features:
|
||||
- Update to the June 5 2013 Maxmind GeoLite Country database.
|
||||
|
3
changes/geoip-may2013
Normal file
3
changes/geoip-may2013
Normal file
@ -0,0 +1,3 @@
|
||||
o Minor features:
|
||||
- Update to the May 9 2013 Maxmind GeoLite Country database.
|
||||
|
3
changes/geoip-october2013
Normal file
3
changes/geoip-october2013
Normal file
@ -0,0 +1,3 @@
|
||||
o Minor features:
|
||||
- Update to the October 2 2013 Maxmind GeoLite Country database.
|
||||
|
3
changes/geoip-september2013
Normal file
3
changes/geoip-september2013
Normal file
@ -0,0 +1,3 @@
|
||||
o Minor features:
|
||||
- Update to the September 4 2013 Maxmind GeoLite Country database.
|
||||
|
5
changes/md_leak_bug
Normal file
5
changes/md_leak_bug
Normal file
@ -0,0 +1,5 @@
|
||||
o Major bugfixes (security, OOM)
|
||||
- Fix a memory leak that could occur if a microdescriptor parse
|
||||
fails during the tokenizing step. This could enable a memory
|
||||
exhaustion attack by directory servers. Fixes bug #11649; bugfix
|
||||
on 0.2.2.6-alpha.
|
@ -1475,6 +1475,15 @@ is non-zero):
|
||||
localhost, RFC1918 addresses, and so on. This can create security issues;
|
||||
you should probably leave it off. (Default: 0)
|
||||
|
||||
**MaxMemInCellQueues** __N__ **bytes**|**KB**|**MB**|**GB**::
|
||||
This option configures a threshold above which Tor will assume that it
|
||||
needs to stop queueing cells because it's about to run out of memory.
|
||||
If it hits this threshold, it will begin killing circuits until it
|
||||
has recovered at least 10% of this memory. Do not set this option too
|
||||
low, or your relay may be unreliable under load. This option only
|
||||
effects circuit queues, so the actual process size will be larger than
|
||||
this. (Default: 8GB)
|
||||
|
||||
DIRECTORY SERVER OPTIONS
|
||||
------------------------
|
||||
|
||||
|
@ -22,6 +22,8 @@ void mp_pool_destroy(mp_pool_t *pool);
|
||||
void mp_pool_assert_ok(mp_pool_t *pool);
|
||||
void mp_pool_log_status(mp_pool_t *pool, int severity);
|
||||
|
||||
#define MP_POOL_ITEM_OVERHEAD (sizeof(void*))
|
||||
|
||||
#define MEMPOOL_STATS
|
||||
|
||||
#ifdef MEMPOOL_PRIVATE
|
||||
|
@ -1176,10 +1176,11 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime,
|
||||
goto error;
|
||||
#endif
|
||||
|
||||
/* Tell OpenSSL to use SSL3 or TLS1 but not SSL2. */
|
||||
/* Tell OpenSSL to use TLS 1.0 or later but not SSL2 or SSL3. */
|
||||
if (!(result->ctx = SSL_CTX_new(SSLv23_method())))
|
||||
goto error;
|
||||
SSL_CTX_set_options(result->ctx, SSL_OP_NO_SSLv2);
|
||||
SSL_CTX_set_options(result->ctx, SSL_OP_NO_SSLv3);
|
||||
|
||||
/* Disable TLS1.1 and TLS1.2 if they exist. We need to do this to
|
||||
* workaround a bug present in all OpenSSL 1.0.1 versions (as of 1
|
||||
@ -1204,6 +1205,7 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime,
|
||||
SSL_CTX_set_options(result->ctx, SSL_OP_NO_TICKET);
|
||||
#endif
|
||||
|
||||
/* XXX This block is now obsolete. */
|
||||
if (
|
||||
#ifdef DISABLE_SSL3_HANDSHAKE
|
||||
1 ||
|
||||
|
@ -3256,10 +3256,10 @@ format_hex_number_for_helper_exit_status(unsigned int x, char *buf,
|
||||
* <b>hex_errno</b>. Called between fork and _exit, so must be signal-handler
|
||||
* safe.
|
||||
*
|
||||
* <b>hex_errno</b> must have at least HEX_ERRNO_SIZE bytes available.
|
||||
* <b>hex_errno</b> must have at least HEX_ERRNO_SIZE+1 bytes available.
|
||||
*
|
||||
* The format of <b>hex_errno</b> is: "CHILD_STATE/ERRNO\n", left-padded
|
||||
* with spaces. Note that there is no trailing \0. CHILD_STATE indicates where
|
||||
* with spaces. CHILD_STATE indicates where
|
||||
* in the processs of starting the child process did the failure occur (see
|
||||
* CHILD_STATE_* macros for definition), and SAVED_ERRNO is the value of
|
||||
* errno when the failure occurred.
|
||||
@ -3294,7 +3294,7 @@ format_helper_exit_status(unsigned char child_state, int saved_errno,
|
||||
* Count how many chars of space we have left, and keep a pointer into the
|
||||
* current point in the buffer.
|
||||
*/
|
||||
left = HEX_ERRNO_SIZE;
|
||||
left = HEX_ERRNO_SIZE+1;
|
||||
cur = hex_errno;
|
||||
|
||||
/* Emit child_state */
|
||||
@ -3338,8 +3338,8 @@ format_helper_exit_status(unsigned char child_state, int saved_errno,
|
||||
left -= written;
|
||||
cur += written;
|
||||
|
||||
/* Check that we have enough space left for a newline */
|
||||
if (left <= 0)
|
||||
/* Check that we have enough space left for a newline and a NUL */
|
||||
if (left <= 1)
|
||||
goto err;
|
||||
|
||||
/* Emit the newline and NUL */
|
||||
@ -3594,7 +3594,7 @@ tor_spawn_background(const char *const filename, const char **argv,
|
||||
this is used for printing out the error message */
|
||||
unsigned char child_state = CHILD_STATE_INIT;
|
||||
|
||||
char hex_errno[HEX_ERRNO_SIZE];
|
||||
char hex_errno[HEX_ERRNO_SIZE + 2]; /* + 1 should be sufficient actually */
|
||||
|
||||
static int max_fd = -1;
|
||||
|
||||
|
134839
src/config/geoip
134839
src/config/geoip
File diff suppressed because it is too large
Load Diff
@ -147,7 +147,8 @@ static INLINE chunk_freelist_t *
|
||||
get_freelist(size_t alloc)
|
||||
{
|
||||
int i;
|
||||
for (i=0; freelists[i].alloc_size <= alloc; ++i) {
|
||||
for (i=0; (freelists[i].alloc_size <= alloc &&
|
||||
freelists[i].alloc_size); ++i ) {
|
||||
if (freelists[i].alloc_size == alloc) {
|
||||
return &freelists[i];
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ static void pathbias_count_success(origin_circuit_t *circ);
|
||||
* 3. If we are a directory authority
|
||||
* 4. If we fail to write circuit build time history to our state file.
|
||||
*/
|
||||
static int
|
||||
int
|
||||
circuit_build_times_disabled(void)
|
||||
{
|
||||
if (unit_tests) {
|
||||
|
@ -32,6 +32,7 @@ char *circuit_list_path_for_controller(origin_circuit_t *circ);
|
||||
void circuit_log_path(int severity, unsigned int domain,
|
||||
origin_circuit_t *circ);
|
||||
void circuit_rep_hist_note_result(origin_circuit_t *circ);
|
||||
int circuit_build_times_disabled(void);
|
||||
origin_circuit_t *origin_circuit_init(uint8_t purpose, int flags);
|
||||
origin_circuit_t *circuit_establish_circuit(uint8_t purpose,
|
||||
extend_info_t *exit,
|
||||
|
@ -1359,6 +1359,144 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line,
|
||||
}
|
||||
}
|
||||
|
||||
/** Given a marked circuit <b>circ</b>, aggressively free its cell queues to
|
||||
* recover memory. */
|
||||
static void
|
||||
marked_circuit_free_cells(circuit_t *circ)
|
||||
{
|
||||
if (!circ->marked_for_close) {
|
||||
log_warn(LD_BUG, "Called on non-marked circuit");
|
||||
return;
|
||||
}
|
||||
cell_queue_clear(&circ->n_conn_cells);
|
||||
if (! CIRCUIT_IS_ORIGIN(circ))
|
||||
cell_queue_clear(& TO_OR_CIRCUIT(circ)->p_conn_cells);
|
||||
}
|
||||
|
||||
/** Return the number of cells used by the circuit <b>c</b>'s cell queues. */
|
||||
static size_t
|
||||
n_cells_in_circ_queues(const circuit_t *c)
|
||||
{
|
||||
size_t n = c->n_conn_cells.n;
|
||||
if (! CIRCUIT_IS_ORIGIN(c))
|
||||
n += TO_OR_CIRCUIT((circuit_t*)c)->p_conn_cells.n;
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the age of the oldest cell queued on <b>c</b>, in milliseconds.
|
||||
* Return 0 if there are no cells queued on c. Requires that <b>now</b> be
|
||||
* the current time in milliseconds since the epoch, truncated.
|
||||
*
|
||||
* This function will return incorrect results if the oldest cell queued on
|
||||
* the circuit is older than 2**32 msec (about 49 days) old.
|
||||
*/
|
||||
static uint32_t
|
||||
circuit_max_queued_cell_age(const circuit_t *c, uint32_t now)
|
||||
{
|
||||
uint32_t age = 0;
|
||||
if (c->n_conn_cells.head)
|
||||
age = now - c->n_conn_cells.head->inserted_time;
|
||||
|
||||
if (! CIRCUIT_IS_ORIGIN(c)) {
|
||||
const or_circuit_t *orcirc = TO_OR_CIRCUIT((circuit_t*)c);
|
||||
if (orcirc->p_conn_cells.head) {
|
||||
uint32_t age2 = now - orcirc->p_conn_cells.head->inserted_time;
|
||||
if (age2 > age)
|
||||
return age2;
|
||||
}
|
||||
}
|
||||
return age;
|
||||
}
|
||||
|
||||
/** Temporary variable for circuits_compare_by_oldest_queued_cell_ This is a
|
||||
* kludge to work around the fact that qsort doesn't provide a way for
|
||||
* comparison functions to take an extra argument. */
|
||||
static uint32_t circcomp_now_tmp;
|
||||
|
||||
/** Helper to sort a list of circuit_t by age of oldest cell, in descending
|
||||
* order. Requires that circcomp_now_tmp is set correctly. */
|
||||
static int
|
||||
circuits_compare_by_oldest_queued_cell_(const void **a_, const void **b_)
|
||||
{
|
||||
const circuit_t *a = *a_;
|
||||
const circuit_t *b = *b_;
|
||||
uint32_t age_a = circuit_max_queued_cell_age(a, circcomp_now_tmp);
|
||||
uint32_t age_b = circuit_max_queued_cell_age(b, circcomp_now_tmp);
|
||||
|
||||
if (age_a < age_b)
|
||||
return 1;
|
||||
else if (age_a == age_b)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define FRACTION_OF_CELLS_TO_RETAIN_ON_OOM 0.90
|
||||
|
||||
/** We're out of memory for cells, having allocated <b>current_allocation</b>
|
||||
* bytes' worth. Kill the 'worst' circuits until we're under
|
||||
* FRACTION_OF_CIRCS_TO_RETAIN_ON_OOM of our maximum usage. */
|
||||
void
|
||||
circuits_handle_oom(size_t current_allocation)
|
||||
{
|
||||
/* Let's hope there's enough slack space for this allocation here... */
|
||||
smartlist_t *circlist = smartlist_new();
|
||||
circuit_t *circ;
|
||||
size_t n_cells_removed=0, n_cells_to_remove;
|
||||
int n_circuits_killed=0;
|
||||
struct timeval now;
|
||||
log_notice(LD_GENERAL, "We're low on memory. Killing circuits with "
|
||||
"over-long queues. (This behavior is controlled by "
|
||||
"MaxMemInCellQueues.)");
|
||||
|
||||
{
|
||||
size_t mem_target = (size_t)(get_options()->MaxMemInCellQueues *
|
||||
FRACTION_OF_CELLS_TO_RETAIN_ON_OOM);
|
||||
size_t mem_to_recover;
|
||||
if (current_allocation <= mem_target)
|
||||
return;
|
||||
mem_to_recover = current_allocation - mem_target;
|
||||
n_cells_to_remove = CEIL_DIV(mem_to_recover, packed_cell_mem_cost());
|
||||
}
|
||||
|
||||
/* This algorithm itself assumes that you've got enough memory slack
|
||||
* to actually run it. */
|
||||
for (circ = global_circuitlist; circ; circ = circ->next)
|
||||
smartlist_add(circlist, circ);
|
||||
|
||||
/* Set circcomp_now_tmp so that the sort can work. */
|
||||
tor_gettimeofday_cached(&now);
|
||||
circcomp_now_tmp = (uint32_t)tv_to_msec(&now);
|
||||
|
||||
/* This is O(n log n); there are faster algorithms we could use instead.
|
||||
* Let's hope this doesn't happen enough to be in the critical path. */
|
||||
smartlist_sort(circlist, circuits_compare_by_oldest_queued_cell_);
|
||||
|
||||
/* Okay, now the worst circuits are at the front of the list. Let's mark
|
||||
* them, and reclaim their storage aggressively. */
|
||||
SMARTLIST_FOREACH_BEGIN(circlist, circuit_t *, circ) {
|
||||
size_t n = n_cells_in_circ_queues(circ);
|
||||
if (! circ->marked_for_close) {
|
||||
circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT);
|
||||
}
|
||||
marked_circuit_free_cells(circ);
|
||||
|
||||
++n_circuits_killed;
|
||||
n_cells_removed += n;
|
||||
if (n_cells_removed >= n_cells_to_remove)
|
||||
break;
|
||||
} SMARTLIST_FOREACH_END(circ);
|
||||
|
||||
clean_cell_pool(); /* In case this helps. */
|
||||
|
||||
log_notice(LD_GENERAL, "Removed "U64_FORMAT" bytes by killing %d circuits.",
|
||||
U64_PRINTF_ARG(n_cells_removed * packed_cell_mem_cost()),
|
||||
n_circuits_killed);
|
||||
|
||||
smartlist_free(circlist);
|
||||
}
|
||||
|
||||
/** Verify that cpath layer <b>cp</b> has all of its invariants
|
||||
* correct. Trigger an assert if anything is invalid.
|
||||
*/
|
||||
|
@ -57,6 +57,7 @@ int circuit_count_pending_on_or_conn(or_connection_t *or_conn);
|
||||
void assert_cpath_layer_ok(const crypt_path_t *cp);
|
||||
void assert_circuit_ok(const circuit_t *c);
|
||||
void circuit_free_all(void);
|
||||
void circuits_handle_oom(size_t current_allocation);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -746,7 +746,7 @@ circuit_predict_and_launch_new(void)
|
||||
* want, don't do another -- we want to leave a few slots open so
|
||||
* we can still build circuits preemptively as needed. */
|
||||
if (num < MAX_UNUSED_OPEN_CIRCUITS-2 &&
|
||||
get_options()->LearnCircuitBuildTimeout &&
|
||||
! circuit_build_times_disabled() &&
|
||||
circuit_build_times_needs_circuits_now(&circ_times)) {
|
||||
flags = CIRCLAUNCH_NEED_CAPACITY;
|
||||
log_info(LD_CIRC,
|
||||
@ -882,7 +882,7 @@ circuit_expire_old_circuits_clientside(void)
|
||||
tor_gettimeofday(&now);
|
||||
cutoff = now;
|
||||
|
||||
if (get_options()->LearnCircuitBuildTimeout &&
|
||||
if (! circuit_build_times_disabled() &&
|
||||
circuit_build_times_needs_circuits(&circ_times)) {
|
||||
/* Circuits should be shorter lived if we need more of them
|
||||
* for learning a good build timeout */
|
||||
@ -1310,7 +1310,7 @@ circuit_launch_by_extend_info(uint8_t purpose,
|
||||
circ = circuit_find_to_cannibalize(purpose, extend_info, flags);
|
||||
if (circ) {
|
||||
uint8_t old_purpose = circ->_base.purpose;
|
||||
struct timeval old_timestamp_created;
|
||||
struct timeval old_timestamp_created = circ->_base.timestamp_created;
|
||||
|
||||
log_info(LD_CIRC,"Cannibalizing circ '%s' for purpose %d (%s)",
|
||||
build_state_get_exit_nickname(circ->build_state), purpose,
|
||||
|
@ -755,8 +755,8 @@ command_process_versions_cell(var_cell_t *cell, or_connection_t *conn)
|
||||
const int send_versions = !started_here;
|
||||
/* If we want to authenticate, send a CERTS cell */
|
||||
const int send_certs = !started_here || public_server_mode(get_options());
|
||||
/* If we're a relay that got a connection, ask for authentication. */
|
||||
const int send_chall = !started_here && public_server_mode(get_options());
|
||||
/* If we're a host that got a connection, ask for authentication. */
|
||||
const int send_chall = !started_here;
|
||||
/* If our certs cell will authenticate us, we can send a netinfo cell
|
||||
* right now. */
|
||||
const int send_netinfo = !started_here;
|
||||
@ -941,6 +941,16 @@ command_process_netinfo_cell(cell_t *cell, or_connection_t *conn)
|
||||
* trustworthy. */
|
||||
(void)my_apparent_addr;
|
||||
|
||||
if (! conn->handshake_state->sent_netinfo) {
|
||||
/* If we were prepared to authenticate, but we never got an AUTH_CHALLENGE
|
||||
* cell, then we would not previously have sent a NETINFO cell. Do so
|
||||
* now. */
|
||||
if (connection_or_send_netinfo(conn) < 0) {
|
||||
connection_mark_for_close(TO_CONN(conn));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (connection_or_set_state_open(conn)<0) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_OR, "Got good NETINFO cell from %s:%d; but "
|
||||
"was unable to make the OR connection become open.",
|
||||
|
@ -343,6 +343,7 @@ static config_var_t _option_vars[] = {
|
||||
V(MaxAdvertisedBandwidth, MEMUNIT, "1 GB"),
|
||||
V(MaxCircuitDirtiness, INTERVAL, "10 minutes"),
|
||||
V(MaxClientCircuitsPending, UINT, "32"),
|
||||
V(MaxMemInCellQueues, MEMUNIT, "8 GB"),
|
||||
V(MaxOnionsPending, UINT, "100"),
|
||||
OBSOLETE("MonthlyAccountingStart"),
|
||||
V(MyFamily, STRING, NULL),
|
||||
@ -960,7 +961,7 @@ add_default_trusted_dir_authorities(dirinfo_type_t type)
|
||||
"76.73.17.194:9030 F397 038A DC51 3361 35E7 B80B D99C A384 4360 292B",
|
||||
"gabelmoo orport=443 no-v2 "
|
||||
"v3ident=ED03BB616EB2F60BEC80151114BB25CEF515B226 "
|
||||
"212.112.245.170:80 F204 4413 DAC2 E02E 3D6B CF47 35A1 9BCA 1DE9 7281",
|
||||
"131.188.40.189:80 F204 4413 DAC2 E02E 3D6B CF47 35A1 9BCA 1DE9 7281",
|
||||
"dannenberg orport=443 no-v2 "
|
||||
"v3ident=585769C78764D58426B8B52B6651A5A71137189A "
|
||||
"193.23.244.244:80 7BE6 83E6 5D48 1413 21C5 ED92 F075 C553 64AC 7123",
|
||||
@ -3668,6 +3669,12 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
||||
log_warn(LD_CONFIG, "EntryNodes is set, but UseEntryGuards is disabled. "
|
||||
"EntryNodes will be ignored.");
|
||||
|
||||
if (options->MaxMemInCellQueues < (500 << 20)) {
|
||||
log_warn(LD_CONFIG, "MaxMemInCellQueues must be at least 500 MB for now. "
|
||||
"Ideally, have it as large as you can afford.");
|
||||
options->MaxMemInCellQueues = (500 << 20);
|
||||
}
|
||||
|
||||
options->_AllowInvalid = 0;
|
||||
if (options->AllowInvalidNodes) {
|
||||
SMARTLIST_FOREACH_BEGIN(options->AllowInvalidNodes, const char *, cp) {
|
||||
@ -4042,6 +4049,10 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
||||
REJECT("If you set UseBridges, you must specify at least one bridge.");
|
||||
if (options->UseBridges && !options->TunnelDirConns)
|
||||
REJECT("If you set UseBridges, you must set TunnelDirConns.");
|
||||
if (options->RendConfigLines &&
|
||||
(!options->TunnelDirConns || !options->PreferTunneledDirConns))
|
||||
REJECT("If you are running a hidden service, you must set TunnelDirConns "
|
||||
"and PreferTunneledDirConns");
|
||||
|
||||
for (cl = options->Bridges; cl; cl = cl->next) {
|
||||
if (parse_bridge_line(cl->value, 1)<0)
|
||||
|
@ -2825,7 +2825,20 @@ connection_read_to_buf(connection_t *conn, ssize_t *max_to_read,
|
||||
case TOR_TLS_WANTWRITE:
|
||||
connection_start_writing(conn);
|
||||
return 0;
|
||||
case TOR_TLS_WANTREAD: /* we're already reading */
|
||||
case TOR_TLS_WANTREAD:
|
||||
if (conn->in_connection_handle_write) {
|
||||
/* We've been invoked from connection_handle_write, because we're
|
||||
* waiting for a TLS renegotiation, the renegotiation started, and
|
||||
* SSL_read returned WANTWRITE. But now SSL_read is saying WANTREAD
|
||||
* again. Stop waiting for write events now, or else we'll
|
||||
* busy-loop until data arrives for us to read. */
|
||||
connection_stop_writing(conn);
|
||||
if (!connection_is_reading(conn))
|
||||
connection_start_reading(conn);
|
||||
}
|
||||
/* we're already reading, one hopes */
|
||||
result = 0;
|
||||
break;
|
||||
case TOR_TLS_DONE: /* no data read, so nothing to process */
|
||||
result = 0;
|
||||
break; /* so we call bucket_decrement below */
|
||||
@ -3337,7 +3350,9 @@ connection_handle_write(connection_t *conn, int force)
|
||||
{
|
||||
int res;
|
||||
tor_gettimeofday_cache_clear();
|
||||
conn->in_connection_handle_write = 1;
|
||||
res = connection_handle_write_impl(conn, force);
|
||||
conn->in_connection_handle_write = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -3302,12 +3302,13 @@ connection_exit_connect(edge_connection_t *edge_conn)
|
||||
|
||||
conn->state = EXIT_CONN_STATE_OPEN;
|
||||
if (connection_get_outbuf_len(conn)) {
|
||||
/* in case there are any queued data cells */
|
||||
log_warn(LD_BUG,"newly connected conn had data waiting!");
|
||||
// connection_start_writing(conn);
|
||||
}
|
||||
/* in case there are any queued data cells, from e.g. optimistic data */
|
||||
IF_HAS_NO_BUFFEREVENT(conn)
|
||||
connection_watch_events(conn, READ_EVENT|WRITE_EVENT);
|
||||
} else {
|
||||
IF_HAS_NO_BUFFEREVENT(conn)
|
||||
connection_watch_events(conn, READ_EVENT);
|
||||
}
|
||||
|
||||
/* also, deliver a 'connected' cell back through the circuit. */
|
||||
if (connection_edge_is_rendezvous_stream(edge_conn)) {
|
||||
|
@ -1975,6 +1975,12 @@ connection_or_send_netinfo(or_connection_t *conn)
|
||||
|
||||
tor_assert(conn->handshake_state);
|
||||
|
||||
if (conn->handshake_state->sent_netinfo) {
|
||||
log_warn(LD_BUG, "Attempted to send an extra netinfo cell on a connection "
|
||||
"where we already sent one.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(&cell, 0, sizeof(cell_t));
|
||||
cell.command = CELL_NETINFO;
|
||||
|
||||
@ -2009,6 +2015,7 @@ connection_or_send_netinfo(or_connection_t *conn)
|
||||
}
|
||||
|
||||
conn->handshake_state->digest_sent_data = 0;
|
||||
conn->handshake_state->sent_netinfo = 1;
|
||||
connection_or_write_cell_to_buf(&cell, conn);
|
||||
|
||||
return 0;
|
||||
@ -2137,7 +2144,7 @@ connection_or_compute_authenticate_cell_body(or_connection_t *conn,
|
||||
const tor_cert_t *id_cert=NULL, *link_cert=NULL;
|
||||
const digests_t *my_digests, *their_digests;
|
||||
const uint8_t *my_id, *their_id, *client_id, *server_id;
|
||||
if (tor_tls_get_my_certs(0, &link_cert, &id_cert))
|
||||
if (tor_tls_get_my_certs(server, &link_cert, &id_cert))
|
||||
return -1;
|
||||
my_digests = tor_cert_get_id_digests(id_cert);
|
||||
their_digests = tor_cert_get_id_digests(conn->handshake_state->id_cert);
|
||||
|
@ -561,7 +561,7 @@ microdesc_free(microdesc_t *md)
|
||||
}
|
||||
});
|
||||
if (found) {
|
||||
log_warn(LD_BUG, "microdesc_free() called, but md was still referenced "
|
||||
log_info(LD_BUG, "microdesc_free() called, but md was still referenced "
|
||||
"%d node(s); held_by_nodes == %u", found, md->held_by_nodes);
|
||||
} else {
|
||||
log_warn(LD_BUG, "microdesc_free() called with held_by_nodes set to %u, "
|
||||
|
@ -453,6 +453,17 @@ networkstatus_check_document_signature(const networkstatus_t *consensus,
|
||||
DIGEST_LEN))
|
||||
return -1;
|
||||
|
||||
if (authority_cert_is_blacklisted(cert)) {
|
||||
/* We implement blacklisting for authority signing keys by treating
|
||||
* all their signatures as always bad. That way we don't get into
|
||||
* crazy loops of dropping and re-fetching signatures. */
|
||||
log_warn(LD_DIR, "Ignoring a consensus signature made with deprecated"
|
||||
" signing key %s",
|
||||
hex_str(cert->signing_key_digest, DIGEST_LEN));
|
||||
sig->bad_signature = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
signed_digest_len = crypto_pk_keysize(cert->signing_key);
|
||||
signed_digest = tor_malloc(signed_digest_len);
|
||||
if (crypto_pk_public_checksig(cert->signing_key,
|
||||
@ -1239,7 +1250,7 @@ update_consensus_networkstatus_downloads(time_t now)
|
||||
}
|
||||
|
||||
if (time_to_download_next_consensus[i] > now)
|
||||
return; /* Wait until the current consensus is older. */
|
||||
continue; /* Wait until the current consensus is older. */
|
||||
|
||||
resource = networkstatus_get_flavor_name(i);
|
||||
|
||||
|
24
src/or/or.h
24
src/or/or.h
@ -539,6 +539,8 @@ typedef enum {
|
||||
#define CIRCUIT_PURPOSE_IS_ESTABLISHED_REND(p) \
|
||||
((p) == CIRCUIT_PURPOSE_C_REND_JOINED || \
|
||||
(p) == CIRCUIT_PURPOSE_S_REND_JOINED)
|
||||
/** True iff the circuit_t c is actually an or_circuit_t */
|
||||
#define CIRCUIT_IS_ORCIRC(c) (((circuit_t *)(c))->magic == OR_CIRCUIT_MAGIC)
|
||||
|
||||
/** How many circuits do we want simultaneously in-progress to handle
|
||||
* a given stream? */
|
||||
@ -814,6 +816,13 @@ typedef enum {
|
||||
/** Amount to increment a stream window when we get a stream SENDME. */
|
||||
#define STREAMWINDOW_INCREMENT 50
|
||||
|
||||
/** Maximum number of queued cells on a circuit for which we are the
|
||||
* midpoint before we give up and kill it. This must be >= circwindow
|
||||
* to avoid killing innocent circuits, and >= circwindow*2 to give
|
||||
* leaky-pipe a chance for being useful someday.
|
||||
*/
|
||||
#define ORCIRC_MAX_MIDDLE_CELLS (21*(CIRCWINDOW_START_MAX)/10)
|
||||
|
||||
/* Cell commands. These values are defined in tor-spec.txt. */
|
||||
#define CELL_PADDING 0
|
||||
#define CELL_CREATE 1
|
||||
@ -903,8 +912,13 @@ typedef struct var_cell_t {
|
||||
typedef struct packed_cell_t {
|
||||
struct packed_cell_t *next; /**< Next cell queued on this circuit. */
|
||||
char body[CELL_NETWORK_SIZE]; /**< Cell as packed for network. */
|
||||
uint32_t inserted_time; /**< Time (in milliseconds since epoch, with high
|
||||
* bits truncated) when this cell was inserted. */
|
||||
} packed_cell_t;
|
||||
|
||||
/* XXXX This next structure may be obsoleted by inserted_time in
|
||||
* packed_cell_t */
|
||||
|
||||
/** Number of cells added to a circuit queue including their insertion
|
||||
* time on 10 millisecond detail; used for buffer statistics. */
|
||||
typedef struct insertion_time_elem_t {
|
||||
@ -998,6 +1012,9 @@ typedef struct connection_t {
|
||||
/** Set to 1 when we're inside connection_flushed_some to keep us from
|
||||
* calling connection_handle_write() recursively. */
|
||||
unsigned int in_flushed_some:1;
|
||||
/** True if connection_handle_write is currently running on this connection.
|
||||
*/
|
||||
unsigned int in_connection_handle_write:1;
|
||||
|
||||
/* For linked connections:
|
||||
*/
|
||||
@ -1149,6 +1166,9 @@ typedef struct or_handshake_state_t {
|
||||
/* True iff we've received valid authentication to some identity. */
|
||||
unsigned int authenticated : 1;
|
||||
|
||||
/* True iff we have sent a netinfo cell */
|
||||
unsigned int sent_netinfo : 1;
|
||||
|
||||
/** True iff we should feed outgoing cells into digest_sent and
|
||||
* digest_received respectively.
|
||||
*
|
||||
@ -3052,6 +3072,10 @@ typedef struct {
|
||||
config_line_t *DirPort_lines;
|
||||
config_line_t *DNSPort_lines; /**< Ports to listen on for DNS requests. */
|
||||
|
||||
uint64_t MaxMemInCellQueues; /**< If we have more memory than this allocated
|
||||
* for circuit cell queues, run the OOM handler
|
||||
*/
|
||||
|
||||
/** @name port booleans
|
||||
*
|
||||
* Derived booleans: True iff there is a non-listener port on an AF_INET or
|
||||
|
@ -1799,7 +1799,7 @@ circuit_consider_sending_sendme(circuit_t *circ, crypt_path_t *layer_hint)
|
||||
#endif
|
||||
|
||||
/** The total number of cells we have allocated from the memory pool. */
|
||||
static int total_cells_allocated = 0;
|
||||
static size_t total_cells_allocated = 0;
|
||||
|
||||
/** A memory pool to allocate packed_cell_t objects. */
|
||||
static mp_pool_t *cell_pool = NULL;
|
||||
@ -1871,7 +1871,7 @@ dump_cell_pool_usage(int severity)
|
||||
++n_circs;
|
||||
}
|
||||
log(severity, LD_MM, "%d cells allocated on %d circuits. %d cells leaked.",
|
||||
n_cells, n_circs, total_cells_allocated - n_cells);
|
||||
n_cells, n_circs, (int)total_cells_allocated - n_cells);
|
||||
mp_pool_log_status(cell_pool, severity);
|
||||
}
|
||||
|
||||
@ -1904,15 +1904,19 @@ cell_queue_append(cell_queue_t *queue, packed_cell_t *cell)
|
||||
void
|
||||
cell_queue_append_packed_copy(cell_queue_t *queue, const cell_t *cell)
|
||||
{
|
||||
packed_cell_t *copy = packed_cell_copy(cell);
|
||||
/* Remember the time when this cell was put in the queue. */
|
||||
if (get_options()->CellStatistics) {
|
||||
struct timeval now;
|
||||
packed_cell_t *copy = packed_cell_copy(cell);
|
||||
tor_gettimeofday_cached(&now);
|
||||
copy->inserted_time = (uint32_t)tv_to_msec(&now);
|
||||
|
||||
/* Remember the time when this cell was put in the queue. */
|
||||
/*XXXX This may be obsoleted by inserted_time */
|
||||
if (get_options()->CellStatistics) {
|
||||
uint32_t added;
|
||||
insertion_time_queue_t *it_queue = queue->insertion_times;
|
||||
if (!it_pool)
|
||||
it_pool = mp_pool_new(sizeof(insertion_time_elem_t), 1024);
|
||||
tor_gettimeofday_cached(&now);
|
||||
|
||||
#define SECONDS_IN_A_DAY 86400L
|
||||
added = (uint32_t)(((now.tv_sec % SECONDS_IN_A_DAY) * 100L)
|
||||
+ ((uint32_t)now.tv_usec / (uint32_t)10000L));
|
||||
@ -1978,6 +1982,29 @@ cell_queue_pop(cell_queue_t *queue)
|
||||
return cell;
|
||||
}
|
||||
|
||||
/** Return the total number of bytes used for each packed_cell in a queue.
|
||||
* Approximate. */
|
||||
size_t
|
||||
packed_cell_mem_cost(void)
|
||||
{
|
||||
return sizeof(packed_cell_t) + MP_POOL_ITEM_OVERHEAD +
|
||||
get_options()->CellStatistics ?
|
||||
(sizeof(insertion_time_elem_t)+MP_POOL_ITEM_OVERHEAD) : 0;
|
||||
}
|
||||
|
||||
/** Check whether we've got too much space used for cells. If so,
|
||||
* call the OOM handler and return 1. Otherwise, return 0. */
|
||||
static int
|
||||
cell_queues_check_size(void)
|
||||
{
|
||||
size_t alloc = total_cells_allocated * packed_cell_mem_cost();
|
||||
if (alloc >= get_options()->MaxMemInCellQueues) {
|
||||
circuits_handle_oom(alloc);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Return a pointer to the "next_active_on_{n,p}_conn" pointer of <b>circ</b>,
|
||||
* depending on whether <b>conn</b> matches n_conn or p_conn. */
|
||||
static INLINE circuit_t **
|
||||
@ -2532,8 +2559,10 @@ append_cell_to_circuit_queue(circuit_t *circ, or_connection_t *orconn,
|
||||
cell_t *cell, cell_direction_t direction,
|
||||
streamid_t fromstream)
|
||||
{
|
||||
or_circuit_t *orcirc = NULL;
|
||||
cell_queue_t *queue;
|
||||
int streams_blocked;
|
||||
|
||||
if (circ->marked_for_close)
|
||||
return;
|
||||
|
||||
@ -2541,13 +2570,43 @@ append_cell_to_circuit_queue(circuit_t *circ, or_connection_t *orconn,
|
||||
queue = &circ->n_conn_cells;
|
||||
streams_blocked = circ->streams_blocked_on_n_conn;
|
||||
} else {
|
||||
or_circuit_t *orcirc = TO_OR_CIRCUIT(circ);
|
||||
orcirc = TO_OR_CIRCUIT(circ);
|
||||
queue = &orcirc->p_conn_cells;
|
||||
streams_blocked = circ->streams_blocked_on_p_conn;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disabling this for now because of a possible guard discovery attack
|
||||
*/
|
||||
#if 0
|
||||
/* Are we a middle circuit about to exceed ORCIRC_MAX_MIDDLE_CELLS? */
|
||||
if ((circ->n_conn != NULL) && CIRCUIT_IS_ORCIRC(circ)) {
|
||||
orcirc = TO_OR_CIRCUIT(circ);
|
||||
if (orcirc->p_conn) {
|
||||
if (queue->n + 1 >= ORCIRC_MAX_MIDDLE_CELLS) {
|
||||
/* Queueing this cell would put queue over the cap */
|
||||
log_warn(LD_CIRC,
|
||||
"Got a cell exceeding the cap of %u in the %s direction "
|
||||
"on middle circ ID %u; killing the circuit.",
|
||||
ORCIRC_MAX_MIDDLE_CELLS,
|
||||
(direction == CELL_DIRECTION_OUT) ? "n" : "p",
|
||||
(direction == CELL_DIRECTION_OUT) ?
|
||||
circ->n_circ_id : orcirc->p_circ_id);
|
||||
circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
cell_queue_append_packed_copy(queue, cell);
|
||||
|
||||
if (PREDICT_UNLIKELY(cell_queues_check_size())) {
|
||||
/* We ran the OOM handler */
|
||||
if (circ->marked_for_close)
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we have too many cells on the circuit, we should stop reading from
|
||||
* the edge streams for a while. */
|
||||
if (!streams_blocked && queue->n >= CELL_QUEUE_HIGHWATER_SIZE)
|
||||
|
@ -40,6 +40,7 @@ void init_cell_pool(void);
|
||||
void free_cell_pool(void);
|
||||
void clean_cell_pool(void);
|
||||
void dump_cell_pool_usage(int severity);
|
||||
size_t packed_cell_mem_cost(void);
|
||||
|
||||
void cell_queue_clear(cell_queue_t *queue);
|
||||
void cell_queue_append(cell_queue_t *queue, packed_cell_t *cell);
|
||||
|
@ -1002,6 +1002,10 @@ rend_cache_lookup_v2_desc_as_dir(const char *desc_id, const char **desc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Do not allow more than this many introduction points in a hidden service
|
||||
* descriptor */
|
||||
#define MAX_INTRO_POINTS 10
|
||||
|
||||
/** Parse *desc, calculate its service id, and store it in the cache.
|
||||
* If we have a newer v0 descriptor with the same ID, ignore this one.
|
||||
* If we have an older descriptor with the same ID, replace it.
|
||||
@ -1070,6 +1074,16 @@ rend_cache_store(const char *desc, size_t desc_len, int published,
|
||||
rend_service_descriptor_free(parsed);
|
||||
return -1;
|
||||
}
|
||||
if (parsed->intro_nodes &&
|
||||
smartlist_len(parsed->intro_nodes) > MAX_INTRO_POINTS) {
|
||||
log_warn(LD_REND, "Found too many introduction points on a hidden "
|
||||
"service descriptor for %s. This is probably a (misguided) "
|
||||
"attempt to improve reliability, but it could also be an "
|
||||
"attempt to do a guard enumeration attack. Rejecting.",
|
||||
safe_str_client(query));
|
||||
rend_service_descriptor_free(parsed);
|
||||
return -2;
|
||||
}
|
||||
tor_snprintf(key, sizeof(key), "0%s", query);
|
||||
e = (rend_cache_entry_t*) strmap_get_lc(rend_cache, key);
|
||||
if (e && e->parsed->timestamp > parsed->timestamp) {
|
||||
@ -1288,6 +1302,7 @@ rend_cache_store_v2_desc_as_client(const char *desc,
|
||||
}
|
||||
/* Decode/decrypt introduction points. */
|
||||
if (intro_content) {
|
||||
int n_intro_points;
|
||||
if (rend_query->auth_type != REND_NO_AUTH &&
|
||||
!tor_mem_is_zero(rend_query->descriptor_cookie,
|
||||
sizeof(rend_query->descriptor_cookie))) {
|
||||
@ -1308,13 +1323,22 @@ rend_cache_store_v2_desc_as_client(const char *desc,
|
||||
intro_size = ipos_decrypted_size;
|
||||
}
|
||||
}
|
||||
if (rend_parse_introduction_points(parsed, intro_content,
|
||||
intro_size) <= 0) {
|
||||
n_intro_points = rend_parse_introduction_points(parsed, intro_content,
|
||||
intro_size);
|
||||
if (n_intro_points <= 0) {
|
||||
log_warn(LD_REND, "Failed to parse introduction points. Either the "
|
||||
"service has published a corrupt descriptor or you have "
|
||||
"provided invalid authorization data.");
|
||||
retval = -2;
|
||||
goto err;
|
||||
} else if (n_intro_points > MAX_INTRO_POINTS) {
|
||||
log_warn(LD_REND, "Found too many introduction points on a hidden "
|
||||
"service descriptor for %s. This is probably a (misguided) "
|
||||
"attempt to improve reliability, but it could also be an "
|
||||
"attempt to do a guard enumeration attack. Rejecting.",
|
||||
safe_str_client(rend_query->onion_address));
|
||||
retval = -2;
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
log_info(LD_REND, "Descriptor does not contain any introduction points.");
|
||||
|
@ -177,7 +177,7 @@ get_server_identity_key(void)
|
||||
int
|
||||
server_identity_key_is_set(void)
|
||||
{
|
||||
return server_identitykey != NULL;
|
||||
return server_mode(get_options()) && server_identitykey != NULL;
|
||||
}
|
||||
|
||||
/** Set the current client identity key to <b>k</b>.
|
||||
|
@ -458,6 +458,37 @@ authority_cert_dl_failed(const char *id_digest, int status)
|
||||
download_status_failed(&cl->dl_status, status);
|
||||
}
|
||||
|
||||
static const char *BAD_SIGNING_KEYS[] = {
|
||||
"09CD84F751FD6E955E0F8ADB497D5401470D697E", // Expires 2015-01-11 16:26:31
|
||||
"0E7E9C07F0969D0468AD741E172A6109DC289F3C", // Expires 2014-08-12 10:18:26
|
||||
"57B85409891D3FB32137F642FDEDF8B7F8CDFDCD", // Expires 2015-02-11 17:19:09
|
||||
"87326329007AF781F587AF5B594E540B2B6C7630", // Expires 2014-07-17 11:10:09
|
||||
"98CC82342DE8D298CF99D3F1A396475901E0D38E", // Expires 2014-11-10 13:18:56
|
||||
"9904B52336713A5ADCB13E4FB14DC919E0D45571", // Expires 2014-04-20 20:01:01
|
||||
"9DCD8E3F1DD1597E2AD476BBA28A1A89F3095227", // Expires 2015-01-16 03:52:30
|
||||
"A61682F34B9BB9694AC98491FE1ABBFE61923941", // Expires 2014-06-11 09:25:09
|
||||
"B59F6E99C575113650C99F1C425BA7B20A8C071D", // Expires 2014-07-31 13:22:10
|
||||
"D27178388FA75B96D37FA36E0B015227DDDBDA51", // Expires 2014-08-04 04:01:57
|
||||
NULL,
|
||||
};
|
||||
|
||||
/** DOCDOC */
|
||||
int
|
||||
authority_cert_is_blacklisted(const authority_cert_t *cert)
|
||||
{
|
||||
char hex_digest[HEX_DIGEST_LEN+1];
|
||||
int i;
|
||||
base16_encode(hex_digest, sizeof(hex_digest),
|
||||
cert->signing_key_digest, sizeof(cert->signing_key_digest));
|
||||
|
||||
for (i = 0; BAD_SIGNING_KEYS[i]; ++i) {
|
||||
if (!strcasecmp(hex_digest, BAD_SIGNING_KEYS[i])) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Return true iff when we've been getting enough failures when trying to
|
||||
* download the certificate with ID digest <b>id_digest</b> that we're willing
|
||||
* to start bugging the user about it. */
|
||||
|
@ -25,6 +25,7 @@ void authority_cert_dl_failed(const char *id_digest, int status);
|
||||
void authority_certs_fetch_missing(networkstatus_t *status, time_t now);
|
||||
int router_reload_router_list(void);
|
||||
int authority_cert_dl_looks_uncertain(const char *id_digest);
|
||||
int authority_cert_is_blacklisted(const authority_cert_t *cert);
|
||||
smartlist_t *router_get_trusted_dir_servers(void);
|
||||
|
||||
const routerstatus_t *router_pick_directory_server(dirinfo_type_t type,
|
||||
|
@ -3053,6 +3053,14 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
|
||||
log_warn(LD_DIR,"Mismatch between identities in certificate and vote");
|
||||
goto err;
|
||||
}
|
||||
if (ns->type != NS_TYPE_CONSENSUS) {
|
||||
if (authority_cert_is_blacklisted(ns->cert)) {
|
||||
log_warn(LD_DIR, "Rejecting vote signature made with blacklisted "
|
||||
"signing key %s",
|
||||
hex_str(ns->cert->signing_key_digest, DIGEST_LEN));
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
voter->address = tor_strdup(tok->args[2]);
|
||||
if (!tor_inet_aton(tok->args[3], &in)) {
|
||||
log_warn(LD_DIR, "Error decoding IP address %s in network-status.",
|
||||
@ -4447,11 +4455,13 @@ microdescs_parse_from_string(const char *s, const char *eos,
|
||||
microdesc_free(md);
|
||||
md = NULL;
|
||||
|
||||
SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
|
||||
memarea_clear(area);
|
||||
smartlist_clear(tokens);
|
||||
s = start_of_next_microdesc;
|
||||
}
|
||||
|
||||
SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
|
||||
memarea_drop_all(area);
|
||||
smartlist_free(tokens);
|
||||
|
||||
|
@ -802,6 +802,18 @@ test_buffers(void)
|
||||
buf_free(buf);
|
||||
buf = NULL;
|
||||
|
||||
/* Try adding a string too long for any freelist. */
|
||||
{
|
||||
char *cp = tor_malloc_zero(65536);
|
||||
buf = buf_new();
|
||||
write_to_buf(cp, 65536, buf);
|
||||
tor_free(cp);
|
||||
|
||||
tt_int_op(buf_datalen(buf), ==, 65536);
|
||||
buf_free(buf);
|
||||
buf = NULL;
|
||||
}
|
||||
|
||||
done:
|
||||
if (buf)
|
||||
buf_free(buf);
|
||||
|
@ -2169,6 +2169,7 @@ test_util_exit_status(void *ptr)
|
||||
n = format_helper_exit_status(0xFF, -0x80000000, hex_errno);
|
||||
test_streq("FF/-80000000\n", hex_errno);
|
||||
test_eq(n, strlen(hex_errno));
|
||||
test_eq(n, HEX_ERRNO_SIZE);
|
||||
|
||||
clear_hex_errno(hex_errno);
|
||||
n = format_helper_exit_status(0x7F, 0, hex_errno);
|
||||
|
Loading…
Reference in New Issue
Block a user