diff options
-rw-r--r-- | ChangeLog | 28 | ||||
-rw-r--r-- | ReleaseNotes | 75 | ||||
-rw-r--r-- | changes/bug2097-more | 6 | ||||
-rw-r--r-- | changes/bug2146.1 | 4 | ||||
-rw-r--r-- | changes/bug2183 | 6 | ||||
-rw-r--r-- | changes/bug2195 | 7 | ||||
-rw-r--r-- | changes/bug2210 | 5 | ||||
-rw-r--r-- | changes/bug2235 | 3 | ||||
-rw-r--r-- | changes/bytecount | 5 | ||||
-rw-r--r-- | changes/fix2195-fix | 6 | ||||
-rw-r--r-- | changes/fix2204 | 7 | ||||
-rw-r--r-- | changes/mingw-openssl098m | 3 | ||||
-rw-r--r-- | changes/remove-website | 5 | ||||
-rw-r--r-- | changes/task2196 | 5 | ||||
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | contrib/tor-mingw.nsi.in | 2 | ||||
-rw-r--r-- | doc/spec/control-spec.txt | 144 | ||||
-rw-r--r-- | src/common/compat.c | 24 | ||||
-rw-r--r-- | src/common/compat.h | 5 | ||||
-rw-r--r-- | src/common/crypto.c | 10 | ||||
-rw-r--r-- | src/or/control.c | 3 | ||||
-rw-r--r-- | src/or/dirserv.c | 2 | ||||
-rw-r--r-- | src/or/hibernate.c | 28 | ||||
-rw-r--r-- | src/or/relay.c | 50 | ||||
-rw-r--r-- | src/or/rephist.c | 148 | ||||
-rw-r--r-- | src/or/router.c | 2 | ||||
-rw-r--r-- | src/test/test.c | 17 | ||||
-rw-r--r-- | src/win32/orconfig.h | 2 |
28 files changed, 456 insertions, 148 deletions
@@ -1,4 +1,32 @@ +Changes in version 0.2.2.19-alpha - 2010-11-22 + Yet another OpenSSL security patch broke its compatibility with Tor: + Tor 0.2.2.19-alpha makes relays work with OpenSSL 0.9.8p and 1.0.0.b. + + o Major bugfixes: + - Resolve an incompatibility with OpenSSL 0.9.8p and OpenSSL 1.0.0b: + No longer set the tlsext_host_name extension on server SSL objects; + but continue to set it on client SSL objects. Our goal in setting + it was to imitate a browser, not a vhosting server. Fixes bug 2204; + bugfix on 0.2.1.1-alpha. + + o Minor bugfixes: + - Try harder not to exceed the maximum length of 50 KB when writing + statistics to extra-info descriptors. This bug was triggered by very + fast relays reporting exit-port, entry, and dirreq statistics. + Reported by Olaf Selke. Bugfix on 0.2.2.1-alpha. Fixes bug 2183. + - Publish a router descriptor even if generating an extra-info + descriptor fails. Previously we would not publish a router + descriptor without an extra-info descriptor; this can cause fast + exit relays collecting exit-port statistics to drop from the + consensus. Bugfix on 0.1.2.9-rc; fixes bug 2195. + + Changes in version 0.2.2.18-alpha - 2010-11-16 + Tor 0.2.2.18-alpha fixes several crash bugs that have been nagging + us lately, makes unpublished bridge relays able to detect their IP + address, and fixes a wide variety of other bugs to get us much closer + to a stable release. + o Major bugfixes: - Do even more to reject (and not just ignore) annotations on router descriptors received anywhere but from the cache. Previously diff --git a/ReleaseNotes b/ReleaseNotes index efa04775d1..30d35dde0e 100644 --- a/ReleaseNotes +++ b/ReleaseNotes @@ -3,6 +3,81 @@ This document summarizes new features and bugfixes in each stable release of Tor. If you want to see more detailed descriptions of the changes in each development snapshot, see the ChangeLog file. +Changes in version 0.2.1.27 - 2010-11-23 + Yet another OpenSSL security patch broke its compatibility with Tor: + Tor 0.2.1.27 makes relays work with openssl 0.9.8p and 1.0.0.b. We + also took this opportunity to fix several crash bugs, integrate a new + directory authority, and update the bundled GeoIP database. + + o Major bugfixes: + - Resolve an incompatibility with OpenSSL 0.9.8p and OpenSSL 1.0.0b: + No longer set the tlsext_host_name extension on server SSL objects; + but continue to set it on client SSL objects. Our goal in setting + it was to imitate a browser, not a vhosting server. Fixes bug 2204; + bugfix on 0.2.1.1-alpha. + - Do not log messages to the controller while shrinking buffer + freelists. Doing so would sometimes make the controller connection + try to allocate a buffer chunk, which would mess up the internals + of the freelist and cause an assertion failure. Fixes bug 1125; + fixed by Robert Ransom. Bugfix on 0.2.0.16-alpha. + - Learn our external IP address when we're a relay or bridge, even if + we set PublishServerDescriptor to 0. Bugfix on 0.2.0.3-alpha, + where we introduced bridge relays that don't need to publish to + be useful. Fixes bug 2050. + - Do even more to reject (and not just ignore) annotations on + router descriptors received anywhere but from the cache. Previously + we would ignore such annotations at first, but cache them to disk + anyway. Bugfix on 0.2.0.8-alpha. Found by piebeer. + - When you're using bridges and your network goes away and your + bridges get marked as down, recover when you attempt a new socks + connection (if the network is back), rather than waiting up to an + hour to try fetching new descriptors for your bridges. Bugfix on + 0.2.0.3-alpha; fixes bug 1981. + + o Major features: + - Move to the November 2010 Maxmind GeoLite country db (rather + than the June 2009 ip-to-country GeoIP db) for our statistics that + count how many users relays are seeing from each country. Now we'll + have more accurate data, especially for many African countries. + + o New directory authorities: + - Set up maatuska (run by Linus Nordberg) as the eighth v3 directory + authority. + + o Minor bugfixes: + - Fix an assertion failure that could occur in directory caches or + bridge users when using a very short voting interval on a testing + network. Diagnosed by Robert Hogan. Fixes bug 1141; bugfix on + 0.2.0.8-alpha. + - Enforce multiplicity rules when parsing annotations. Bugfix on + 0.2.0.8-alpha. Found by piebeer. + - Allow handshaking OR connections to take a full KeepalivePeriod + seconds to handshake. Previously, we would close them after + IDLE_OR_CONN_TIMEOUT (180) seconds, the same timeout as if they + were open. Bugfix on 0.2.1.26; fixes bug 1840. Thanks to mingw-san + for analysis help. + - When building with --enable-gcc-warnings on OpenBSD, disable + warnings in system headers. This makes --enable-gcc-warnings + pass on OpenBSD 4.8. + + o Minor features: + - Exit nodes didn't recognize EHOSTUNREACH as a plausible error code, + and so sent back END_STREAM_REASON_MISC. Clients now recognize a new + stream ending reason for this case: END_STREAM_REASON_NOROUTE. + Servers can start sending this code when enough clients recognize + it. Bugfix on 0.1.0.1-rc; fixes part of bug 1793. + - Build correctly on mingw with more recent versions of OpenSSL 0.9.8. + Patch from mingw-san. + + o Removed files: + - Remove the old debian/ directory from the main Tor distribution. + The official Tor-for-debian git repository lives at the URL + https://git.torproject.org/debian/tor.git + - Stop shipping the old doc/website/ directory in the tarball. We + changed the website format in late 2010, and what we shipped in + 0.2.1.26 really wasn't that useful anyway. + + Changes in version 0.2.1.26 - 2010-05-02 Tor 0.2.1.26 addresses the recent connection and memory overload problems we've been seeing on relays, especially relays with their diff --git a/changes/bug2097-more b/changes/bug2097-more new file mode 100644 index 0000000000..52351cc019 --- /dev/null +++ b/changes/bug2097-more @@ -0,0 +1,6 @@ + o Minor bugfixes: + - Fix a logic error in directory_fetches_from_authorities that + would cause all _non_-exits refusing single-hop-like circuits to + fetch from authorities, when we wanted to have _exits_ fetch + from authorities. Fix by boboper; fixes more of 2097; bugfix on + 0.2.2.16-alpha. diff --git a/changes/bug2146.1 b/changes/bug2146.1 new file mode 100644 index 0000000000..5b91c59a68 --- /dev/null +++ b/changes/bug2146.1 @@ -0,0 +1,4 @@ + - Major bugfixes: + o Fix a bug that could break accounting on 64-bit systems with large + time_t values, making them hibernate for impossibly long intervals. + Bugfix on 0.0.9pre6; fix for bug 2146; fix by boboper. diff --git a/changes/bug2183 b/changes/bug2183 deleted file mode 100644 index 01a8d76aca..0000000000 --- a/changes/bug2183 +++ /dev/null @@ -1,6 +0,0 @@ - o Minor bugfixes: - - Try harder not to exceed the maximum length of 50 KB when writing - statistics to extra-info descriptors. This bug was triggered by very - fast relays reporting exit-port, entry, and dirreq statistics. - Reported by Olaf Selke. Bugfix on 0.2.2.1-alpha. Fixes bug 2183. - diff --git a/changes/bug2195 b/changes/bug2195 deleted file mode 100644 index 1724fd0e21..0000000000 --- a/changes/bug2195 +++ /dev/null @@ -1,7 +0,0 @@ - o Minor bugfixes - - Publish a router descriptor even if generating an extra-info - descriptor fails. Previously we would not publish a router - descriptor without an extra-info descriptor; this can cause fast - exit relays collecting exit-port statistics to drop from the - consensus. Bugfix on 0.1.2.9-rc; fixes bug 2195. - diff --git a/changes/bug2210 b/changes/bug2210 new file mode 100644 index 0000000000..fe1c049fcd --- /dev/null +++ b/changes/bug2210 @@ -0,0 +1,5 @@ + o ?? bugfixes: + - Fix a bug that would cause newer streams on a given circuit to + get preference when reading bytes from the network. Fixes bug + 2210. Fix by Mashael AlSabah. This bug was introduced before + the first Tor release, in svn revision r152. diff --git a/changes/bug2235 b/changes/bug2235 new file mode 100644 index 0000000000..0c3bafa44f --- /dev/null +++ b/changes/bug2235 @@ -0,0 +1,3 @@ + o Minor bugfixes + - Avoid crashes when AccountingMax is set on clients. Fixes bug 2235; + Bugfix on 0.2.2.18-alpha. Diagnosed by boboper. diff --git a/changes/bytecount b/changes/bytecount new file mode 100644 index 0000000000..50c4d6b35e --- /dev/null +++ b/changes/bytecount @@ -0,0 +1,5 @@ + o Minor bugfixes + - Fix a off-by-one error in calculating some controller command argument + lengths. Fortunately, this is harmless, the controller code does + redundant NUL termination too. Found by boboper. Bugfix on + 0.1.1.1-alpha. diff --git a/changes/fix2195-fix b/changes/fix2195-fix new file mode 100644 index 0000000000..9f03c2465e --- /dev/null +++ b/changes/fix2195-fix @@ -0,0 +1,6 @@ + o Minor bugfixes: + - Do not dereference NULL if a bridge fails to build its + extra-info descriptor. Previously, we would have dereferenced + NULL. Found by an anonymous commenter on Trac. Bugfix on + 0.2.2.19-alpha. + diff --git a/changes/fix2204 b/changes/fix2204 deleted file mode 100644 index fb2771a7fa..0000000000 --- a/changes/fix2204 +++ /dev/null @@ -1,7 +0,0 @@ - o Major bugfixes - - Do not set the tlsext_host_name extension on server SSL objects; - only on client SSL objects. We set it to immitate a browser, not a - vhosting server. This resolves an incompatibility with openssl 0.9.8p - and openssl 1.0.0b. Fixes bug 2204; bugfix on 0.2.1.1-alpha. - - diff --git a/changes/mingw-openssl098m b/changes/mingw-openssl098m new file mode 100644 index 0000000000..b4199760b7 --- /dev/null +++ b/changes/mingw-openssl098m @@ -0,0 +1,3 @@ + o Minor features + - Build correctly on mingw with more recent version of OpenSSL 0.9.8. + Patch from mingw-san. diff --git a/changes/remove-website b/changes/remove-website new file mode 100644 index 0000000000..ecbfbf9bc2 --- /dev/null +++ b/changes/remove-website @@ -0,0 +1,5 @@ + o Removed files: + - Stop shipping the old doc/website/ directory in the tarball. We + changed the website format in late 2010, and what we shipped in + 0.2.1.26 really wasn't that useful anyway. + diff --git a/changes/task2196 b/changes/task2196 new file mode 100644 index 0000000000..e629fccac2 --- /dev/null +++ b/changes/task2196 @@ -0,0 +1,5 @@ + o Minor features: + - Report only the top 10 ports in exit-port stats in order not to + exceed the maximum extra-info descriptor length of 50 KB. Implements + task 2196. + diff --git a/configure.in b/configure.in index d4878cdc5a..346008f630 100644 --- a/configure.in +++ b/configure.in @@ -4,7 +4,7 @@ dnl Copyright (c) 2007-2008, The Tor Project, Inc. dnl See LICENSE for licensing information AC_INIT -AM_INIT_AUTOMAKE(tor, 0.2.2.18-alpha-dev) +AM_INIT_AUTOMAKE(tor, 0.2.2.19-alpha) AM_CONFIG_HEADER(orconfig.h) AC_CANONICAL_HOST diff --git a/contrib/tor-mingw.nsi.in b/contrib/tor-mingw.nsi.in index da7167cdaa..a44961b027 100644 --- a/contrib/tor-mingw.nsi.in +++ b/contrib/tor-mingw.nsi.in @@ -8,7 +8,7 @@ !include "LogicLib.nsh" !include "FileFunc.nsh" !insertmacro GetParameters -!define VERSION "0.2.2.18-alpha-dev" +!define VERSION "0.2.2.19-alpha" !define INSTALLER "tor-${VERSION}-win32.exe" !define WEBSITE "https://www.torproject.org/" !define LICENSE "LICENSE" diff --git a/doc/spec/control-spec.txt b/doc/spec/control-spec.txt index 1864666047..255adf00a4 100644 --- a/doc/spec/control-spec.txt +++ b/doc/spec/control-spec.txt @@ -96,32 +96,35 @@ ; followed by the ASCII Linefeed character (decimal value 10)." CRLF = CR LF - ; Identifiers for servers. - ServerID = Nickname / Fingerprint - - Nickname = 1*19 NicknameChar - NicknameChar = "a"-"z" / "A"-"Z" / "0" - "9" - Fingerprint = "$" 40*HEXDIG - - ; A "=" indicates that the given nickname is canonical; a "~" indicates - ; that the given nickname is not canonical. If no nickname is given at - ; all, Tor does not even have a guess for what this router calls itself. - LongName = Fingerprint [ ( "=" / "~" ) Nickname ] - ; How a controller tells Tor about a particular OR. There are four ; possible formats: - ; $Digest -- The router whose identity key hashes to the given digest. + ; $Fingerprint -- The router whose identity key hashes to the fingerprint. ; This is the preferred way to refer to an OR. - ; $Digest~Name -- The router whose identity key hashes to the given - ; digest, but only if the router has the given nickname. - ; $Digest=Name -- The router whose identity key hashes to the given - ; digest, but only if the router is Named and has the given + ; $Fingerprint~Nickname -- The router whose identity key hashes to the + ; given fingerprint, but only if the router has the given nickname. + ; $Fingerprint=Nickname -- The router whose identity key hashes to the + ; given fingerprint, but only if the router is Named and has the given ; nickname. - ; Name -- The Named router with the given nickname, or, if no such + ; Nickname -- The Named router with the given nickname, or, if no such ; router exists, any router whose nickname matches the one given. ; This is not a safe way to refer to routers, since Named status ; could under some circumstances change over time. + ; + ; The tokens that implement the above follow: + ServerSpec = LongName / Nickname + LongName = Fingerprint [ ( "=" / "~" ) Nickname ] + + Fingerprint = "$" 40*HEXDIG + NicknameChar = "a"-"z" / "A"-"Z" / "0" - "9" + Nickname = 1*19 NicknameChar + + ; What follows is an outdated way to refer to ORs. + ; Feature VERBOSE_NAMES replaces ServerID with LongName in events and + ; GETINFO results. VERBOSE_NAMES can be enabled starting in Tor version + ; 0.1.2.2-alpha and it is always-on in 0.2.2.1-alpha and later. + ServerID = Nickname / Fingerprint + ; Unique identifiers for streams or circuits. Currently, Tor only ; uses digits, but this may change @@ -477,25 +480,36 @@ StreamID SP StreamStatus SP CircID SP Target CRLF "orconn-status" - A series of lines as for an OR connection status event. Each is of the - form: + A series of lines as for an OR connection status event. In Tor + 0.1.2.2-alpha with feature VERBOSE_NAMES enabled and in Tor + 0.2.2.1-alpha and later by default, each line is of the form: + LongName SP ORStatus CRLF + + In Tor versions 0.1.2.2-alpha through 0.2.2.1-alpha with feature + VERBOSE_NAMES turned off and before version 0.1.2.2-alpha, each line + is of the form: ServerID SP ORStatus CRLF "entry-guards" A series of lines listing the currently chosen entry guards, if any. - Each is of the form: - ServerID2 SP Status [SP ISOTime] CRLF - - Status-with-time = ("unlisted") SP ISOTime - Status = ("up" / "never-connected" / "down" / - "unusable" / "unlisted" ) + In Tor 0.1.2.2-alpha with feature VERBOSE_NAMES enabled and in Tor + 0.2.2.1-alpha and later by default, each line is of the form: + LongName SP Status [SP ISOTime] CRLF + In Tor versions 0.1.2.2-alpha through 0.2.2.1-alpha with feature + VERBOSE_NAMES turned off and before version 0.1.2.2-alpha, each line + is of the form: + ServerID2 SP Status [SP ISOTime] CRLF ServerID2 = Nickname / 40*HEXDIG - [From 0.1.1.4-alpha to 0.1.1.10-alpha, this was called "helper-nodes". - Tor still supports calling it that for now, but support will be - removed in 0.1.3.x.] + The definition of Status is the same for both: + Status = "up" / "never-connected" / "down" / + "unusable" / "unlisted" + [From 0.1.1.4-alpha to 0.1.1.10-alpha, entry-guards was called + "helper-nodes". Tor still supports calling "helper-nodes", but it + is deprecated and should not be used.] + [Older versions of Tor (before 0.1.2.x-final) generated 'down' instead of unlisted/unusable. Current Tors never generate 'down'.] @@ -770,46 +784,47 @@ 3.19. USEFEATURE + Adding additional features to the control protocol sometimes will break + backwards compatibility. Initially such features are added into Tor and + disabled by default. USEFEATURE can enable these additional features. + The syntax is: "USEFEATURE" *(SP FeatureName) CRLF FeatureName = 1*(ALPHA / DIGIT / "_" / "-") - Sometimes extensions to the controller protocol break compatibility with - older controllers. In this case, whenever possible, the extensions are - first included in Tor disabled by default, and only enabled on a given - controller connection when the "USEFEATURE" command is given. Once a - "USEFEATURE" command is given, it applies to all subsequent interactions on - the same connection; to disable an enabled feature, a new controller - connection must be opened. + Feature names are case-insensitive. - This is a forward-compatibility mechanism; each feature will eventually - become a regular part of the control protocol in some future version of Tor. - Tor will ignore a request to use any feature that is already on by default. - Tor will give a "552" error if any requested feature is not recognized. + Once enabled, a feature stays enabled for the duration of the connection + to the controller. A new connection to the controller must be opened to + disable an enabled feature. - Feature names are case-insensitive. + Features are a forward-compatibility mechanism; each feature will eventually + become a standard part of the control protocol. Once a feature becomes part + of the protocol, it is always-on. Each feature documents the version it was + introduced as a feature and the version in which it became part of the + protocol. + + Tor will ignore a request to use any feature that is always-on. Tor will give + a 552 error in response to an unrecognized feature. EXTENDED_EVENTS Same as passing 'EXTENDED' to SETEVENTS; this is the preferred way to request the extended event syntax. - This feature was first used in 0.1.2.3-alpha. It is always-on in - Tor 0.2.2.1-alpha and later. + This feature was first introduced in 0.1.2.3-alpha. It is always-on + and part of the protocol in Tor 0.2.2.1-alpha and later. VERBOSE_NAMES - Instead of ServerID as specified above, the controller should - identify ORs by LongName in events and GETINFO results. This format is - strictly more informative: rather than including Nickname for - known Named routers and Fingerprint for unknown or unNamed routers, the - LongName format includes a Fingerprint, an indication of Named status, - and a Nickname (if one is known). + Replaces ServerID with LongName in events and GETINFO results. LongName + provides a Fingerprint for all routers, an indication of Named status, + and a Nickname if one is known. LongName is strictly more informative + than ServerID, which only provides either a Fingerprint or a Nickname. - This will not be always-enabled until at least two stable - releases after 0.1.2.2-alpha, the release where it was first - available. It is always-on in Tor 0.2.2.1-alpha and later. + This feature was first introduced in 0.1.2.2-alpha. It is always-on and + part of the protocol in Tor 0.2.2.1-alpha and later. 3.20. RESOLVE @@ -1000,7 +1015,11 @@ "FAILED" / ; circuit closed (was not built) "CLOSED" ; circuit closed (was built) - Path = ServerID *("," ServerID) + Path = LongName *("," LongName) + ; In Tor versions 0.1.2.2-alpha through 0.2.2.1-alpha with feature + ; VERBOSE_NAMES turned off and before version 0.1.2.2-alpha, Path + ; is as follows: + Path = ServerID *("," ServerID) Reason = "NONE" / "TORPROTOCOL" / "INTERNAL" / "REQUESTED" / "HIBERNATING" / "RESOURCELIMIT" / "CONNECTFAILED" / @@ -1089,19 +1108,26 @@ 4.1.3. OR Connection status changed The syntax is: - "650" SP "ORCONN" SP (ServerID / Target) SP ORStatus [ SP "REASON=" + + "650" SP "ORCONN" SP (LongName / Target) SP ORStatus [ SP "REASON=" Reason ] [ SP "NCIRCS=" NumCircuits ] CRLF ORStatus = "NEW" / "LAUNCHED" / "CONNECTED" / "FAILED" / "CLOSED" + ; In Tor versions 0.1.2.2-alpha through 0.2.2.1-alpha with feature + ; VERBOSE_NAMES turned off and before version 0.1.2.2-alpha, OR + ; Connection is as follows: + "650" SP "ORCONN" SP (ServerID / Target) SP ORStatus [ SP "REASON=" + Reason ] [ SP "NCIRCS=" NumCircuits ] CRLF + NEW is for incoming connections, and LAUNCHED is for outgoing connections. CONNECTED means the TLS handshake has finished (in either direction). FAILED means a connection is being closed that hasn't finished its handshake, and CLOSED is for connections that have handshaked. - A ServerID is specified unless it's a NEW connection, in which - case we don't know what server it is yet, so we use Address:Port. + A LongName or ServerID is specified unless it's a NEW connection, in + which case we don't know what server it is yet, so we use Address:Port. If extended events are enabled (see 3.19), optional reason and circuit counting information is provided for CLOSED and FAILED @@ -1138,7 +1164,11 @@ 4.1.6. New descriptors available Syntax: - "650" SP "NEWDESC" 1*(SP ServerID) CRLF + "650" SP "NEWDESC" 1*(SP LongName) CRLF + ; In Tor versions 0.1.2.2-alpha through 0.2.2.1-alpha with feature + ; VERBOSE_NAMES turned off and before version 0.1.2.2-alpha, it + ; is as follows: + "650" SP "NEWDESC" 1*(SP ServerID) CRLF 4.1.7. New Address mapping diff --git a/src/common/compat.c b/src/common/compat.c index 20394b4c5d..4d556a85e6 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -1679,6 +1679,30 @@ tor_lookup_hostname(const char *name, uint32_t *addr) return -1; } +/** Initialize the insecure libc RNG. */ +void +tor_init_weak_random(unsigned seed) +{ +#ifdef MS_WINDOWS + srand(seed); +#else + srandom(seed); +#endif +} + +/** Return a randomly chosen value in the range 0..TOR_RAND_MAX. This + * entropy will not be cryptographically strong; do not rely on it + * for anything an adversary should not be able to predict. */ +long +tor_weak_random(void) +{ +#ifdef MS_WINDOWS + return rand(); +#else + return random(); +#endif +} + /** Hold the result of our call to <b>uname</b>. */ static char uname_result[256]; /** True iff uname_result is set. */ diff --git a/src/common/compat.h b/src/common/compat.h index 7d59501e2b..449bf748f4 100644 --- a/src/common/compat.h +++ b/src/common/compat.h @@ -480,6 +480,11 @@ typedef enum { SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED = 0x08, } socks5_reply_status_t; +/* ===== Insecure rng */ +void tor_init_weak_random(unsigned seed); +long tor_weak_random(void); +#define TOR_RAND_MAX (RAND_MAX) + /* ===== OS compatibility */ const char *get_uname(void); diff --git a/src/common/crypto.c b/src/common/crypto.c index b49547fa4d..81a432d8d4 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -1935,6 +1935,14 @@ crypto_dh_free(crypto_dh_env_t *dh) OPENSSL_VERSION_NUMBER <= 0x00907fffl) || \ (OPENSSL_VERSION_NUMBER >= 0x0090803fl)) +static void +seed_weak_rng(void) +{ + unsigned seed; + crypto_rand((void*)&seed, sizeof(seed)); + tor_init_weak_random(seed); +} + /** Seed OpenSSL's random number generator with bytes from the operating * system. <b>startup</b> should be true iff we have just started Tor and * have not yet allocated a bunch of fds. Return 0 on success, -1 on failure. @@ -1985,6 +1993,7 @@ crypto_seed_rng(int startup) } RAND_seed(buf, sizeof(buf)); memset(buf, 0, sizeof(buf)); + seed_weak_rng(); return 0; #else for (i = 0; filenames[i]; ++i) { @@ -2001,6 +2010,7 @@ crypto_seed_rng(int startup) } RAND_seed(buf, (int)sizeof(buf)); memset(buf, 0, sizeof(buf)); + seed_weak_rng(); return 0; } diff --git a/src/or/control.c b/src/or/control.c index 4d505a98fb..ad316c4ebc 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -2855,9 +2855,10 @@ connection_control_process_inbuf(control_connection_t *conn) && !TOR_ISSPACE(conn->incoming_cmd[cmd_len])) ++cmd_len; - data_len -= cmd_len; conn->incoming_cmd[cmd_len]='\0'; args = conn->incoming_cmd+cmd_len+1; + tor_assert(data_len>(size_t)cmd_len); + data_len -= (cmd_len+1); /* skip the command and NUL we added after it */ while (*args == ' ' || *args == '\t') { ++args; --data_len; diff --git a/src/or/dirserv.c b/src/or/dirserv.c index fd4b53a482..841c86624b 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -1166,7 +1166,7 @@ directory_fetches_from_authorities(or_options_t *options) return 0; if (server_mode(options) && router_pick_published_address(options, &addr)<0) return 1; /* we don't know our IP address; ask an authority. */ - refuseunknown = router_my_exit_policy_is_reject_star() && + refuseunknown = ! router_my_exit_policy_is_reject_star() && should_refuse_unknown_exits(options); if (options->DirPort == 0 && !refuseunknown) return 0; diff --git a/src/or/hibernate.c b/src/or/hibernate.c index e9be5930d1..929c1994c3 100644 --- a/src/or/hibernate.c +++ b/src/or/hibernate.c @@ -515,7 +515,6 @@ accounting_run_housekeeping(time_t now) static void accounting_set_wakeup_time(void) { - char buf[ISO_TIME_LEN+1]; char digest[DIGEST_LEN]; crypto_digest_env_t *d_env; int time_in_interval; @@ -529,21 +528,26 @@ accounting_set_wakeup_time(void) } } - format_iso_time(buf, interval_start_time); - crypto_pk_get_digest(get_server_identity_key(), digest); + if (server_identity_key_is_set()) { + char buf[ISO_TIME_LEN+1]; + format_iso_time(buf, interval_start_time); - d_env = crypto_new_digest_env(); - crypto_digest_add_bytes(d_env, buf, ISO_TIME_LEN); - crypto_digest_add_bytes(d_env, digest, DIGEST_LEN); - crypto_digest_get_digest(d_env, digest, DIGEST_LEN); - crypto_free_digest_env(d_env); + crypto_pk_get_digest(get_server_identity_key(), digest); + + d_env = crypto_new_digest_env(); + crypto_digest_add_bytes(d_env, buf, ISO_TIME_LEN); + crypto_digest_add_bytes(d_env, digest, DIGEST_LEN); + crypto_digest_get_digest(d_env, digest, DIGEST_LEN); + crypto_free_digest_env(d_env); + } else { + crypto_rand(digest, DIGEST_LEN); + } if (!expected_bandwidth_usage) { char buf1[ISO_TIME_LEN+1]; char buf2[ISO_TIME_LEN+1]; format_local_iso_time(buf1, interval_start_time); format_local_iso_time(buf2, interval_end_time); - time_to_exhaust_bw = GUESS_TIME_TO_USE_BANDWIDTH; interval_wakeup_time = interval_start_time; log_notice(LD_ACCT, @@ -558,8 +562,8 @@ accounting_set_wakeup_time(void) time_to_exhaust_bw = (get_options()->AccountingMax/expected_bandwidth_usage)*60; - if (time_to_exhaust_bw > TIME_MAX) { - time_to_exhaust_bw = TIME_MAX; + if (time_to_exhaust_bw > INT_MAX) { + time_to_exhaust_bw = INT_MAX; time_to_consider = 0; } else { time_to_consider = time_in_interval - (int)time_to_exhaust_bw; @@ -577,8 +581,6 @@ accounting_set_wakeup_time(void) * to be chosen than the last half. */ interval_wakeup_time = interval_start_time + (get_uint32(digest) % time_to_consider); - - format_iso_time(buf, interval_wakeup_time); } { diff --git a/src/or/relay.c b/src/or/relay.c index 467f8847c8..a65280e2a3 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -1478,10 +1478,11 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn, crypt_path_t *layer_hint) { edge_connection_t *conn; - int n_streams, n_streams_left; + int n_packaging_streams, n_streams_left; int packaged_this_round; int cells_on_queue; int cells_per_conn; + edge_connection_t *chosen_stream = NULL; /* How many cells do we have space for? It will be the minimum of * the number needed to exhaust the package window, and the minimum @@ -1496,26 +1497,61 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn, if (CELL_QUEUE_HIGHWATER_SIZE - cells_on_queue < max_to_package) max_to_package = CELL_QUEUE_HIGHWATER_SIZE - cells_on_queue; + /* Once we used to start listening on the streams in the order they + * appeared in the linked list. That leads to starvation on the + * streams that appeared later on the list, since the first streams + * would always get to read first. Instead, we just pick a random + * stream on the list, and enable reading for streams starting at that + * point (and wrapping around as if the list were circular). It would + * probably be better to actually remember which streams we've + * serviced in the past, but this is simple and effective. */ + + /* Select a stream uniformly at random from the linked list. We + * don't need cryptographic randomness here. */ + { + int num_streams = 0; + for (conn = first_conn; conn; conn = conn->next_stream) { + num_streams++; + if ((tor_weak_random() % num_streams)==0) + chosen_stream = conn; + /* Invariant: chosen_stream has been chosen uniformly at random from + * among the first num_streams streams on first_conn. */ + } + } + /* Count how many non-marked streams there are that have anything on * their inbuf, and enable reading on all of the connections. */ - n_streams = 0; - for (conn=first_conn; conn; conn=conn->next_stream) { + n_packaging_streams = 0; + /* Activate reading starting from the chosen stream */ + for (conn=chosen_stream; conn; conn = conn->next_stream) { + /* Start reading for the streams starting from here */ + if (conn->_base.marked_for_close || conn->package_window <= 0) + continue; + if (!layer_hint || conn->cpath_layer == layer_hint) { + connection_start_reading(TO_CONN(conn)); + + if (buf_datalen(conn->_base.inbuf) > 0) + ++n_packaging_streams; + } + } + /* Go back and do the ones we skipped, circular-style */ + for (conn = first_conn; conn != chosen_stream; conn = conn->next_stream) { if (conn->_base.marked_for_close || conn->package_window <= 0) continue; if (!layer_hint || conn->cpath_layer == layer_hint) { connection_start_reading(TO_CONN(conn)); if (buf_datalen(conn->_base.inbuf) > 0) - ++n_streams; + ++n_packaging_streams; } } - if (n_streams == 0) /* avoid divide-by-zero */ + if (n_packaging_streams == 0) /* avoid divide-by-zero */ return 0; again: - cells_per_conn = CEIL_DIV(max_to_package, n_streams); + cells_per_conn = CEIL_DIV(max_to_package, n_packaging_streams); packaged_this_round = 0; n_streams_left = 0; @@ -1563,7 +1599,7 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn, if (packaged_this_round && packaged_this_round < max_to_package && n_streams_left) { max_to_package -= packaged_this_round; - n_streams = n_streams_left; + n_packaging_streams = n_streams_left; goto again; } diff --git a/src/or/rephist.c b/src/or/rephist.c index 22b3ec5217..5a57b954fd 100644 --- a/src/or/rephist.c +++ b/src/or/rephist.c @@ -1943,9 +1943,8 @@ dump_pk_ops(int severity) #define EXIT_STATS_ROUND_UP_STREAMS 4 /** Number of TCP ports */ #define EXIT_STATS_NUM_PORTS 65536 -/** Reciprocal of threshold (= 0.01%) of total bytes that a port needs to - * see in order to be included in exit stats. */ -#define EXIT_STATS_THRESHOLD_RECIPROCAL 10000 +/** Top n ports that will be included in exit stats. */ +#define EXIT_STATS_TOP_N_PORTS 10 /* The following data structures are arrays and no fancy smartlists or maps, * so that all write operations can be done in constant time. This comes at @@ -1995,15 +1994,23 @@ rep_hist_exit_stats_term(void) tor_free(exit_streams); } +/** Helper for qsort: compare two ints. */ +static int +_compare_int(const void *x, const void *y) { + return (*(int*)x - *(int*)y); +} + /** Return a newly allocated string containing the exit port statistics * until <b>now</b>, or NULL if we're not collecting exit stats. */ char * rep_hist_format_exit_stats(time_t now) { - int i; - uint64_t total_bytes = 0, threshold_bytes, other_read = 0, - other_written = 0; - uint32_t other_streams = 0; + int i, j, top_elements = 0, cur_min_idx = 0, cur_port; + uint64_t top_bytes[EXIT_STATS_TOP_N_PORTS]; + int top_ports[EXIT_STATS_TOP_N_PORTS]; + uint64_t cur_bytes = 0, other_read = 0, other_written = 0, + total_read = 0, total_written = 0; + uint32_t total_streams = 0, other_streams = 0; char *buf; smartlist_t *written_strings, *read_strings, *streams_strings; char *written_string, *read_string, *streams_string; @@ -2013,52 +2020,101 @@ rep_hist_format_exit_stats(time_t now) if (!start_of_exit_stats_interval) return NULL; /* Not initialized. */ - /* Count total number of bytes, so that we can attribute observations - * below or equal to a threshold of 1 / EXIT_STATS_THRESHOLD_RECIPROCAL - * of all bytes to a special port 'other'. */ + /* Go through all ports to find the n ports that saw most written and + * read bytes. + * + * Invariant: at the end of the loop for iteration i, + * total_read is the sum of all exit_bytes_read[0..i] + * total_written is the sum of all exit_bytes_written[0..i] + * total_stream is the sum of all exit_streams[0..i] + * + * top_elements = MAX(EXIT_STATS_TOP_N_PORTS, + * #{j | 0 <= j <= i && volume(i) > 0}) + * + * For all 0 <= j < top_elements, + * top_bytes[j] > 0 + * 0 <= top_ports[j] <= 65535 + * top_bytes[j] = volume(top_ports[j]) + * + * There is no j in 0..i and k in 0..top_elements such that: + * volume(j) > top_bytes[k] AND j is not in top_ports[0..top_elements] + * + * There is no j!=cur_min_idx in 0..top_elements such that: + * top_bytes[j] < top_bytes[cur_min_idx] + * + * where volume(x) == exit_bytes_read[x]+exit_bytes_written[x] + * + * Worst case: O(EXIT_STATS_NUM_PORTS * EXIT_STATS_TOP_N_PORTS) + */ for (i = 1; i < EXIT_STATS_NUM_PORTS; i++) { - total_bytes += exit_bytes_read[i]; - total_bytes += exit_bytes_written[i]; + total_read += exit_bytes_read[i]; + total_written += exit_bytes_written[i]; + total_streams += exit_streams[i]; + cur_bytes = exit_bytes_read[i] + exit_bytes_written[i]; + if (cur_bytes == 0) { + continue; + } + if (top_elements < EXIT_STATS_TOP_N_PORTS) { + top_bytes[top_elements] = cur_bytes; + top_ports[top_elements++] = i; + } else if (cur_bytes > top_bytes[cur_min_idx]) { + top_bytes[cur_min_idx] = cur_bytes; + top_ports[cur_min_idx] = i; + } else { + continue; + } + cur_min_idx = 0; + for (j = 1; j < top_elements; j++) { + if (top_bytes[j] < top_bytes[cur_min_idx]) { + cur_min_idx = j; + } + } } - threshold_bytes = total_bytes / EXIT_STATS_THRESHOLD_RECIPROCAL; - /* Add observations of all ports above the threshold to smartlists and - * join them to single strings. Also count bytes and streams of ports - * below or equal to the threshold. */ + /* Add observations of top ports to smartlists. */ written_strings = smartlist_create(); read_strings = smartlist_create(); streams_strings = smartlist_create(); - for (i = 1; i < EXIT_STATS_NUM_PORTS; i++) { - if (exit_bytes_read[i] + exit_bytes_written[i] > threshold_bytes) { - if (exit_bytes_written[i] > 0) { - uint64_t num = round_uint64_to_next_multiple_of( - exit_bytes_written[i], EXIT_STATS_ROUND_UP_BYTES); - num /= 1024; - buf = NULL; - tor_asprintf(&buf, "%d="U64_FORMAT, i, U64_PRINTF_ARG(num)); - smartlist_add(written_strings, buf); - } - if (exit_bytes_read[i] > 0) { - uint64_t num = round_uint64_to_next_multiple_of( - exit_bytes_read[i], EXIT_STATS_ROUND_UP_BYTES); - num /= 1024; - buf = NULL; - tor_asprintf(&buf, "%d="U64_FORMAT, i, U64_PRINTF_ARG(num)); - smartlist_add(read_strings, buf); - } - if (exit_streams[i] > 0) { - uint32_t num = round_uint32_to_next_multiple_of(exit_streams[i], - EXIT_STATS_ROUND_UP_STREAMS); - buf = NULL; - tor_asprintf(&buf, "%d=%u", i, num); - smartlist_add(streams_strings, buf); - } - } else { - other_read += exit_bytes_read[i]; - other_written += exit_bytes_written[i]; - other_streams += exit_streams[i]; + other_read = total_read; + other_written = total_written; + other_streams = total_streams; + /* Sort the ports; this puts them out of sync with top_bytes, but we + * won't be using top_bytes again anyway */ + qsort(top_ports, top_elements, sizeof(int), _compare_int); + for (j = 0; j < top_elements; j++) { + cur_port = top_ports[j]; + if (exit_bytes_written[cur_port] > 0) { + uint64_t num = round_uint64_to_next_multiple_of( + exit_bytes_written[cur_port], + EXIT_STATS_ROUND_UP_BYTES); + num /= 1024; + buf = NULL; + tor_asprintf(&buf, "%d="U64_FORMAT, cur_port, U64_PRINTF_ARG(num)); + smartlist_add(written_strings, buf); + other_written -= exit_bytes_written[cur_port]; + } + if (exit_bytes_read[cur_port] > 0) { + uint64_t num = round_uint64_to_next_multiple_of( + exit_bytes_read[cur_port], + EXIT_STATS_ROUND_UP_BYTES); + num /= 1024; + buf = NULL; + tor_asprintf(&buf, "%d="U64_FORMAT, cur_port, U64_PRINTF_ARG(num)); + smartlist_add(read_strings, buf); + other_read -= exit_bytes_read[cur_port]; + } + if (exit_streams[cur_port] > 0) { + uint32_t num = round_uint32_to_next_multiple_of( + exit_streams[cur_port], + EXIT_STATS_ROUND_UP_STREAMS); + buf = NULL; + tor_asprintf(&buf, "%d=%u", cur_port, num); + smartlist_add(streams_strings, buf); + other_streams -= exit_streams[cur_port]; } } + + /* Add observations of other ports in a single element. */ other_written = round_uint64_to_next_multiple_of(other_written, EXIT_STATS_ROUND_UP_BYTES); other_written /= 1024; @@ -2076,6 +2132,8 @@ rep_hist_format_exit_stats(time_t now) buf = NULL; tor_asprintf(&buf, "other=%u", other_streams); smartlist_add(streams_strings, buf); + + /* Join all observations in single strings. */ written_string = smartlist_join_strings(written_strings, ",", 0, NULL); read_string = smartlist_join_strings(read_strings, ",", 0, NULL); streams_string = smartlist_join_strings(streams_strings, ",", 0, NULL); diff --git a/src/or/router.c b/src/or/router.c index 3d4ee70399..66ef8ec52e 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -1523,7 +1523,7 @@ router_rebuild_descriptor(int force) /* Let bridges serve their own descriptors unencrypted, so they can * pass reachability testing. (If they want to be harder to notice, * they can always leave the DirPort off). */ - if (!options->BridgeRelay) + if (ei && !options->BridgeRelay) ei->cache_info.send_unencrypted = 1; router_get_router_hash(ri->cache_info.signed_descriptor_body, diff --git a/src/test/test.c b/src/test/test.c index 8d8c46fca2..8782ef5077 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -1081,6 +1081,7 @@ test_stats(void) { time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */ char *s = NULL; + int i; /* We shouldn't collect exit stats without initializing them. */ rep_hist_note_exit_stream_opened(80); @@ -1103,6 +1104,22 @@ test_stats(void) "exit-streams-opened 80=4,443=4,other=0\n", s); tor_free(s); + /* Add a few bytes on 10 more ports and ensure that only the top 10 + * ports are contained in the history string. */ + for (i = 50; i < 60; i++) { + rep_hist_note_exit_bytes(i, i, i); + rep_hist_note_exit_stream_opened(i); + } + s = rep_hist_format_exit_stats(now + 86400); + test_streq("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n" + "exit-kibibytes-written 52=1,53=1,54=1,55=1,56=1,57=1,58=1," + "59=1,80=1,443=1,other=1\n" + "exit-kibibytes-read 52=1,53=1,54=1,55=1,56=1,57=1,58=1," + "59=1,80=10,443=20,other=1\n" + "exit-streams-opened 52=4,53=4,54=4,55=4,56=4,57=4,58=4," + "59=4,80=4,443=4,other=4\n", s); + tor_free(s); + /* Stop collecting stats, add some bytes, and ensure we don't generate * a history string. */ rep_hist_exit_stats_term(); diff --git a/src/win32/orconfig.h b/src/win32/orconfig.h index cdf1cbfb91..b3cd1db50b 100644 --- a/src/win32/orconfig.h +++ b/src/win32/orconfig.h @@ -233,5 +233,5 @@ #define USING_TWOS_COMPLEMENT /* Version number of package */ -#define VERSION "0.2.2.18-alpha-dev" +#define VERSION "0.2.2.19-alpha" |