summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changes/bug18483
-rw-r--r--changes/log-ratelim7
-rw-r--r--changes/openbsd-sysheaders4
-rw-r--r--configure.in11
-rw-r--r--doc/spec/rend-spec.txt55
-rw-r--r--src/common/util.c43
-rw-r--r--src/common/util.h27
-rw-r--r--src/or/command.c9
-rw-r--r--src/or/connection.c12
-rw-r--r--src/or/onion.c11
-rw-r--r--src/or/or.h3
11 files changed, 147 insertions, 38 deletions
diff --git a/changes/bug1848 b/changes/bug1848
new file mode 100644
index 0000000000..db00e17f83
--- /dev/null
+++ b/changes/bug1848
@@ -0,0 +1,3 @@
+ o Minor bugfixes:
+ - Squash a compile warning on OpenBSD. Reported by Tas, fixes bug 1848.
+
diff --git a/changes/log-ratelim b/changes/log-ratelim
new file mode 100644
index 0000000000..612a510fdf
--- /dev/null
+++ b/changes/log-ratelim
@@ -0,0 +1,7 @@
+ o Minor bugfixes
+ - Rate-limit "Failed to hand off onionskin" warnings.
+
+ o Minor features
+ - When logging a rate-limited warning, we now mention how many messages
+ got suppressed since the last warning.
+
diff --git a/changes/openbsd-sysheaders b/changes/openbsd-sysheaders
new file mode 100644
index 0000000000..2babde2d78
--- /dev/null
+++ b/changes/openbsd-sysheaders
@@ -0,0 +1,4 @@
+ o Minor bugfixes:
+ - When building with --enable-gcc-warnings on OpenBSD, disable
+ warnings in system headers. This makes --enable-gcc-warnings
+ pass on OpenBSD 4.8. \ No newline at end of file
diff --git a/configure.in b/configure.in
index 917be20ed8..cb07b2f7b0 100644
--- a/configure.in
+++ b/configure.in
@@ -869,6 +869,15 @@ if test x$enable_gcc_warnings = xyes || test x$enable_gcc_warnings_advisory = xy
have_shorten64_flag=no)
CFLAGS="$save_CFLAGS"
+ case $host in
+ *-*-openbsd*)
+ # Some OpenBSD versions (like 4.8) have -Wsystem-headers by default.
+ # That's fine, except that the headers don't pass -Wredundant-decls.
+ # Therefore, let's disable -Wsystem-headers when we're building
+ # with maximal warnings on OpenBSD.
+ CFLAGS="$CFLAGS -Wno-system-headers" ;;
+ esac
+
CFLAGS="$CFLAGS -W -Wfloat-equal -Wundef -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings -Wredundant-decls -Wchar-subscripts -Wcomment -Wformat=2 -Wwrite-strings -Wmissing-declarations -Wredundant-decls -Wnested-externs -Wbad-function-cast -Wswitch-enum"
if test x$enable_gcc_warnings = xyes; then
CFLAGS="$CFLAGS -Werror"
@@ -876,7 +885,7 @@ if test x$enable_gcc_warnings = xyes || test x$enable_gcc_warnings_advisory = xy
# Disabled, so we can use mallinfo(): -Waggregate-return
- if test x$have_gcc4 = xyes ; then
+ if test x$have_gcc4 = xyes ; then
# These warnings break gcc 3.3.5 and work on gcc 4.0.2
CFLAGS="$CFLAGS -Winit-self -Wmissing-field-initializers -Wdeclaration-after-statement -Wold-style-definition"
fi
diff --git a/doc/spec/rend-spec.txt b/doc/spec/rend-spec.txt
index 12e20df659..3c14ebc662 100644
--- a/doc/spec/rend-spec.txt
+++ b/doc/spec/rend-spec.txt
@@ -150,7 +150,7 @@
The first time the OP provides an advertised service, it generates
a public/private keypair (stored locally).
- The OP choses a small number of Tor servers as introduction points.
+ The OP chooses a small number of Tor servers as introduction points.
The OP establishes a new introduction circuit to each introduction
point. These circuits MUST NOT be used for anything but hidden service
introduction. To establish the introduction, Bob sends a
@@ -238,6 +238,9 @@
permanent-id = H(public-key)[:10]
+ Note: If Bob's OP has "stealth" authorization enabled (see Section 2.2),
+ it uses the client key in place of the public hidden service key.
+
"H(time-period | descriptor-cookie | replica)" is the (possibly
secret) id part that is necessary to verify that the hidden service is
the true originator of this descriptor and that is therefore contained
@@ -668,8 +671,8 @@
circuit. (If the PK_ID is unrecognized, the RELAY_COMMAND_INTRODUCE1 cell is
discarded.)
- After sending the RELAY_COMMAND_INTRODUCE2 cell, the OR replies to Alice
- with an empty RELAY_COMMAND_INTRODUCE_ACK cell. If no
+ After sending the RELAY_COMMAND_INTRODUCE2 cell to Bob, the OR replies to
+ Alice with an empty RELAY_COMMAND_INTRODUCE_ACK cell. If no
RELAY_COMMAND_INTRODUCE2 cell can be sent, the OR replies to Alice with a
non-empty cell to indicate an error. (The semantics of the cell body may be
determined later; the current implementation sends a single '1' byte on
@@ -759,11 +762,11 @@
2.1. Service with large-scale client authorization
The first client authorization protocol aims at performing access control
- while consuming as few additional resources as possible. A service
- provider should be able to permit access to a large number of clients
- while denying access for everyone else. However, the price for
- scalability is that the service won't be able to hide its activity from
- unauthorized or formerly authorized clients.
+ while consuming as few additional resources as possible. This is the "basic"
+ authorization protocol. A service provider should be able to permit access
+ to a large number of clients while denying access for everyone else.
+ However, the price for scalability is that the service won't be able to hide
+ its activity from unauthorized or formerly authorized clients.
The main idea of this protocol is to encrypt the introduction-point part
in hidden service descriptors to authorized clients using symmetric keys.
@@ -822,19 +825,19 @@
2.2. Authorization for limited number of clients
A second, more sophisticated client authorization protocol goes the extra
- mile of hiding service activity from unauthorized clients. With all else
- being equal to the preceding authorization protocol, the second protocol
- publishes hidden service descriptors for each user separately and gets
- along with encrypting the introduction-point part of descriptors to a
- single client. This allows the service to stop publishing descriptors for
- removed clients. As long as a removed client cannot link descriptors
- issued for other clients to the service, it cannot derive service
- activity any more. The downside of this approach is limited scalability.
- Even though the distributed storage of descriptors (cf. proposal 114)
- tackles the problem of limited scalability to a certain extent, this
- protocol should not be used for services with more than 16 clients. (In
- fact, Tor should refuse to advertise services for more than this number
- of clients.)
+ mile of hiding service activity from unauthorized clients. This is the
+ "stealth" authorization protocol. With all else being equal to the preceding
+ authorization protocol, the second protocol publishes hidden service
+ descriptors for each user separately and gets along with encrypting the
+ introduction-point part of descriptors to a single client. This allows the
+ service to stop publishing descriptors for removed clients. As long as a
+ removed client cannot link descriptors issued for other clients to the
+ service, it cannot derive service activity any more. The downside of this
+ approach is limited scalability. Even though the distributed storage of
+ descriptors (cf. proposal 114) tackles the problem of limited scalability to
+ a certain extent, this protocol should not be used for services with more
+ than 16 clients. (In fact, Tor should refuse to advertise services for more
+ than this number of clients.)
A hidden service generates an asymmetric "client key" and a symmetric
"descriptor cookie" for each client. The client key is used as
@@ -882,14 +885,16 @@
A hidden service that is meant to perform client authorization adds a
new option HiddenServiceAuthorizeClient to its hidden service
configuration. This option contains the authorization type which is
- either "1" for the protocol described in 2.1 or "2" for the protocol in
- 2.2 and a comma-separated list of human-readable client names, so that
- Tor can create authorization data for these clients:
+ either "basic" for the protocol described in 2.1 or "stealth" for the
+ protocol in 2.2 and a comma-separated list of human-readable client
+ names, so that Tor can create authorization data for these clients:
HiddenServiceAuthorizeClient auth-type client-name,client-name,...
If this option is configured, HiddenServiceVersion is automatically
- reconfigured to contain only version numbers of 2 or higher.
+ reconfigured to contain only version numbers of 2 or higher. There is
+ a maximum of 512 client names for basic auth and a maximum of 16 for
+ stealth auth.
Tor stores all generated authorization data for the authorization
protocols described in Sections 2.1 and 2.2 in a new file using the
diff --git a/src/common/util.c b/src/common/util.c
index 0f50dfedea..1d770458f7 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -1578,6 +1578,49 @@ ftime_definitely_before(time_t now, time_t when)
}
/* =====
+ * Rate limiting
+ * ===== */
+
+/** If the rate-limiter <b>lim</b> is ready at <b>now</b>, return the number
+ * of calls to rate_limit_is_ready (including this one!) since the last time
+ * rate_limit_is_ready returned nonzero. Otherwise return 0. */
+static int
+rate_limit_is_ready(ratelim_t *lim, time_t now)
+{
+ if (lim->rate + lim->last_allowed <= now) {
+ int res = lim->n_calls_since_last_time + 1;
+ lim->last_allowed = now;
+ lim->n_calls_since_last_time = 0;
+ return res;
+ } else {
+ ++lim->n_calls_since_last_time;
+ return 0;
+ }
+}
+
+/** If the rate-limiter <b>lim</b> is ready at <b>now</b>, return a newly
+ * allocated string indicating how many messages were suppressed, suitable to
+ * append to a log message. Otherwise return NULL. */
+char *
+rate_limit_log(ratelim_t *lim, time_t now)
+{
+ int n;
+ if ((n = rate_limit_is_ready(lim, now))) {
+ if (n == 1) {
+ return tor_strdup("");
+ } else {
+ char *cp=NULL;
+ tor_asprintf(&cp,
+ " [%d similar message(s) suppressed in last %d seconds]",
+ n-1, lim->rate);
+ return cp;
+ }
+ } else {
+ return NULL;
+ }
+}
+
+/* =====
* File helpers
* ===== */
diff --git a/src/common/util.h b/src/common/util.h
index ba38f4c7ed..3a3a87378a 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -252,6 +252,33 @@ int ftime_maybe_before(time_t now, time_t when);
int ftime_definitely_after(time_t now, time_t when);
int ftime_definitely_before(time_t now, time_t when);
+/* Rate-limiter */
+
+/** A ratelim_t remembers how often an event is occurring, and how often
+ * it's allowed to occur. Typical usage is something like:
+ *
+ <pre>
+ if (possibly_very_frequent_event()) {
+ const int INTERVAL = 300;
+ static ratelim_t warning_limit = RATELIM_INIT(INTERVAL);
+ char *m;
+ if ((m = rate_limit_log(&warning_limit, approx_time()))) {
+ log_warn(LD_GENERAL, "The event occurred!%s", m);
+ tor_free(m);
+ }
+ }
+ </pre>
+ */
+typedef struct ratelim_t {
+ int rate;
+ time_t last_allowed;
+ int n_calls_since_last_time;
+} ratelim_t;
+
+#define RATELIM_INIT(r) { (r), 0, 0 }
+
+char *rate_limit_log(ratelim_t *lim, time_t now);
+
/* File helpers */
ssize_t write_all(int fd, const char *buf, size_t count, int isSocket);
ssize_t read_all(int fd, char *buf, size_t count, int isSocket);
diff --git a/src/or/command.c b/src/or/command.c
index 0460e25c25..ea0bbea1e5 100644
--- a/src/or/command.c
+++ b/src/or/command.c
@@ -288,7 +288,14 @@ command_process_create_cell(cell_t *cell, or_connection_t *conn)
/* hand it off to the cpuworkers, and then return. */
if (assign_onionskin_to_cpuworker(NULL, circ, onionskin) < 0) {
- log_warn(LD_GENERAL,"Failed to hand off onionskin. Closing.");
+#define WARN_HANDOFF_FAILURE_INTERVAL (6*60*60)
+ static ratelim_t handoff_warning =
+ RATELIM_INIT(WARN_HANDOFF_FAILURE_INTERVAL);
+ char *m;
+ if ((m = rate_limit_log(&handoff_warning, approx_time()))) {
+ log_warn(LD_GENERAL,"Failed to hand off onionskin. Closing.%s",m);
+ tor_free(m);
+ }
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
return;
}
diff --git a/src/or/connection.c b/src/or/connection.c
index c040be041e..91ce74b5b0 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -839,13 +839,13 @@ static void
warn_too_many_conns(void)
{
#define WARN_TOO_MANY_CONNS_INTERVAL (6*60*60)
- static time_t last_warned = 0;
- time_t now = time(NULL);
- int n_conns = get_n_open_sockets();
- if (last_warned + WARN_TOO_MANY_CONNS_INTERVAL < now) {
+ static ratelim_t last_warned = RATELIM_INIT(WARN_TOO_MANY_CONNS_INTERVAL);
+ char *m;
+ if ((m = rate_limit_log(&last_warned, approx_time()))) {
+ int n_conns = get_n_open_sockets();
log_warn(LD_NET,"Failing because we have %d connections already. Please "
- "raise your ulimit -n.", n_conns);
- last_warned = now;
+ "raise your ulimit -n.%s", n_conns, m);
+ tor_free(m);
control_event_general_status(LOG_WARN, "TOO_MANY_CONNECTIONS CURRENT=%d",
n_conns);
}
diff --git a/src/or/onion.c b/src/or/onion.c
index ebc3583648..fa001656e6 100644
--- a/src/or/onion.c
+++ b/src/or/onion.c
@@ -63,15 +63,16 @@ onion_pending_add(or_circuit_t *circ, char *onionskin)
if (ol_length >= get_options()->MaxOnionsPending) {
#define WARN_TOO_MANY_CIRC_CREATIONS_INTERVAL (60)
- static time_t last_warned = 0;
- time_t now = time(NULL);
- if (last_warned + WARN_TOO_MANY_CIRC_CREATIONS_INTERVAL < now) {
+ static ratelim_t last_warned =
+ RATELIM_INIT(WARN_TOO_MANY_CIRC_CREATIONS_INTERVAL);
+ char *m;
+ if ((m = rate_limit_log(&last_warned, approx_time()))) {
log_warn(LD_GENERAL,
"Your computer is too slow to handle this many circuit "
"creation requests! Please consider using the "
"MaxAdvertisedBandwidth config option or choosing a more "
- "restricted exit policy.");
- last_warned = now;
+ "restricted exit policy.%s",m);
+ tor_free(m);
}
tor_free(tmp);
return -1;
diff --git a/src/or/or.h b/src/or/or.h
index e6307e3eea..48641c8115 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -59,6 +59,9 @@
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif