summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog61
-rw-r--r--changes/50534
-rw-r--r--changes/50559
-rw-r--r--changes/bsd_queue7
-rw-r--r--changes/bug72353
-rw-r--r--changes/dist-geoip63
-rw-r--r--changes/ewma_policy_c993
-rw-r--r--configure.ac2
-rw-r--r--contrib/tor-mingw.nsi.in2
-rw-r--r--src/common/aes.c4
-rw-r--r--src/common/compat.c2
-rw-r--r--src/common/crypto.c81
-rw-r--r--src/common/crypto.h3
-rw-r--r--src/common/mempool.c3
-rw-r--r--src/common/tortls.c4
-rw-r--r--src/common/util.c19
-rw-r--r--src/common/util.h2
-rw-r--r--src/config/include.am4
-rw-r--r--src/or/buffers.c6
-rw-r--r--src/or/channel.c32
-rw-r--r--src/or/channeltls.c2
-rw-r--r--src/or/circuitlist.c22
-rw-r--r--src/or/config.c2
-rw-r--r--src/or/connection.c70
-rw-r--r--src/or/connection.h48
-rw-r--r--src/or/connection_edge.c4
-rw-r--r--src/or/connection_or.c16
-rw-r--r--src/or/main.c2
-rw-r--r--src/or/networkstatus.c2
-rw-r--r--src/or/onion.c24
-rw-r--r--src/or/relay.c12
-rw-r--r--src/or/relay.h5
-rw-r--r--src/or/rendclient.c14
-rw-r--r--src/or/rendservice.c58
-rw-r--r--src/or/routerparse.c2
-rw-r--r--src/or/transports.c9
-rw-r--r--src/test/test.c5
-rw-r--r--src/tools/tor-gencert.c6
-rw-r--r--src/win32/orconfig.h2
39 files changed, 397 insertions, 162 deletions
diff --git a/ChangeLog b/ChangeLog
index 0541c448c3..0d6221bb18 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,64 @@
+Changes in version 0.2.4.6-alpha - 2012-11-13
+ Tor 0.2.4.6-alpha fixes an assert bug that has been plaguing relays,
+ makes our defense-in-depth memory wiping more reliable, and begins to
+ count IPv6 addresses in bridge statistics,
+
+ o Major bugfixes:
+ - Fix an assertion failure that could occur when closing a connection
+ with a spliced rendezvous circuit. Fix for bug 7212; bugfix on
+ Tor 0.2.4.4-alpha.
+ - Tor tries to wipe potentially sensitive data after using it, so
+ that if some subsequent security failure exposes Tor's memory,
+ the damage will be limited. But we had a bug where the compiler
+ was eliminating these wipe operations when it decided that the
+ memory was no longer visible to a (correctly running) program,
+ hence defeating our attempt at defense in depth. We fix that
+ by using OpenSSL's OPENSSL_cleanse() operation, which a compiler
+ is unlikely to optimize away. Future versions of Tor may use
+ a less ridiculously heavy approach for this. Fixes bug 7352.
+ Reported in an article by Andrey Karpov.
+
+ o Minor features:
+ - Add GeoIP database for IPv6 addresses. The new config option
+ is GeoIPv6File.
+ - Bridge statistics now count bridge clients connecting over IPv6:
+ bridge statistics files now list "bridge-ip-versions" and
+ extra-info documents list "geoip6-db-digest". The control protocol
+ "CLIENTS_SEEN" and "ip-to-country" queries now support IPv6. Initial
+ implementation by "shkoo", addressing ticket 5055.
+
+ o Minor bugfixes:
+ - Warn when we are binding low ports when hibernation is enabled;
+ previously we had warned when we were _advertising_ low ports with
+ hibernation enabled. Fixes bug 7285; bugfix on 0.2.3.9-alpha.
+ - Fix a harmless bug when opting against publishing a relay descriptor
+ because DisableNetwork is set. Fixes bug 7464; bugfix on
+ 0.2.3.9-alpha.
+ - Add warning message when a managed proxy dies during configuration.
+ Fixes bug 7195; bugfix on 0.2.4.2-alpha.
+ - Fix a linking error when building tor-fw-helper without miniupnp.
+ Fixes bug 7235; bugfix on 0.2.4.2-alpha. Fix by Anthony G. Basile.
+ - Check for closing an or_connection_t without going through correct
+ channel functions; emit a warning and then call
+ connection_or_close_for_error() so we don't assert as in bugs 7212
+ and 7267.
+ - Compile correctly on compilers without C99 designated initializer
+ support. Fixes bug 7286; bugfix on 0.2.4.4-alpha.
+ - Avoid a possible assert that can occur when channel_send_destroy() is
+ called on a channel in CHANNEL_STATE_CLOSING, CHANNEL_STATE_CLOSED,
+ or CHANNEL_STATE_ERROR when the Tor process is resumed after being
+ blocked for a long interval. Fixes bug 7350; bugfix on 0.2.4.4-alpha.
+ - Fix a memory leak on failing cases of channel_tls_process_certs_cell.
+ Fixes bug 7422; bugfix on 0.2.4.4-alpha.
+
+ o Code simplification and refactoring:
+ - Start using OpenBSD's implementation of queue.h, so that we don't
+ need to hand-roll our own pointer and list structures whenever we
+ need them. (We can't rely on a sys/queue.h, since some operating
+ systems don't have them, and the ones that do have them don't all
+ present the same extensions.)
+
+
Changes in version 0.2.4.5-alpha - 2012-10-25
Tor 0.2.4.5-alpha comes hard at the heels of 0.2.4.4-alpha, to fix
two important security vulnerabilities that could lead to remotely
diff --git a/changes/5053 b/changes/5053
deleted file mode 100644
index c695f3ca9f..0000000000
--- a/changes/5053
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor features (IPv6):
- - Bridge clients connecting over IPv6 are now counted in bridge
- statistics. Implementation by shkoo, addressing ticket 5053.
- Included in 0.2.3.14-alpha.
diff --git a/changes/5055 b/changes/5055
deleted file mode 100644
index d51fef4cf8..0000000000
--- a/changes/5055
+++ /dev/null
@@ -1,9 +0,0 @@
- o Minor features (IPv6):
- - Add GeoIP database for IPv6 addresses and use it. The new config
- option is GeoIPv6File.
- Bridge clients connecting over IPv6 are now counted in bridge
- statistics. Bridge statistics files now list "bridge-ip-versions"
- and extra-info documents list "geoip6-db-digest".
- The control protocol has been extended to support more IPv6
- ("CLIENTS_SEEN" and "ip-to-country").
- Initial implementation by shkoo, addressing ticket 5055.
diff --git a/changes/bsd_queue b/changes/bsd_queue
deleted file mode 100644
index 024ca6fa5f..0000000000
--- a/changes/bsd_queue
+++ /dev/null
@@ -1,7 +0,0 @@
- o Code simplification and refactoring:
- - Start using OpenBSD's implementation of queue.h, so that we don't
- need to hand-roll our own pointer and list structures whenever we
- need them. (We can't rely on a sys/queue.h, since some operating
- systems don't have them, and the ones that do have them don't all
- present the same extensions.)
-
diff --git a/changes/bug7235 b/changes/bug7235
deleted file mode 100644
index 15d610090b..0000000000
--- a/changes/bug7235
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfixes (build):
- - Fix a linking error when building tor-fw-helper without miniupnp.
- Fixes bug 7235; bugfix on 0.2.4.2-alpha. Fix by Anthony G. Basile.
diff --git a/changes/dist-geoip6 b/changes/dist-geoip6
new file mode 100644
index 0000000000..2f2bf8f99f
--- /dev/null
+++ b/changes/dist-geoip6
@@ -0,0 +1,3 @@
+ o Minor bugfixes:
+ - Distribute and install the geoip6 IPv6 GeoIP database. Bugfix
+ on 0.2.4.6-alpha.
diff --git a/changes/ewma_policy_c99 b/changes/ewma_policy_c99
deleted file mode 100644
index 49177b388b..0000000000
--- a/changes/ewma_policy_c99
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfixes:
- - Compile correctly on compilers without C99 designated initializer
- support. Fixes bug 7286; bugfix on 0.2.4.4-alpha.
diff --git a/configure.ac b/configure.ac
index 105528e142..9963a97d49 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3,7 +3,7 @@ dnl Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson
dnl Copyright (c) 2007-2012, The Tor Project, Inc.
dnl See LICENSE for licensing information
-AC_INIT([tor],[0.2.4.5-alpha-dev])
+AC_INIT([tor],[0.2.4.6-alpha-dev])
AC_CONFIG_SRCDIR([src/or/main.c])
AM_INIT_AUTOMAKE
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
diff --git a/contrib/tor-mingw.nsi.in b/contrib/tor-mingw.nsi.in
index 427fa43d00..c22d0c5dcd 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.4.5-alpha-dev"
+!define VERSION "0.2.4.6-alpha-dev"
!define INSTALLER "tor-${VERSION}-win32.exe"
!define WEBSITE "https://www.torproject.org/"
!define LICENSE "LICENSE"
diff --git a/src/common/aes.c b/src/common/aes.c
index 8e489baae1..2d64b85944 100644
--- a/src/common/aes.c
+++ b/src/common/aes.c
@@ -106,7 +106,7 @@ aes_cipher_free(aes_cnt_cipher_t *cipher)
if (!cipher)
return;
EVP_CIPHER_CTX_cleanup(&cipher->evp);
- memset(cipher, 0, sizeof(aes_cnt_cipher_t));
+ memwipe(cipher, 0, sizeof(aes_cnt_cipher_t));
tor_free(cipher);
}
void
@@ -373,7 +373,7 @@ aes_cipher_free(aes_cnt_cipher_t *cipher)
if (cipher->using_evp) {
EVP_CIPHER_CTX_cleanup(&cipher->key.evp);
}
- memset(cipher, 0, sizeof(aes_cnt_cipher_t));
+ memwipe(cipher, 0, sizeof(aes_cnt_cipher_t));
tor_free(cipher);
}
diff --git a/src/common/compat.c b/src/common/compat.c
index b8674a2f5f..89f9cfa3d4 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -332,7 +332,7 @@ tor_munmap_file(tor_mmap_t *handle)
{
char *d = (char*)handle->data;
tor_free(d);
- memset(handle, 0, sizeof(tor_mmap_t));
+ memwipe(handle, 0, sizeof(tor_mmap_t));
tor_free(handle);
}
#endif
diff --git a/src/common/crypto.c b/src/common/crypto.c
index c5844046e8..6c3dd8d4a4 100644
--- a/src/common/crypto.c
+++ b/src/common/crypto.c
@@ -444,7 +444,7 @@ crypto_cipher_free(crypto_cipher_t *env)
tor_assert(env->cipher);
aes_cipher_free(env->cipher);
- memset(env, 0, sizeof(crypto_cipher_t));
+ memwipe(env, 0, sizeof(crypto_cipher_t));
tor_free(env);
}
@@ -544,7 +544,7 @@ crypto_pk_read_private_key_from_filename(crypto_pk_t *env,
/* Try to parse it. */
r = crypto_pk_read_private_key_from_string(env, contents, -1);
- memset(contents, 0, strlen(contents));
+ memwipe(contents, 0, strlen(contents));
tor_free(contents);
if (r)
return -1; /* read_private_key_from_string already warned, so we don't.*/
@@ -686,7 +686,7 @@ crypto_pk_write_private_key_to_filename(crypto_pk_t *env,
s[len]='\0';
r = write_str_to_file(fname, s, 0);
BIO_free(bio);
- memset(s, 0, strlen(s));
+ memwipe(s, 0, strlen(s));
tor_free(s);
return r;
}
@@ -1012,7 +1012,7 @@ crypto_pk_private_sign_digest(crypto_pk_t *env, char *to, size_t tolen,
if (crypto_digest(digest,from,fromlen)<0)
return -1;
r = crypto_pk_private_sign(env,to,tolen,digest,DIGEST_LEN);
- memset(digest, 0, sizeof(digest));
+ memwipe(digest, 0, sizeof(digest));
return r;
}
@@ -1076,14 +1076,14 @@ crypto_pk_public_hybrid_encrypt(crypto_pk_t *env,
from+pkeylen-overhead-CIPHER_KEY_LEN, symlen);
if (r<0) goto err;
- memset(buf, 0, pkeylen);
+ memwipe(buf, 0, pkeylen);
tor_free(buf);
crypto_cipher_free(cipher);
tor_assert(outlen+symlen < INT_MAX);
return (int)(outlen + symlen);
err:
- memset(buf, 0, pkeylen);
+ memwipe(buf, 0, pkeylen);
tor_free(buf);
crypto_cipher_free(cipher);
return -1;
@@ -1134,13 +1134,13 @@ crypto_pk_private_hybrid_decrypt(crypto_pk_t *env,
r = crypto_cipher_decrypt(cipher, to+outlen, from+pkeylen, fromlen-pkeylen);
if (r<0)
goto err;
- memset(buf,0,pkeylen);
+ memwipe(buf,0,pkeylen);
tor_free(buf);
crypto_cipher_free(cipher);
tor_assert(outlen + fromlen < INT_MAX);
return (int)(outlen + (fromlen-pkeylen));
err:
- memset(buf,0,pkeylen);
+ memwipe(buf,0,pkeylen);
tor_free(buf);
crypto_cipher_free(cipher);
return -1;
@@ -1540,7 +1540,7 @@ crypto_digest_free(crypto_digest_t *digest)
{
if (!digest)
return;
- memset(digest, 0, sizeof(crypto_digest_t));
+ memwipe(digest, 0, sizeof(crypto_digest_t));
tor_free(digest);
}
@@ -1602,7 +1602,7 @@ crypto_digest_get_digest(crypto_digest_t *digest,
break;
}
memcpy(out, r, out_len);
- memset(r, 0, sizeof(r));
+ memwipe(r, 0, sizeof(r));
}
/** Allocate and return a new digest object with the same state as
@@ -2187,7 +2187,7 @@ crypto_dh_compute_secret(int severity, crypto_dh_t *dh,
if (pubkey_bn)
BN_free(pubkey_bn);
if (secret_tmp) {
- memset(secret_tmp, 0, secret_tmp_len);
+ memwipe(secret_tmp, 0, secret_tmp_len);
tor_free(secret_tmp);
}
if (result < 0)
@@ -2222,15 +2222,15 @@ crypto_expand_key_material(const char *key_in, size_t key_in_len,
goto err;
memcpy(cp, digest, MIN(DIGEST_LEN, key_out_len-(cp-key_out)));
}
- memset(tmp, 0, key_in_len+1);
+ memwipe(tmp, 0, key_in_len+1);
tor_free(tmp);
- memset(digest, 0, sizeof(digest));
+ memwipe(digest, 0, sizeof(digest));
return 0;
err:
- memset(tmp, 0, key_in_len+1);
+ memwipe(tmp, 0, key_in_len+1);
tor_free(tmp);
- memset(digest, 0, sizeof(digest));
+ memwipe(digest, 0, sizeof(digest));
return -1;
}
@@ -2320,7 +2320,7 @@ crypto_seed_rng(int startup)
return rand_poll_status ? 0 : -1;
}
RAND_seed(buf, sizeof(buf));
- memset(buf, 0, sizeof(buf));
+ memwipe(buf, 0, sizeof(buf));
seed_weak_rng();
return 0;
#else
@@ -2337,7 +2337,7 @@ crypto_seed_rng(int startup)
return -1;
}
RAND_seed(buf, (int)sizeof(buf));
- memset(buf, 0, sizeof(buf));
+ memwipe(buf, 0, sizeof(buf));
seed_weak_rng();
return 0;
}
@@ -2820,7 +2820,7 @@ base32_decode(char *dest, size_t destlen, const char *src, size_t srclen)
}
}
- memset(tmp, 0, srclen);
+ memwipe(tmp, 0, srclen);
tor_free(tmp);
tmp = NULL;
return 0;
@@ -2865,11 +2865,54 @@ secret_to_key(char *key_out, size_t key_out_len, const char *secret,
}
}
crypto_digest_get_digest(d, key_out, key_out_len);
- memset(tmp, 0, tmplen);
+ memwipe(tmp, 0, tmplen);
tor_free(tmp);
crypto_digest_free(d);
}
+/**
+ * Destroy the <b>sz</b> bytes of data stored at <b>mem</b>, setting them to
+ * the value <b>byte</b>.
+ *
+ * This function is preferable to memset, since many compilers will happily
+ * optimize out memset() when they can convince themselves that the data being
+ * cleared will never be read.
+ *
+ * Right now, our convention is to use this function when we are wiping data
+ * that's about to become inaccessible, such as stack buffers that are about
+ * to go out of scope or structures that are about to get freed. (In
+ * practice, it appears that the compilers we're currently using will optimize
+ * out the memset()s for stack-allocated buffers, but not those for
+ * about-to-be-freed structures. That could change, though, so we're being
+ * wary.) If there are live reads for the data, then you can just use
+ * memset().
+ */
+void
+memwipe(void *mem, uint8_t byte, size_t sz)
+{
+ /* Because whole-program-optimization exists, we may not be able to just
+ * have this function call "memset". A smart compiler could inline it, then
+ * eliminate dead memsets, and declare itself to be clever. */
+
+ /* This is a slow and ugly function from OpenSSL that fills 'mem' with junk
+ * based on the pointer value, then uses that junk to update a global
+ * variable. It's an elaborate ruse to trick the compiler into not
+ * optimizing out the "wipe this memory" code. Read it if you like zany
+ * programming tricks! In later versions of Tor, we should look for better
+ * not-optimized-out memory wiping stuff. */
+ OPENSSL_cleanse(mem, sz);
+ /* Just in case some caller of memwipe() is relying on getting a buffer
+ * filled with a particular value, fill the buffer.
+ *
+ * If this function gets inlined, this memset might get eliminated, but
+ * that's okay: We only care about this particular memset in the case where
+ * the caller should have been using memset(), and the memset() wouldn't get
+ * eliminated. In other words, this is here so that we won't break anything
+ * if somebody accidentally calls memwipe() instead of memset().
+ **/
+ memset(mem, byte, sz);
+}
+
#ifdef TOR_IS_MULTITHREADED
/** Helper: OpenSSL uses this callback to manipulate mutexes. */
static void
diff --git a/src/common/crypto.h b/src/common/crypto.h
index 0782ee57f1..4c5fa6ad97 100644
--- a/src/common/crypto.h
+++ b/src/common/crypto.h
@@ -273,6 +273,9 @@ int digest256_from_base64(char *digest, const char *d64);
void secret_to_key(char *key_out, size_t key_out_len, const char *secret,
size_t secret_len, const char *s2k_specifier);
+/** OpenSSL-based utility functions. */
+void memwipe(void *mem, uint8_t byte, size_t sz);
+
#ifdef CRYPTO_PRIVATE
/* Prototypes for private functions only used by tortls.c, crypto.c, and the
* unit tests. */
diff --git a/src/common/mempool.c b/src/common/mempool.c
index 0d2580dcaf..78d4da6f76 100644
--- a/src/common/mempool.c
+++ b/src/common/mempool.c
@@ -8,6 +8,7 @@
#include <stdlib.h>
#include <string.h>
#include "torint.h"
+#include "crypto.h"
#define MEMPOOL_PRIVATE
#include "mempool.h"
@@ -509,7 +510,7 @@ mp_pool_destroy(mp_pool_t *pool)
destroy_chunks(pool->empty_chunks);
destroy_chunks(pool->used_chunks);
destroy_chunks(pool->full_chunks);
- memset(pool, 0xe0, sizeof(mp_pool_t));
+ memwipe(pool, 0xe0, sizeof(mp_pool_t));
FREE(pool);
}
diff --git a/src/common/tortls.c b/src/common/tortls.c
index d4f02d3d38..76924b3177 100644
--- a/src/common/tortls.c
+++ b/src/common/tortls.c
@@ -713,7 +713,7 @@ tor_cert_free(tor_cert_t *cert)
if (cert->cert)
X509_free(cert->cert);
tor_free(cert->encoded);
- memset(cert, 0x03, sizeof(*cert));
+ memwipe(cert, 0x03, sizeof(*cert));
tor_free(cert);
}
@@ -2450,7 +2450,7 @@ tor_tls_get_tlssecrets(tor_tls_t *tls, uint8_t *secrets_out)
(char*)tls->ssl->session->master_key,
tls->ssl->session->master_key_length,
buf, len);
- memset(buf, 0, sizeof(buf));
+ memwipe(buf, 0, sizeof(buf));
return 0;
}
diff --git a/src/common/util.c b/src/common/util.c
index 75eb233bef..1b0603a469 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -4461,6 +4461,25 @@ tor_split_lines(smartlist_t *sl, char *buf, int len)
return smartlist_len(sl);
}
+/** Return a string corresponding to <b>stream_status</b>. */
+const char *
+stream_status_to_string(enum stream_status stream_status)
+{
+ switch (stream_status) {
+ case IO_STREAM_OKAY:
+ return "okay";
+ case IO_STREAM_EAGAIN:
+ return "temporarily unavailable";
+ case IO_STREAM_TERM:
+ return "terminated";
+ case IO_STREAM_CLOSED:
+ return "closed";
+ default:
+ tor_fragile_assert();
+ return "unknown";
+ }
+}
+
#ifdef _WIN32
/** Return a smartlist containing lines outputted from
diff --git a/src/common/util.h b/src/common/util.h
index aa2087b013..fabfdb19fd 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -307,6 +307,8 @@ enum stream_status {
IO_STREAM_CLOSED
};
+const char *stream_status_to_string(enum stream_status stream_status);
+
enum stream_status get_string_from_pipe(FILE *stream, char *buf, size_t count);
/** Return values from file_status(); see that function's documentation
diff --git a/src/config/include.am b/src/config/include.am
index e6e1fe0440..35961b829a 100644
--- a/src/config/include.am
+++ b/src/config/include.am
@@ -2,12 +2,12 @@ confdir = $(sysconfdir)/tor
tordatadir = $(datadir)/tor
-EXTRA_DIST+= src/config/geoip
+EXTRA_DIST+= src/config/geoip src/config/geoip6
# fallback-consensus
conf_DATA = src/config/torrc.sample
-tordata_DATA = src/config/geoip
+tordata_DATA = src/config/geoip src/config/geoip6
# fallback_consensus
# If we don't have it, fake it.
diff --git a/src/or/buffers.c b/src/or/buffers.c
index a8d06cef1e..f03047a641 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -1544,14 +1544,14 @@ socks_request_free(socks_request_t *req)
if (!req)
return;
if (req->username) {
- memset(req->username, 0x10, req->usernamelen);
+ memwipe(req->username, 0x10, req->usernamelen);
tor_free(req->username);
}
if (req->password) {
- memset(req->password, 0x04, req->passwordlen);
+ memwipe(req->password, 0x04, req->passwordlen);
tor_free(req->password);
}
- memset(req, 0xCC, sizeof(socks_request_t));
+ memwipe(req, 0xCC, sizeof(socks_request_t));
tor_free(req);
}
diff --git a/src/or/channel.c b/src/or/channel.c
index cbf7f99be1..16dd9f903a 100644
--- a/src/or/channel.c
+++ b/src/or/channel.c
@@ -2585,17 +2585,29 @@ channel_send_destroy(circid_t circ_id, channel_t *chan, int reason)
tor_assert(chan);
- memset(&cell, 0, sizeof(cell_t));
- cell.circ_id = circ_id;
- cell.command = CELL_DESTROY;
- cell.payload[0] = (uint8_t) reason;
- log_debug(LD_OR,
- "Sending destroy (circID %d) on channel %p "
- "(global ID " U64_FORMAT ")",
- circ_id, chan,
- U64_PRINTF_ARG(chan->global_identifier));
+ /* Check to make sure we can send on this channel first */
+ if (!(chan->state == CHANNEL_STATE_CLOSING ||
+ chan->state == CHANNEL_STATE_CLOSED ||
+ chan->state == CHANNEL_STATE_ERROR)) {
+ memset(&cell, 0, sizeof(cell_t));
+ cell.circ_id = circ_id;
+ cell.command = CELL_DESTROY;
+ cell.payload[0] = (uint8_t) reason;
+ log_debug(LD_OR,
+ "Sending destroy (circID %d) on channel %p "
+ "(global ID " U64_FORMAT ")",
+ circ_id, chan,
+ U64_PRINTF_ARG(chan->global_identifier));
- channel_write_cell(chan, &cell);
+ channel_write_cell(chan, &cell);
+ } else {
+ log_warn(LD_BUG,
+ "Someone called channel_send_destroy() for circID %d "
+ "on a channel " U64_FORMAT " at %p in state %s (%d)",
+ circ_id, U64_PRINTF_ARG(chan->global_identifier),
+ chan, channel_state_to_string(chan->state),
+ chan->state);
+ }
return 0;
}
diff --git a/src/or/channeltls.c b/src/or/channeltls.c
index d094d15af0..ede245894e 100644
--- a/src/or/channeltls.c
+++ b/src/or/channeltls.c
@@ -1522,7 +1522,7 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
safe_str(chan->conn->base_.address), \
chan->conn->base_.port, (s)); \
connection_or_close_for_error(chan->conn, 0); \
- return; \
+ goto err; \
} while (0)
if (chan->conn->base_.state != OR_CONN_STATE_OR_HANDSHAKING_V3)
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index 3ec2bf15bb..abb83954a4 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -637,11 +637,11 @@ circuit_free(circuit_t *circ)
tor_free(ocirc->dest_address);
if (ocirc->socks_username) {
- memset(ocirc->socks_username, 0x12, ocirc->socks_username_len);
+ memwipe(ocirc->socks_username, 0x12, ocirc->socks_username_len);
tor_free(ocirc->socks_username);
}
if (ocirc->socks_password) {
- memset(ocirc->socks_password, 0x06, ocirc->socks_password_len);
+ memwipe(ocirc->socks_password, 0x06, ocirc->socks_password_len);
tor_free(ocirc->socks_password);
}
} else {
@@ -682,7 +682,7 @@ circuit_free(circuit_t *circ)
* "active" checks will be violated. */
cell_queue_clear(&circ->n_chan_cells);
- memset(mem, 0xAA, memlen); /* poison memory */
+ memwipe(mem, 0xAA, memlen); /* poison memory */
tor_free(mem);
}
@@ -746,7 +746,7 @@ circuit_free_cpath_node(crypt_path_t *victim)
crypto_dh_free(victim->dh_handshake_state);
extend_info_free(victim->extend_info);
- memset(victim, 0xBB, sizeof(crypt_path_t)); /* poison memory */
+ memwipe(victim, 0xBB, sizeof(crypt_path_t)); /* poison memory */
tor_free(victim);
}
@@ -1411,7 +1411,12 @@ circuit_mark_for_close_(circuit_t *circ, int reason, int line,
}
if (circ->n_chan) {
circuit_clear_cell_queue(circ, circ->n_chan);
- channel_send_destroy(circ->n_circ_id, circ->n_chan, reason);
+ /* Only send destroy if the channel isn't closing anyway */
+ if (!(circ->n_chan->state == CHANNEL_STATE_CLOSING ||
+ circ->n_chan->state == CHANNEL_STATE_CLOSED ||
+ circ->n_chan->state == CHANNEL_STATE_ERROR)) {
+ channel_send_destroy(circ->n_circ_id, circ->n_chan, reason);
+ }
circuitmux_detach_circuit(circ->n_chan->cmux, circ);
}
@@ -1439,7 +1444,12 @@ circuit_mark_for_close_(circuit_t *circ, int reason, int line,
if (or_circ->p_chan) {
circuit_clear_cell_queue(circ, or_circ->p_chan);
- channel_send_destroy(or_circ->p_circ_id, or_circ->p_chan, reason);
+ /* Only send destroy if the channel isn't closing anyway */
+ if (!(or_circ->p_chan->state == CHANNEL_STATE_CLOSING ||
+ or_circ->p_chan->state == CHANNEL_STATE_CLOSED ||
+ or_circ->p_chan->state == CHANNEL_STATE_ERROR)) {
+ channel_send_destroy(or_circ->p_circ_id, or_circ->p_chan, reason);
+ }
circuitmux_detach_circuit(or_circ->p_chan->cmux, circ);
}
} else {
diff --git a/src/or/config.c b/src/or/config.c
index dca49f5cf4..bf32fae0e2 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -5004,7 +5004,7 @@ check_server_ports(const smartlist_t *ports,
continue;
}
#ifndef _WIN32
- if (!port->no_advertise && port->port < 1024)
+ if (!port->no_listen && port->port < 1024)
++n_low_port;
#endif
} SMARTLIST_FOREACH_END(port);
diff --git a/src/or/connection.c b/src/or/connection.c
index 1fbce418a4..bb175d0d6d 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -574,7 +574,7 @@ connection_free_(connection_t *conn)
}
#endif
- memset(mem, 0xCC, memlen); /* poison memory */
+ memwipe(mem, 0xCC, memlen); /* poison memory */
tor_free(mem);
}
@@ -688,6 +688,41 @@ connection_mark_for_close_(connection_t *conn, int line, const char *file)
tor_assert(line < 1<<16); /* marked_for_close can only fit a uint16_t. */
tor_assert(file);
+ if (conn->type == CONN_TYPE_OR) {
+ /*
+ * An or_connection should have been closed through one of the channel-
+ * aware functions in connection_or.c. We'll assume this is an error
+ * close and do that, and log a bug warning.
+ */
+ log_warn(LD_CHANNEL | LD_BUG,
+ "Something tried to close an or_connection_t without going "
+ "through channels at %s:%d",
+ file, line);
+ connection_or_close_for_error(TO_OR_CONN(conn), 0);
+ } else {
+ /* Pass it down to the real function */
+ connection_mark_for_close_internal_(conn, line, file);
+ }
+}
+
+/** Mark <b>conn</b> to be closed next time we loop through
+ * conn_close_if_marked() in main.c; the _internal version bypasses the
+ * CONN_TYPE_OR checks; this should be called when you either are sure that
+ * if this is an or_connection_t the controlling channel has been notified
+ * (e.g. with connection_or_notify_error()), or you actually are the
+ * connection_or_close_for_error() or connection_or_close_normally function.
+ * For all other cases, use connection_mark_and_flush() instead, which
+ * checks for or_connection_t properly, instead. See below.
+ */
+void
+connection_mark_for_close_internal_(connection_t *conn,
+ int line, const char *file)
+{
+ assert_connection_ok(conn,0);
+ tor_assert(line);
+ tor_assert(line < 1<<16); /* marked_for_close can only fit a uint16_t. */
+ tor_assert(file);
+
if (conn->marked_for_close) {
log(LOG_WARN,LD_BUG,"Duplicate call to connection_mark_for_close at %s:%d"
" (first at %s:%d)", file, line, conn->marked_for_close_file,
@@ -702,7 +737,8 @@ connection_mark_for_close_(connection_t *conn, int line, const char *file)
* this so we can find things that call this wrongly when the asserts hit.
*/
log_debug(LD_CHANNEL,
- "Calling connection_mark_for_close on an OR conn at %s:%d",
+ "Calling connection_mark_for_close_internal_() on an OR conn "
+ "at %s:%d",
file, line);
}
@@ -2727,7 +2763,11 @@ connection_handle_read_impl(connection_t *conn)
}
}
connection_close_immediate(conn); /* Don't flush; connection is dead. */
- connection_mark_for_close(conn);
+ /*
+ * This can bypass normal channel checking since we did
+ * connection_or_notify_error() above.
+ */
+ connection_mark_for_close_internal(conn);
return -1;
}
n_read += buf_datalen(conn->inbuf) - before;
@@ -3243,7 +3283,11 @@ connection_handle_write_impl(connection_t *conn, int force)
tor_socket_strerror(e));
connection_close_immediate(conn);
- connection_mark_for_close(conn);
+ /*
+ * This can bypass normal channel checking since we did
+ * connection_or_notify_error() above.
+ */
+ connection_mark_for_close_internal(conn);
return -1;
} else {
return 0; /* no change, see if next time is better */
@@ -3270,7 +3314,11 @@ connection_handle_write_impl(connection_t *conn, int force)
"TLS error in connection_tls_"
"continue_handshake()");
connection_close_immediate(conn);
- connection_mark_for_close(conn);
+ /*
+ * This can bypass normal channel checking since we did
+ * connection_or_notify_error() above.
+ */
+ connection_mark_for_close_internal(conn);
return -1;
}
return 0;
@@ -3300,7 +3348,11 @@ connection_handle_write_impl(connection_t *conn, int force)
"TLS error in during flush" :
"TLS closed during flush");
connection_close_immediate(conn);
- connection_mark_for_close(conn);
+ /*
+ * This can bypass normal channel checking since we did
+ * connection_or_notify_error() above.
+ */
+ connection_mark_for_close_internal(conn);
return -1;
case TOR_TLS_WANTWRITE:
log_debug(LD_NET,"wanted write.");
@@ -3365,7 +3417,11 @@ connection_handle_write_impl(connection_t *conn, int force)
"connection_flushed_some()");
}
- connection_mark_for_close(conn);
+ /*
+ * This can bypass normal channel checking since we did
+ * connection_or_notify_error() above.
+ */
+ connection_mark_for_close_internal(conn);
}
}
diff --git a/src/or/connection.h b/src/or/connection.h
index 6ed9e4a41f..b0c2a42838 100644
--- a/src/or/connection.h
+++ b/src/or/connection.h
@@ -31,21 +31,53 @@ void connection_free(connection_t *conn);
void connection_free_all(void);
void connection_about_to_close_connection(connection_t *conn);
void connection_close_immediate(connection_t *conn);
-void connection_mark_for_close_(connection_t *conn,int line, const char *file);
+void connection_mark_for_close_(connection_t *conn,
+ int line, const char *file);
+void connection_mark_for_close_internal_(connection_t *conn,
+ int line, const char *file);
#define connection_mark_for_close(c) \
connection_mark_for_close_((c), __LINE__, SHORT_FILE__)
+#define connection_mark_for_close_internal(c) \
+ connection_mark_for_close_internal_((c), __LINE__, SHORT_FILE__)
/**
* Mark 'c' for close, but try to hold it open until all the data is written.
+ * Use the _internal versions of connection_mark_for_close; this should be
+ * called when you either are sure that if this is an or_connection_t the
+ * controlling channel has been notified (e.g. with
+ * connection_or_notify_error()), or you actually are the
+ * connection_or_close_for_error() or connection_or_close_normally function.
+ * For all other cases, use connection_mark_and_flush() instead, which
+ * checks for or_connection_t properly, instead. See below.
*/
-#define connection_mark_and_flush_(c,line,file) \
- do { \
- connection_t *tmp_conn_ = (c); \
- connection_mark_for_close_(tmp_conn_, (line), (file)); \
- tmp_conn_->hold_open_until_flushed = 1; \
- IF_HAS_BUFFEREVENT(tmp_conn_, \
- connection_start_writing(tmp_conn_)); \
+#define connection_mark_and_flush_internal_(c,line,file) \
+ do { \
+ connection_t *tmp_conn_ = (c); \
+ connection_mark_for_close_internal_(tmp_conn_, (line), (file)); \
+ tmp_conn_->hold_open_until_flushed = 1; \
+ IF_HAS_BUFFEREVENT(tmp_conn_, \
+ connection_start_writing(tmp_conn_)); \
+ } while (0)
+
+#define connection_mark_and_flush_internal(c) \
+ connection_mark_and_flush_internal_((c), __LINE__, SHORT_FILE__)
+
+/**
+ * Mark 'c' for close, but try to hold it open until all the data is written.
+ */
+#define connection_mark_and_flush_(c,line,file) \
+ do { \
+ connection_t *tmp_conn_ = (c); \
+ if (tmp_conn_->type == CONN_TYPE_OR) { \
+ log_warn(LD_CHANNEL | LD_BUG, \
+ "Something tried to close (and flush) an or_connection_t" \
+ " without going through channels at %s:%d", \
+ file, line); \
+ connection_or_close_for_error(TO_OR_CONN(tmp_conn_), 1); \
+ } else { \
+ connection_mark_and_flush_internal_(c, line, file); \
+ } \
} while (0)
#define connection_mark_and_flush(c) \
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index 4d528a810e..162de2e009 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -3716,11 +3716,11 @@ circuit_clear_isolation(origin_circuit_t *circ)
circ->session_group = -1;
circ->nym_epoch = 0;
if (circ->socks_username) {
- memset(circ->socks_username, 0x11, circ->socks_username_len);
+ memwipe(circ->socks_username, 0x11, circ->socks_username_len);
tor_free(circ->socks_username);
}
if (circ->socks_password) {
- memset(circ->socks_password, 0x05, circ->socks_password_len);
+ memwipe(circ->socks_password, 0x05, circ->socks_password_len);
tor_free(circ->socks_password);
}
circ->socks_username_len = circ->socks_password_len = 0;
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index 9cd56bb89c..a50088d579 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -1143,8 +1143,8 @@ connection_or_close_normally(or_connection_t *orconn, int flush)
channel_t *chan = NULL;
tor_assert(orconn);
- if (flush) connection_mark_and_flush(TO_CONN(orconn));
- else connection_mark_for_close(TO_CONN(orconn));
+ if (flush) connection_mark_and_flush_internal(TO_CONN(orconn));
+ else connection_mark_for_close_internal(TO_CONN(orconn));
if (orconn->chan) {
chan = TLS_CHAN_TO_BASE(orconn->chan);
/* Don't transition if we're already in closing, closed or error */
@@ -1166,8 +1166,8 @@ connection_or_close_for_error(or_connection_t *orconn, int flush)
channel_t *chan = NULL;
tor_assert(orconn);
- if (flush) connection_mark_and_flush(TO_CONN(orconn));
- else connection_mark_for_close(TO_CONN(orconn));
+ if (flush) connection_mark_and_flush_internal(TO_CONN(orconn));
+ else connection_mark_for_close_internal(TO_CONN(orconn));
if (orconn->chan) {
chan = TLS_CHAN_TO_BASE(orconn->chan);
/* Don't transition if we're already in closing, closed or error */
@@ -1719,7 +1719,7 @@ or_handshake_state_free(or_handshake_state_t *state)
crypto_digest_free(state->digest_received);
tor_cert_free(state->auth_cert);
tor_cert_free(state->id_cert);
- memset(state, 0xBE, sizeof(or_handshake_state_t));
+ memwipe(state, 0xBE, sizeof(or_handshake_state_t));
tor_free(state);
}
@@ -1760,7 +1760,7 @@ or_handshake_state_record_cell(or_handshake_state_t *state,
this very often at all. */
cell_pack(&packed, cell);
crypto_digest_add_bytes(d, packed.body, sizeof(packed.body));
- memset(&packed, 0, sizeof(packed));
+ memwipe(&packed, 0, sizeof(packed));
}
/** Remember that a variable-length <b>cell</b> has been transmitted (if
@@ -1795,7 +1795,7 @@ or_handshake_state_record_var_cell(or_handshake_state_t *state,
crypto_digest_add_bytes(d, buf, sizeof(buf));
crypto_digest_add_bytes(d, (const char *)cell->payload, cell->payload_len);
- memset(buf, 0, sizeof(buf));
+ memwipe(buf, 0, sizeof(buf));
}
/** Set <b>conn</b>'s state to OR_CONN_STATE_OPEN, and tell other subsystems
@@ -2125,7 +2125,7 @@ connection_or_send_auth_challenge_cell(or_connection_t *conn)
connection_or_write_var_cell_to_buf(cell, conn);
var_cell_free(cell);
- memset(challenge, 0, sizeof(challenge));
+ memwipe(challenge, 0, sizeof(challenge));
return 0;
}
diff --git a/src/or/main.c b/src/or/main.c
index 0ba28db05e..fd8f9413de 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -1218,7 +1218,7 @@ run_scheduled_events(time_t now)
if (router_rebuild_descriptor(1)<0) {
log_info(LD_CONFIG, "Couldn't rebuild router descriptor");
}
- if (advertised_server_mode() & !options->DisableNetwork)
+ if (advertised_server_mode() && !options->DisableNetwork)
router_upload_dir_desc_to_dirservers(0);
}
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c
index 7296f9698c..f33de4c188 100644
--- a/src/or/networkstatus.c
+++ b/src/or/networkstatus.c
@@ -417,7 +417,7 @@ networkstatus_vote_free(networkstatus_t *ns)
digestmap_free(ns->desc_digest_map, NULL);
- memset(ns, 11, sizeof(*ns));
+ memwipe(ns, 11, sizeof(*ns));
tor_free(ns);
}
diff --git a/src/or/onion.c b/src/or/onion.c
index 17d8e777ad..cce4bdf73c 100644
--- a/src/or/onion.c
+++ b/src/or/onion.c
@@ -206,12 +206,12 @@ onion_skin_create(crypto_pk_t *dest_router_key,
PK_PKCS1_OAEP_PADDING, 1)<0)
goto err;
- memset(challenge, 0, sizeof(challenge));
+ memwipe(challenge, 0, sizeof(challenge));
*handshake_state_out = dh;
return 0;
err:
- memset(challenge, 0, sizeof(challenge));
+ memwipe(challenge, 0, sizeof(challenge));
if (dh) crypto_dh_free(dh);
return -1;
}
@@ -286,15 +286,15 @@ onion_skin_server_handshake(const char *onion_skin, /*ONIONSKIN_CHALLENGE_LEN*/
/* use the rest of the key material for our shared keys, digests, etc */
memcpy(key_out, key_material+DIGEST_LEN, key_out_len);
- memset(challenge, 0, sizeof(challenge));
- memset(key_material, 0, key_material_len);
+ memwipe(challenge, 0, sizeof(challenge));
+ memwipe(key_material, 0, key_material_len);
tor_free(key_material);
crypto_dh_free(dh);
return 0;
err:
- memset(challenge, 0, sizeof(challenge));
+ memwipe(challenge, 0, sizeof(challenge));
if (key_material) {
- memset(key_material, 0, key_material_len);
+ memwipe(key_material, 0, key_material_len);
tor_free(key_material);
}
if (dh) crypto_dh_free(dh);
@@ -340,11 +340,11 @@ onion_skin_client_handshake(crypto_dh_t *handshake_state,
/* use the rest of the key material for our shared keys, digests, etc */
memcpy(key_out, key_material+DIGEST_LEN, key_out_len);
- memset(key_material, 0, key_material_len);
+ memwipe(key_material, 0, key_material_len);
tor_free(key_material);
return 0;
err:
- memset(key_material, 0, key_material_len);
+ memwipe(key_material, 0, key_material_len);
tor_free(key_material);
return -1;
}
@@ -381,8 +381,8 @@ fast_server_handshake(const uint8_t *key_in, /* DIGEST_LEN bytes */
memcpy(key_out, out+DIGEST_LEN, key_out_len);
r = 0;
done:
- memset(tmp, 0, sizeof(tmp));
- memset(out, 0, out_len);
+ memwipe(tmp, 0, sizeof(tmp));
+ memwipe(out, 0, out_len);
tor_free(out);
return r;
}
@@ -426,8 +426,8 @@ fast_client_handshake(const uint8_t *handshake_state,/*DIGEST_LEN bytes*/
memcpy(key_out, out+DIGEST_LEN, key_out_len);
r = 0;
done:
- memset(tmp, 0, sizeof(tmp));
- memset(out, 0, out_len);
+ memwipe(tmp, 0, sizeof(tmp));
+ memwipe(out, 0, out_len);
tor_free(out);
return r;
}
diff --git a/src/or/relay.c b/src/or/relay.c
index bd99d91dca..0f0d1df414 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -1976,7 +1976,8 @@ cell_queue_pop(cell_queue_t *queue)
* circuit mux.
*/
void
-update_circuit_on_cmux(circuit_t *circ, cell_direction_t direction)
+update_circuit_on_cmux_(circuit_t *circ, cell_direction_t direction,
+ const char *file, int lineno)
{
channel_t *chan = NULL;
or_circuit_t *or_circ = NULL;
@@ -1999,7 +2000,11 @@ update_circuit_on_cmux(circuit_t *circ, cell_direction_t direction)
cmux = chan->cmux;
/* Cmux sanity check */
- tor_assert(circuitmux_is_circuit_attached(cmux, circ));
+ if (! circuitmux_is_circuit_attached(cmux, circ)) {
+ log_warn(LD_BUG, "called on non-attachd circuit from %s:%d",
+ file, lineno);
+ return;
+ }
tor_assert(circuitmux_attached_circuit_direction(cmux, circ) == direction);
assert_cmux_ok_paranoid(chan);
@@ -2334,7 +2339,8 @@ circuit_clear_cell_queue(circuit_t *circ, channel_t *chan)
cell_queue_clear(queue);
/* Update the cell counter in the cmux */
- update_circuit_on_cmux(circ, direction);
+ if (chan->cmux && circuitmux_is_circuit_attached(chan->cmux, circ))
+ update_circuit_on_cmux(circ, direction);
}
/** Fail with an assert if the circuit mux on chan is corrupt
diff --git a/src/or/relay.h b/src/or/relay.h
index 3906d6bf85..0f7b45fef3 100644
--- a/src/or/relay.h
+++ b/src/or/relay.h
@@ -54,7 +54,10 @@ void append_cell_to_circuit_queue(circuit_t *circ, channel_t *chan,
void channel_unlink_all_circuits(channel_t *chan);
int channel_flush_from_first_active_circuit(channel_t *chan, int max);
void assert_circuit_mux_okay(channel_t *chan);
-void update_circuit_on_cmux(circuit_t *circ, cell_direction_t direction);
+void update_circuit_on_cmux_(circuit_t *circ, cell_direction_t direction,
+ const char *file, int lineno);
+#define update_circuit_on_cmux(circ, direction) \
+ update_circuit_on_cmux_((circ), (direction), SHORT_FILE__, __LINE__)
int append_address_to_payload(uint8_t *payload_out, const tor_addr_t *addr);
const uint8_t *decode_address_from_payload(tor_addr_t *addr_out,
diff --git a/src/or/rendclient.c b/src/or/rendclient.c
index 915a41a0c3..3fb4025e69 100644
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@ -317,8 +317,8 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
circuit_mark_for_close(TO_CIRCUIT(introcirc), END_CIRC_REASON_INTERNAL);
circuit_mark_for_close(TO_CIRCUIT(rendcirc), END_CIRC_REASON_INTERNAL);
cleanup:
- memset(payload, 0, sizeof(payload));
- memset(tmp, 0, sizeof(tmp));
+ memwipe(payload, 0, sizeof(payload));
+ memwipe(tmp, 0, sizeof(tmp));
return status;
}
@@ -696,7 +696,7 @@ rend_client_refetch_v2_renddesc(const rend_data_t *rend_query)
rend_client_desc_trynow(rend_query->onion_address);
done:
- memset(descriptor_id, 0, sizeof(descriptor_id));
+ memwipe(descriptor_id, 0, sizeof(descriptor_id));
return;
}
@@ -936,10 +936,10 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const uint8_t *request,
circuit_try_attaching_streams(circ);
- memset(keys, 0, sizeof(keys));
+ memwipe(keys, 0, sizeof(keys));
return 0;
err:
- memset(keys, 0, sizeof(keys));
+ memwipe(keys, 0, sizeof(keys));
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL);
return -1;
}
@@ -1281,8 +1281,8 @@ rend_parse_service_authorization(const or_options_t *options,
} else {
strmap_free(parsed, rend_service_authorization_strmap_item_free);
}
- memset(descriptor_cookie_tmp, 0, sizeof(descriptor_cookie_tmp));
- memset(descriptor_cookie_base64ext, 0, sizeof(descriptor_cookie_base64ext));
+ memwipe(descriptor_cookie_tmp, 0, sizeof(descriptor_cookie_tmp));
+ memwipe(descriptor_cookie_base64ext, 0, sizeof(descriptor_cookie_base64ext));
return res;
}
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index fe0333ef40..09792bd1d7 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -161,7 +161,7 @@ rend_authorized_client_free(rend_authorized_client_t *client)
crypto_pk_free(client->client_key);
tor_strclear(client->client_name);
tor_free(client->client_name);
- memset(client->descriptor_cookie, 0, sizeof(client->descriptor_cookie));
+ memwipe(client->descriptor_cookie, 0, sizeof(client->descriptor_cookie));
tor_free(client);
}
@@ -699,10 +699,10 @@ rend_service_load_keys(rend_service_t *s)
tor_snprintf(buf, sizeof(buf),"%s.onion\n", s->service_id);
if (write_str_to_file(fname,buf,0)<0) {
log_warn(LD_CONFIG, "Could not write onion address to hostname file.");
- memset(buf, 0, sizeof(buf));
+ memwipe(buf, 0, sizeof(buf));
return -1;
}
- memset(buf, 0, sizeof(buf));
+ memwipe(buf, 0, sizeof(buf));
/* If client authorization is configured, load or generate keys. */
if (s->auth_type != REND_NO_AUTH) {
@@ -830,13 +830,13 @@ rend_service_load_auth_keys(rend_service_t *s, const char *hfname)
* len is string length, not buffer length, but last byte is NUL
* anyway.
*/
- memset(client_key_out, 0, len);
+ memwipe(client_key_out, 0, len);
tor_free(client_key_out);
goto err;
}
written = tor_snprintf(buf + written, sizeof(buf) - written,
"client-key\n%s", client_key_out);
- memset(client_key_out, 0, len);
+ memwipe(client_key_out, 0, len);
tor_free(client_key_out);
if (written < 0) {
log_warn(LD_BUG, "Could not write client entry.");
@@ -897,13 +897,13 @@ rend_service_load_auth_keys(rend_service_t *s, const char *hfname)
}
strmap_free(parsed_clients, rend_authorized_client_strmap_item_free);
- memset(cfname, 0, sizeof(cfname));
+ memwipe(cfname, 0, sizeof(cfname));
/* Clear stack buffers that held key-derived material. */
- memset(buf, 0, sizeof(buf));
- memset(desc_cook_out, 0, sizeof(desc_cook_out));
- memset(service_id, 0, sizeof(service_id));
- memset(extended_desc_cookie, 0, sizeof(extended_desc_cookie));
+ memwipe(buf, 0, sizeof(buf));
+ memwipe(desc_cook_out, 0, sizeof(desc_cook_out));
+ memwipe(service_id, 0, sizeof(service_id));
+ memwipe(extended_desc_cookie, 0, sizeof(extended_desc_cookie));
return r;
}
@@ -1406,13 +1406,13 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
tor_free(err_msg);
done:
- memset(keys, 0, sizeof(keys));
- memset(buf, 0, sizeof(buf));
- memset(serviceid, 0, sizeof(serviceid));
- memset(hexcookie, 0, sizeof(hexcookie));
- memset(intro_key_digest, 0, sizeof(intro_key_digest));
- memset(auth_data, 0, sizeof(auth_data));
- memset(diffie_hellman_hash, 0, sizeof(diffie_hellman_hash));
+ memwipe(keys, 0, sizeof(keys));
+ memwipe(buf, 0, sizeof(buf));
+ memwipe(serviceid, 0, sizeof(serviceid));
+ memwipe(hexcookie, 0, sizeof(hexcookie));
+ memwipe(intro_key_digest, 0, sizeof(intro_key_digest));
+ memwipe(auth_data, 0, sizeof(auth_data));
+ memwipe(diffie_hellman_hash, 0, sizeof(diffie_hellman_hash));
/* Free the parsed cell */
if (parsed_req) {
@@ -1540,7 +1540,7 @@ rend_service_free_intro(rend_intro_cell_t *request)
/* Have plaintext? */
if (request->plaintext) {
/* Zero it out just to be safe */
- memset(request->plaintext, 0, request->plaintext_len);
+ memwipe(request->plaintext, 0, request->plaintext_len);
tor_free(request->plaintext);
request->plaintext_len = 0;
}
@@ -1561,7 +1561,7 @@ rend_service_free_intro(rend_intro_cell_t *request)
break;
case 3:
if (request->u.v3.auth_data) {
- memset(request->u.v3.auth_data, 0, request->u.v3.auth_len);
+ memwipe(request->u.v3.auth_data, 0, request->u.v3.auth_len);
tor_free(request->u.v3.auth_data);
}
@@ -1577,7 +1577,7 @@ rend_service_free_intro(rend_intro_cell_t *request)
}
/* Zero it out to make sure sensitive stuff doesn't hang around in memory */
- memset(request, 0, sizeof(*request));
+ memwipe(request, 0, sizeof(*request));
tor_free(request);
}
@@ -2075,9 +2075,9 @@ rend_service_decrypt_intro(
else tor_free(err_msg);
/* clean up potentially sensitive material */
- memset(buf, 0, sizeof(buf));
- memset(key_digest, 0, sizeof(key_digest));
- memset(service_id, 0, sizeof(service_id));
+ memwipe(buf, 0, sizeof(buf));
+ memwipe(key_digest, 0, sizeof(key_digest));
+ memwipe(service_id, 0, sizeof(service_id));
return status;
}
@@ -2513,9 +2513,9 @@ rend_service_intro_has_opened(origin_circuit_t *circuit)
err:
circuit_mark_for_close(TO_CIRCUIT(circuit), reason);
done:
- memset(buf, 0, sizeof(buf));
- memset(auth, 0, sizeof(auth));
- memset(serviceid, 0, sizeof(serviceid));
+ memwipe(buf, 0, sizeof(buf));
+ memwipe(auth, 0, sizeof(auth));
+ memwipe(serviceid, 0, sizeof(serviceid));
return;
}
@@ -2665,9 +2665,9 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit)
err:
circuit_mark_for_close(TO_CIRCUIT(circuit), reason);
done:
- memset(buf, 0, sizeof(buf));
- memset(serviceid, 0, sizeof(serviceid));
- memset(hexcookie, 0, sizeof(hexcookie));
+ memwipe(buf, 0, sizeof(buf));
+ memwipe(serviceid, 0, sizeof(serviceid));
+ memwipe(hexcookie, 0, sizeof(hexcookie));
return;
}
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index 8d6cd1c7fa..a333780752 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -4637,7 +4637,7 @@ tor_version_parse(const char *s, tor_version_t *out)
if (close_paren-cp > HEX_DIGEST_LEN)
return -1;
hexlen = (int)(close_paren-cp);
- memset(digest, 0, sizeof(digest));
+ memwipe(digest, 0, sizeof(digest));
if ( hexlen == 0 || (hexlen % 2) == 1)
return -1;
if (base16_decode(digest, hexlen/2, cp, hexlen))
diff --git a/src/or/transports.c b/src/or/transports.c
index a532f87502..0319071097 100644
--- a/src/or/transports.c
+++ b/src/or/transports.c
@@ -614,8 +614,15 @@ configure_proxy(managed_proxy_t *mp)
tor_get_lines_from_handle(tor_process_get_stdout_pipe(mp->process_handle),
&stream_status);
if (!proxy_output) { /* failed to get input from proxy */
- if (stream_status != IO_STREAM_EAGAIN)
+ if (stream_status != IO_STREAM_EAGAIN) { /* bad stream status! */
mp->conf_state = PT_PROTO_BROKEN;
+ log_warn(LD_GENERAL, "The communication stream of managed proxy '%s' "
+ "is '%s'. Most probably the managed proxy stopped running. "
+ "This might be a bug of the managed proxy, a bug of Tor, or "
+ "a misconfiguration. Please enable logging on your managed "
+ "proxy and check the logs for errors.",
+ mp->argv[0], stream_status_to_string(stream_status));
+ }
goto done;
}
diff --git a/src/test/test.c b/src/test/test.c
index 9848770a84..1eaa65c783 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -1547,7 +1547,10 @@ test_geoip(void)
memset(&in6, 0, sizeof(in6));
/* Make sure that country ID actually works. */
-#define SET_TEST_IPV6(i) in6.s6_addr32[3] = htonl((uint32_t) i)
+#define SET_TEST_IPV6(i) \
+ do { \
+ set_uint32(in6.s6_addr + 12, htonl((uint32_t) (i))); \
+ } while (0)
#define CHECK_COUNTRY(country, val) do { \
/* test ipv4 country lookup */ \
test_streq(country, \
diff --git a/src/tools/tor-gencert.c b/src/tools/tor-gencert.c
index b1cf3a3887..91b1e3c234 100644
--- a/src/tools/tor-gencert.c
+++ b/src/tools/tor-gencert.c
@@ -105,7 +105,7 @@ load_passphrase(void)
cp = memchr(buf, '\n', n);
passphrase_len = cp-buf;
passphrase = tor_strndup(buf, passphrase_len);
- memset(buf, 0, sizeof(buf));
+ memwipe(buf, 0, sizeof(buf));
return 0;
}
@@ -113,7 +113,7 @@ static void
clear_passphrase(void)
{
if (passphrase) {
- memset(passphrase, 0, passphrase_len);
+ memwipe(passphrase, 0, passphrase_len);
tor_free(passphrase);
}
}
@@ -191,7 +191,7 @@ parse_commandline(int argc, char **argv)
}
}
- memset(&s, 0, sizeof(s));
+ memwipe(&s, 0, sizeof(s));
if (verbose)
set_log_severity_config(LOG_DEBUG, LOG_ERR, &s);
else
diff --git a/src/win32/orconfig.h b/src/win32/orconfig.h
index e4b2df78a9..8fe31a02f9 100644
--- a/src/win32/orconfig.h
+++ b/src/win32/orconfig.h
@@ -232,7 +232,7 @@
#define USING_TWOS_COMPLEMENT
/* Version number of package */
-#define VERSION "0.2.4.5-alpha-dev"
+#define VERSION "0.2.4.6-alpha-dev"