aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/compat.c1
-rw-r--r--src/common/container.h3
-rw-r--r--src/common/crypto.c3
-rw-r--r--src/common/workqueue.c21
-rw-r--r--src/common/workqueue.h19
-rw-r--r--src/ext/ed25519/donna/ed25519_tor.c2
-rw-r--r--src/ext/ed25519/donna/modm-donna-64bit.h4
-rw-r--r--src/or/buffers.c36
-rw-r--r--src/or/buffers.h2
-rw-r--r--src/or/channel.c1
-rw-r--r--src/or/circuituse.c11
-rw-r--r--src/or/config.c29
-rw-r--r--src/or/connection.c4
-rw-r--r--src/or/connection.h2
-rw-r--r--src/or/control.c7
-rw-r--r--src/or/control.h2
-rw-r--r--src/or/cpuworker.c4
-rw-r--r--src/or/dirserv.c8
-rw-r--r--src/or/dns.c116
-rw-r--r--src/or/dns.h18
-rw-r--r--src/or/dns_structs.h90
-rw-r--r--src/or/include.am5
-rw-r--r--src/or/main.c23
-rw-r--r--src/or/or.h7
-rw-r--r--src/or/rendcache.c2
-rw-r--r--src/or/rendclient.c9
-rw-r--r--src/or/rendservice.c33
-rw-r--r--src/or/routerkeys.c7
-rw-r--r--src/or/routerset.c11
-rw-r--r--src/or/routerset.h1
-rw-r--r--src/or/tor_main.c6
-rw-r--r--src/test/include.am15
-rwxr-xr-xsrc/test/test-network.sh16
-rw-r--r--src/test/test.c2
-rw-r--r--src/test/test_buffers.c11
-rw-r--r--src/test/test_checkdir.c4
-rw-r--r--src/test/test_dns.c311
-rwxr-xr-xsrc/test/test_keygen.sh27
-rw-r--r--src/test/test_util.c1
-rw-r--r--src/test/test_workqueue.c29
-rw-r--r--src/tools/tor-resolve.c2
41 files changed, 674 insertions, 231 deletions
diff --git a/src/common/compat.c b/src/common/compat.c
index 76f9bcb97e..7d72b4b7fd 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -3424,3 +3424,4 @@ tor_get_avail_disk_space(const char *path)
return -1;
#endif
}
+
diff --git a/src/common/container.h b/src/common/container.h
index 5abd8b48d9..bf4f04762c 100644
--- a/src/common/container.h
+++ b/src/common/container.h
@@ -110,7 +110,8 @@ void smartlist_sort_digests256(smartlist_t *sl);
void smartlist_sort_pointers(smartlist_t *sl);
const char *smartlist_get_most_frequent_string(smartlist_t *sl);
-const char *smartlist_get_most_frequent_string_(smartlist_t *sl, int *count_out);
+const char *smartlist_get_most_frequent_string_(smartlist_t *sl,
+ int *count_out);
const uint8_t *smartlist_get_most_frequent_digest256(smartlist_t *sl);
void smartlist_uniq_strings(smartlist_t *sl);
diff --git a/src/common/crypto.c b/src/common/crypto.c
index 6d4b0d7e16..815c2ec0c5 100644
--- a/src/common/crypto.c
+++ b/src/common/crypto.c
@@ -2440,7 +2440,8 @@ crypto_rand_uint64_range(uint64_t min, uint64_t max)
time_t
crypto_rand_time_range(time_t min, time_t max)
{
- return (time_t) crypto_rand_uint64_range(min, max);
+ tor_assert(min < max);
+ return min + (time_t)crypto_rand_uint64(max - min);
}
/** Return a pseudorandom 64-bit integer, chosen uniformly from the values
diff --git a/src/common/workqueue.c b/src/common/workqueue.c
index b0b004dc25..c467bdf43b 100644
--- a/src/common/workqueue.c
+++ b/src/common/workqueue.c
@@ -25,7 +25,7 @@ struct threadpool_s {
unsigned generation;
/** Function that should be run for updates on each thread. */
- int (*update_fn)(void *, void *);
+ workqueue_reply_t (*update_fn)(void *, void *);
/** Function to free update arguments if they can't be run. */
void (*free_update_arg_fn)(void *);
/** Array of n_threads update arguments. */
@@ -56,7 +56,7 @@ struct workqueue_entry_s {
/** True iff this entry is waiting for a worker to start processing it. */
uint8_t pending;
/** Function to run in the worker thread. */
- int (*fn)(void *state, void *arg);
+ workqueue_reply_t (*fn)(void *state, void *arg);
/** Function to run while processing the reply queue. */
void (*reply_fn)(void *arg);
/** Argument for the above functions. */
@@ -96,7 +96,7 @@ static void queue_reply(replyqueue_t *queue, workqueue_entry_t *work);
* <b>fn</b> in the worker thread, and <b>reply_fn</b> in the main
* thread. See threadpool_queue_work() for full documentation. */
static workqueue_entry_t *
-workqueue_entry_new(int (*fn)(void*, void*),
+workqueue_entry_new(workqueue_reply_t (*fn)(void*, void*),
void (*reply_fn)(void*),
void *arg)
{
@@ -172,7 +172,7 @@ worker_thread_main(void *thread_)
workerthread_t *thread = thread_;
threadpool_t *pool = thread->in_pool;
workqueue_entry_t *work;
- int result;
+ workqueue_reply_t result;
tor_mutex_acquire(&pool->lock);
while (1) {
@@ -182,13 +182,14 @@ worker_thread_main(void *thread_)
if (thread->in_pool->generation != thread->generation) {
void *arg = thread->in_pool->update_args[thread->index];
thread->in_pool->update_args[thread->index] = NULL;
- int (*update_fn)(void*,void*) = thread->in_pool->update_fn;
+ workqueue_reply_t (*update_fn)(void*,void*) =
+ thread->in_pool->update_fn;
thread->generation = thread->in_pool->generation;
tor_mutex_release(&pool->lock);
- int r = update_fn(thread->state, arg);
+ workqueue_reply_t r = update_fn(thread->state, arg);
- if (r < 0) {
+ if (r != WQ_RPL_REPLY) {
return;
}
@@ -208,7 +209,7 @@ worker_thread_main(void *thread_)
queue_reply(thread->reply_queue, work);
/* We may need to exit the thread. */
- if (result >= WQ_RPL_ERROR) {
+ if (result != WQ_RPL_REPLY) {
return;
}
tor_mutex_acquire(&pool->lock);
@@ -281,7 +282,7 @@ workerthread_new(void *state, threadpool_t *pool, replyqueue_t *replyqueue)
*/
workqueue_entry_t *
threadpool_queue_work(threadpool_t *pool,
- int (*fn)(void *, void *),
+ workqueue_reply_t (*fn)(void *, void *),
void (*reply_fn)(void *),
void *arg)
{
@@ -318,7 +319,7 @@ threadpool_queue_work(threadpool_t *pool,
int
threadpool_queue_update(threadpool_t *pool,
void *(*dup_fn)(void *),
- int (*fn)(void *, void *),
+ workqueue_reply_t (*fn)(void *, void *),
void (*free_fn)(void *),
void *arg)
{
diff --git a/src/common/workqueue.h b/src/common/workqueue.h
index 92e82b8a48..9ce1eadafc 100644
--- a/src/common/workqueue.h
+++ b/src/common/workqueue.h
@@ -15,21 +15,22 @@ typedef struct threadpool_s threadpool_t;
* pool. */
typedef struct workqueue_entry_s workqueue_entry_t;
-/** Possible return value from a work function: indicates success. */
-#define WQ_RPL_REPLY 0
-/** Possible return value from a work function: indicates fatal error */
-#define WQ_RPL_ERROR 1
-/** Possible return value from a work function: indicates thread is shutting
- * down. */
-#define WQ_RPL_SHUTDOWN 2
+/** Possible return value from a work function: */
+typedef enum {
+ WQ_RPL_REPLY = 0, /** indicates success */
+ WQ_RPL_ERROR = 1, /** indicates fatal error */
+ WQ_RPL_SHUTDOWN = 2, /** indicates thread is shutting down */
+} workqueue_reply_t;
workqueue_entry_t *threadpool_queue_work(threadpool_t *pool,
- int (*fn)(void *, void *),
+ workqueue_reply_t (*fn)(void *,
+ void *),
void (*reply_fn)(void *),
void *arg);
+
int threadpool_queue_update(threadpool_t *pool,
void *(*dup_fn)(void *),
- int (*fn)(void *, void *),
+ workqueue_reply_t (*fn)(void *, void *),
void (*free_fn)(void *),
void *arg);
void *workqueue_entry_cancel(workqueue_entry_t *pending_work);
diff --git a/src/ext/ed25519/donna/ed25519_tor.c b/src/ext/ed25519/donna/ed25519_tor.c
index 7f5894da79..12493f7d14 100644
--- a/src/ext/ed25519/donna/ed25519_tor.c
+++ b/src/ext/ed25519/donna/ed25519_tor.c
@@ -323,7 +323,7 @@ int
ed25519_donna_pubkey_from_curve25519_pubkey(unsigned char *out,
const unsigned char *inp, int signbit)
{
- static const bignum25519 one = { 1 };
+ static const bignum25519 ALIGN(16) one = { 1 };
bignum25519 ALIGN(16) u, uminus1, uplus1, inv_uplus1, y;
/* Prop228: y = (u-1)/(u+1) */
diff --git a/src/ext/ed25519/donna/modm-donna-64bit.h b/src/ext/ed25519/donna/modm-donna-64bit.h
index b22df2be75..012ea9ea08 100644
--- a/src/ext/ed25519/donna/modm-donna-64bit.h
+++ b/src/ext/ed25519/donna/modm-donna-64bit.h
@@ -261,6 +261,10 @@ contract256_slidingwindow_modm(signed char r[256], const bignum256modm s, int wi
continue;
for (b = 1; (b < (soplen - j)) && (b <= 6); b++) {
+ /* XXX Tor: coverity scan says that r[j+b] can
+ * overflow, but that's not possible: b < (soplen-j)
+ * guarantees that b + j < soplen, so b+j < 256,
+ * so the index doesn't overflow. */
if ((r[j] + (r[j + b] << b)) <= m) {
r[j] += r[j + b] << b;
r[j + b] = 0;
diff --git a/src/or/buffers.c b/src/or/buffers.c
index 2d7dd937d8..cc2f6f409b 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -178,13 +178,10 @@ preferred_chunk_size(size_t target)
/** Collapse data from the first N chunks from <b>buf</b> into buf->head,
* growing it as necessary, until buf->head has the first <b>bytes</b> bytes
* of data from the buffer, or until buf->head has all the data in <b>buf</b>.
- *
- * If <b>nulterminate</b> is true, ensure that there is a 0 byte in
- * buf->head->mem right after all the data. */
+ */
STATIC void
-buf_pullup(buf_t *buf, size_t bytes, int nulterminate)
+buf_pullup(buf_t *buf, size_t bytes)
{
- /* XXXX nothing uses nulterminate; remove it. */
chunk_t *dest, *src;
size_t capacity;
if (!buf->head)
@@ -194,17 +191,9 @@ buf_pullup(buf_t *buf, size_t bytes, int nulterminate)
if (buf->datalen < bytes)
bytes = buf->datalen;
- if (nulterminate) {
- capacity = bytes + 1;
- if (buf->head->datalen >= bytes && CHUNK_REMAINING_CAPACITY(buf->head)) {
- *CHUNK_WRITE_PTR(buf->head) = '\0';
- return;
- }
- } else {
- capacity = bytes;
- if (buf->head->datalen >= bytes)
- return;
- }
+ capacity = bytes;
+ if (buf->head->datalen >= bytes)
+ return;
if (buf->head->memlen >= capacity) {
/* We don't need to grow the first chunk, but we might need to repack it.*/
@@ -248,11 +237,6 @@ buf_pullup(buf_t *buf, size_t bytes, int nulterminate)
}
}
- if (nulterminate) {
- tor_assert(CHUNK_REMAINING_CAPACITY(buf->head));
- *CHUNK_WRITE_PTR(buf->head) = '\0';
- }
-
check();
}
@@ -1203,7 +1187,7 @@ fetch_from_buf_http(buf_t *buf,
/* Okay, we have a full header. Make sure it all appears in the first
* chunk. */
if ((int)buf->head->datalen < crlf_offset + 4)
- buf_pullup(buf, crlf_offset+4, 0);
+ buf_pullup(buf, crlf_offset+4);
headerlen = crlf_offset + 4;
headers = buf->head->data;
@@ -1451,7 +1435,7 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
do {
n_drain = 0;
- buf_pullup(buf, want_length, 0);
+ buf_pullup(buf, want_length);
tor_assert(buf->head && buf->head->datalen >= 2);
want_length = 0;
@@ -1842,7 +1826,7 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req,
log_warn(LD_PROTOCOL,
"Your application (using socks5 to port %d) gave Tor "
"a malformed hostname: %s. Rejecting the connection.",
- req->port, escaped(req->address));
+ req->port, escaped_safe_str_client(req->address));
return -1;
}
if (log_sockstype)
@@ -1870,7 +1854,7 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req,
*want_length_out = SOCKS4_NETWORK_LEN;
return 0; /* not yet */
}
- // buf_pullup(buf, 1280, 0);
+ // buf_pullup(buf, 1280);
req->command = (unsigned char) *(data+1);
if (req->command != SOCKS_COMMAND_CONNECT &&
req->command != SOCKS_COMMAND_RESOLVE) {
@@ -2038,7 +2022,7 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
if (buf->datalen < 2)
return 0;
- buf_pullup(buf, MAX_SOCKS_MESSAGE_LEN, 0);
+ buf_pullup(buf, MAX_SOCKS_MESSAGE_LEN);
tor_assert(buf->head && buf->head->datalen >= 2);
r = parse_socks_client((uint8_t*)buf->head->data, buf->head->datalen,
diff --git a/src/or/buffers.h b/src/or/buffers.h
index 6d0c68500b..7f79e3c0b2 100644
--- a/src/or/buffers.h
+++ b/src/or/buffers.h
@@ -101,7 +101,7 @@ void assert_buf_ok(buf_t *buf);
#ifdef BUFFERS_PRIVATE
STATIC int buf_find_string_offset(const buf_t *buf, const char *s, size_t n);
-STATIC void buf_pullup(buf_t *buf, size_t bytes, int nulterminate);
+STATIC void buf_pullup(buf_t *buf, size_t bytes);
void buf_get_first_chunk_data(const buf_t *buf, const char **cp, size_t *sz);
#define DEBUG_CHUNK_ALLOC
diff --git a/src/or/channel.c b/src/or/channel.c
index af095026e4..21522a5303 100644
--- a/src/or/channel.c
+++ b/src/or/channel.c
@@ -3069,6 +3069,7 @@ channel_free_list(smartlist_t *channels, int mark_for_close)
if (curr->cmux) {
circuitmux_detach_all_circuits(curr->cmux, NULL);
}
+ SMARTLIST_DEL_CURRENT(channels, curr);
channel_unregister(curr);
if (mark_for_close) {
if (!CHANNEL_CONDEMNED(curr)) {
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index a3b71974ca..00340fd689 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -2284,8 +2284,15 @@ connection_ap_handshake_attach_chosen_circuit(entry_connection_t *conn,
base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
- if (!circ->base_.timestamp_dirty)
- circ->base_.timestamp_dirty = time(NULL);
+ if (!circ->base_.timestamp_dirty ||
+ ((conn->entry_cfg.isolation_flags & ISO_SOCKSAUTH) &&
+ (conn->entry_cfg.socks_iso_keep_alive) &&
+ (conn->socks_request->usernamelen ||
+ conn->socks_request->passwordlen))) {
+ /* When stream isolation is in use and controlled by an application
+ * we are willing to keep using the stream. */
+ circ->base_.timestamp_dirty = approx_time();
+ }
pathbias_count_use_attempt(circ);
diff --git a/src/or/config.c b/src/or/config.c
index 6e782de0e0..98d9d83846 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -289,7 +289,7 @@ static config_var_t option_vars_[] = {
VAR("HiddenServiceMaxStreams",LINELIST_S, RendConfigLines, NULL),
VAR("HiddenServiceMaxStreamsCloseCircuit",LINELIST_S, RendConfigLines, NULL),
VAR("HiddenServiceNumIntroductionPoints", LINELIST_S, RendConfigLines, NULL),
- V(HiddenServiceStatistics, BOOL, "0"),
+ V(HiddenServiceStatistics, BOOL, "1"),
V(HidServAuth, LINELIST, NULL),
V(CloseHSClientCircuitsImmediatelyOnTimeout, BOOL, "0"),
V(CloseHSServiceRendCircuitsImmediatelyOnTimeout, BOOL, "0"),
@@ -3173,6 +3173,21 @@ options_validate(or_options_t *old_options, or_options_t *options,
"http://freehaven.net/anonbib/#hs-attack06 for details.");
}
+ if (options->EntryNodes &&
+ routerset_is_list(options->EntryNodes) &&
+ (routerset_len(options->EntryNodes) == 1) &&
+ (options->RendConfigLines != NULL)) {
+ tor_asprintf(msg,
+ "You have one single EntryNodes and at least one hidden service "
+ "configured. This is bad because it's very easy to locate your "
+ "entry guard which can then lead to the deanonymization of your "
+ "hidden service -- for more details, see "
+ "https://trac.torproject.org/projects/tor/ticket/14917. "
+ "For this reason, the use of one EntryNodes with an hidden "
+ "service is prohibited until a better solution is found.");
+ return -1;
+ }
+
if (!options->LearnCircuitBuildTimeout && options->CircuitBuildTimeout &&
options->CircuitBuildTimeout < RECOMMENDED_MIN_CIRCUIT_BUILD_TIMEOUT) {
log_warn(LD_CONFIG,
@@ -6022,6 +6037,7 @@ parse_port_config(smartlist_t *out,
int sessiongroup = SESSION_GROUP_UNSET;
unsigned isolation = ISO_DEFAULT;
int prefer_no_auth = 0;
+ int socks_iso_keep_alive = 0;
char *addrport;
uint16_t ptmp=0;
@@ -6231,6 +6247,9 @@ parse_port_config(smartlist_t *out,
} else if (!strcasecmp(elt, "PreferSOCKSNoAuth")) {
prefer_no_auth = ! no;
continue;
+ } else if (!strcasecmp(elt, "KeepAliveIsolateSOCKSAuth")) {
+ socks_iso_keep_alive = ! no;
+ continue;
}
if (!strcasecmpend(elt, "s"))
@@ -6276,6 +6295,13 @@ parse_port_config(smartlist_t *out,
goto err;
}
+ if (!(isolation & ISO_SOCKSAUTH) && socks_iso_keep_alive) {
+ log_warn(LD_CONFIG, "You have a %sPort entry with both "
+ "NoIsolateSOCKSAuth and KeepAliveIsolateSOCKSAuth set.",
+ portname);
+ goto err;
+ }
+
if (out && port) {
size_t namelen = unix_socket_path ? strlen(unix_socket_path) : 0;
port_cfg_t *cfg = port_cfg_new(namelen);
@@ -6309,6 +6335,7 @@ parse_port_config(smartlist_t *out,
cfg->entry_cfg.socks_prefer_no_auth = prefer_no_auth;
if (! (isolation & ISO_SOCKSAUTH))
cfg->entry_cfg.socks_prefer_no_auth = 1;
+ cfg->entry_cfg.socks_iso_keep_alive = socks_iso_keep_alive;
smartlist_add(out, cfg);
}
diff --git a/src/or/connection.c b/src/or/connection.c
index ac36578069..78176d3768 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -654,8 +654,8 @@ connection_free_(connection_t *conn)
/** Make sure <b>conn</b> isn't in any of the global conn lists; then free it.
*/
-void
-connection_free(connection_t *conn)
+MOCK_IMPL(void,
+connection_free,(connection_t *conn))
{
if (!conn)
return;
diff --git a/src/or/connection.h b/src/or/connection.h
index d0a34ece5c..b6ff3d7bd6 100644
--- a/src/or/connection.h
+++ b/src/or/connection.h
@@ -28,7 +28,7 @@ listener_connection_t *listener_connection_new(int type, int socket_family);
connection_t *connection_new(int type, int socket_family);
void connection_link_connections(connection_t *conn_a, connection_t *conn_b);
-void connection_free(connection_t *conn);
+MOCK_DECL(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);
diff --git a/src/or/control.c b/src/or/control.c
index 3638bd2e05..220e7e514f 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -1130,7 +1130,7 @@ static const struct control_event_t control_event_table[] = {
{ EVENT_CLIENTS_SEEN, "CLIENTS_SEEN" },
{ EVENT_NEWCONSENSUS, "NEWCONSENSUS" },
{ EVENT_BUILDTIMEOUT_SET, "BUILDTIMEOUT_SET" },
- { EVENT_SIGNAL, "SIGNAL" },
+ { EVENT_GOT_SIGNAL, "SIGNAL" },
{ EVENT_CONF_CHANGED, "CONF_CHANGED"},
{ EVENT_CONN_BW, "CONN_BW" },
{ EVENT_CELL_STATS, "CELL_STATS" },
@@ -5464,7 +5464,7 @@ control_event_signal(uintptr_t signal)
{
const char *signal_string = NULL;
- if (!control_event_is_interesting(EVENT_SIGNAL))
+ if (!control_event_is_interesting(EVENT_GOT_SIGNAL))
return 0;
switch (signal) {
@@ -5492,7 +5492,7 @@ control_event_signal(uintptr_t signal)
return -1;
}
- send_control_event(EVENT_SIGNAL, "650 SIGNAL %s\r\n",
+ send_control_event(EVENT_GOT_SIGNAL, "650 SIGNAL %s\r\n",
signal_string);
return 0;
}
@@ -6478,3 +6478,4 @@ control_testing_set_global_event_mask(uint64_t mask)
global_event_mask = mask;
}
#endif
+
diff --git a/src/or/control.h b/src/or/control.h
index 574dd85002..fdf7903cb8 100644
--- a/src/or/control.h
+++ b/src/or/control.h
@@ -176,7 +176,7 @@ void control_free_all(void);
#define EVENT_CLIENTS_SEEN 0x0015
#define EVENT_NEWCONSENSUS 0x0016
#define EVENT_BUILDTIMEOUT_SET 0x0017
-#define EVENT_SIGNAL 0x0018
+#define EVENT_GOT_SIGNAL 0x0018
#define EVENT_CONF_CHANGED 0x0019
#define EVENT_CONN_BW 0x001A
#define EVENT_CELL_STATS 0x001B
diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c
index d511ecf84c..76d97e05f2 100644
--- a/src/or/cpuworker.c
+++ b/src/or/cpuworker.c
@@ -160,7 +160,7 @@ typedef struct cpuworker_job_u {
} u;
} cpuworker_job_t;
-static int
+static workqueue_reply_t
update_state_threadfn(void *state_, void *work_)
{
worker_state_t *state = state_;
@@ -387,7 +387,7 @@ cpuworker_onion_handshake_replyfn(void *work_)
}
/** Implementation function for onion handshake requests. */
-static int
+static workqueue_reply_t
cpuworker_onion_handshake_threadfn(void *state_, void *work_)
{
worker_state_t *state = state_;
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index 58ab009cbf..53b450cef5 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -1344,7 +1344,7 @@ dirserv_thinks_router_is_unreliable(time_t now,
/** Return true iff <b>router</b> should be assigned the "HSDir" flag.
* Right now this means it advertises support for it, it has a high uptime,
- * it has a DirPort open, it has the Stable flag and it's currently
+ * it has a DirPort open, it has the Stable and Fast flag and it's currently
* considered Running.
*
* This function needs to be called after router-\>is_running has
@@ -1372,7 +1372,7 @@ dirserv_thinks_router_is_hs_dir(const routerinfo_t *router,
uptime = real_uptime(router, now);
return (router->wants_to_be_hs_dir && router->dir_port &&
- node->is_stable &&
+ node->is_stable && node->is_fast &&
uptime >= get_options()->MinUptimeHidServDirectoryV2 &&
router_is_active(router, node, now));
}
@@ -3745,7 +3745,9 @@ validate_recommended_package_line(const char *line)
cp = end_of_word + 1;
}
- return (n_entries == 0) ? 0 : 1;
+ /* If we reach this point, we have at least 1 entry. */
+ tor_assert(n_entries > 0);
+ return 1;
}
/** Release all storage used by the directory server. */
diff --git a/src/or/dns.c b/src/or/dns.c
index db77d20783..d71246d61e 100644
--- a/src/or/dns.c
+++ b/src/or/dns.c
@@ -11,6 +11,8 @@
* be nonblocking.)
**/
+#define DNS_PRIVATE
+
#include "or.h"
#include "circuitlist.h"
#include "circuituse.h"
@@ -81,9 +83,6 @@ struct evdns_request;
#endif
-/** Longest hostname we're willing to resolve. */
-#define MAX_ADDRESSLEN 256
-
/** How long will we wait for an answer from the resolver before we decide
* that the resolver is wedged? */
#define RESOLVE_MAX_TIMEOUT 300
@@ -102,104 +101,16 @@ static char *resolv_conf_fname = NULL;
* the nameservers? Used to check whether we need to reconfigure. */
static time_t resolv_conf_mtime = 0;
-/** Linked list of connections waiting for a DNS answer. */
-typedef struct pending_connection_t {
- edge_connection_t *conn;
- struct pending_connection_t *next;
-} pending_connection_t;
-
-/** Value of 'magic' field for cached_resolve_t. Used to try to catch bad
- * pointers and memory stomping. */
-#define CACHED_RESOLVE_MAGIC 0x1234F00D
-
-/* Possible states for a cached resolve_t */
-/** We are waiting for the resolver system to tell us an answer here.
- * When we get one, or when we time out, the state of this cached_resolve_t
- * will become "DONE" and we'll possibly add a CACHED
- * entry. This cached_resolve_t will be in the hash table so that we will
- * know not to launch more requests for this addr, but rather to add more
- * connections to the pending list for the addr. */
-#define CACHE_STATE_PENDING 0
-/** This used to be a pending cached_resolve_t, and we got an answer for it.
- * Now we're waiting for this cached_resolve_t to expire. This should
- * have no pending connections, and should not appear in the hash table. */
-#define CACHE_STATE_DONE 1
-/** We are caching an answer for this address. This should have no pending
- * connections, and should appear in the hash table. */
-#define CACHE_STATE_CACHED 2
-
-/** @name status values for a single DNS request.
- *
- * @{ */
-/** The DNS request is in progress. */
-#define RES_STATUS_INFLIGHT 1
-/** The DNS request finished and gave an answer */
-#define RES_STATUS_DONE_OK 2
-/** The DNS request finished and gave an error */
-#define RES_STATUS_DONE_ERR 3
-/**@}*/
-
-/** A DNS request: possibly completed, possibly pending; cached_resolve
- * structs are stored at the OR side in a hash table, and as a linked
- * list from oldest to newest.
- */
-typedef struct cached_resolve_t {
- HT_ENTRY(cached_resolve_t) node;
- uint32_t magic; /**< Must be CACHED_RESOLVE_MAGIC */
- char address[MAX_ADDRESSLEN]; /**< The hostname to be resolved. */
-
- union {
- uint32_t addr_ipv4; /**< IPv4 addr for <b>address</b>, if successful.
- * (In host order.) */
- int err_ipv4; /**< One of DNS_ERR_*, if IPv4 lookup failed. */
- } result_ipv4; /**< Outcome of IPv4 lookup */
- union {
- struct in6_addr addr_ipv6; /**< IPv6 addr for <b>address</b>, if
- * successful */
- int err_ipv6; /**< One of DNS_ERR_*, if IPv6 lookup failed. */
- } result_ipv6; /**< Outcome of IPv6 lookup, if any */
- union {
- char *hostname; /** A hostname, if PTR lookup happened successfully*/
- int err_hostname; /** One of DNS_ERR_*, if PTR lookup failed. */
- } result_ptr;
- /** @name Status fields
- *
- * These take one of the RES_STATUS_* values, depending on the state
- * of the corresponding lookup.
- *
- * @{ */
- unsigned int res_status_ipv4 : 2;
- unsigned int res_status_ipv6 : 2;
- unsigned int res_status_hostname : 2;
- /**@}*/
- uint8_t state; /**< Is this cached entry pending/done/informative? */
-
- time_t expire; /**< Remove items from cache after this time. */
- uint32_t ttl_ipv4; /**< What TTL did the nameserver tell us? */
- uint32_t ttl_ipv6; /**< What TTL did the nameserver tell us? */
- uint32_t ttl_hostname; /**< What TTL did the nameserver tell us? */
- /** Connections that want to know when we get an answer for this resolve. */
- pending_connection_t *pending_connections;
- /** Position of this element in the heap*/
- int minheap_idx;
-} cached_resolve_t;
-
static void purge_expired_resolves(time_t now);
static void dns_found_answer(const char *address, uint8_t query_type,
int dns_answer,
const tor_addr_t *addr,
const char *hostname,
uint32_t ttl);
-static void send_resolved_cell(edge_connection_t *conn, uint8_t answer_type,
- const cached_resolve_t *resolve);
static int launch_resolve(cached_resolve_t *resolve);
static void add_wildcarded_test_address(const char *address);
static int configure_nameservers(int force);
static int answer_is_wildcarded(const char *ip);
-static int dns_resolve_impl(edge_connection_t *exitconn, int is_resolve,
- or_circuit_t *oncirc, char **resolved_to_hostname,
- int *made_connection_pending_out,
- cached_resolve_t **resolve_out);
static int set_exitconn_info_from_resolve(edge_connection_t *exitconn,
const cached_resolve_t *resolve,
char **hostname_out);
@@ -367,7 +278,7 @@ dns_clip_ttl(uint32_t ttl)
/** Helper: Given a TTL from a DNS response, determine how long to hold it in
* our cache. */
-static uint32_t
+STATIC uint32_t
dns_get_expiry_ttl(uint32_t ttl)
{
if (ttl < MIN_DNS_TTL)
@@ -605,9 +516,9 @@ purge_expired_resolves(time_t now)
* answer back along circ; otherwise, send the answer back along
* <b>conn</b>'s attached circuit.
*/
-static void
-send_resolved_cell(edge_connection_t *conn, uint8_t answer_type,
- const cached_resolve_t *resolved)
+MOCK_IMPL(STATIC void,
+send_resolved_cell,(edge_connection_t *conn, uint8_t answer_type,
+ const cached_resolve_t *resolved))
{
char buf[RELAY_PAYLOAD_SIZE], *cp = buf;
size_t buflen = 0;
@@ -671,8 +582,9 @@ send_resolved_cell(edge_connection_t *conn, uint8_t answer_type,
* answer back along circ; otherwise, send the answer back along
* <b>conn</b>'s attached circuit.
*/
-static void
-send_resolved_hostname_cell(edge_connection_t *conn, const char *hostname)
+MOCK_IMPL(STATIC void,
+send_resolved_hostname_cell,(edge_connection_t *conn,
+ const char *hostname))
{
char buf[RELAY_PAYLOAD_SIZE];
size_t buflen;
@@ -800,11 +712,11 @@ dns_resolve(edge_connection_t *exitconn)
*
* Set *<b>resolve_out</b> to a cached resolve, if we found one.
*/
-static int
-dns_resolve_impl(edge_connection_t *exitconn, int is_resolve,
+MOCK_IMPL(STATIC int,
+dns_resolve_impl,(edge_connection_t *exitconn, int is_resolve,
or_circuit_t *oncirc, char **hostname_out,
int *made_connection_pending_out,
- cached_resolve_t **resolve_out)
+ cached_resolve_t **resolve_out))
{
cached_resolve_t *resolve;
cached_resolve_t search;
@@ -1145,8 +1057,8 @@ connection_dns_remove(edge_connection_t *conn)
* the resolve for <b>address</b> itself, and remove any cached results for
* <b>address</b> from the cache.
*/
-void
-dns_cancel_pending_resolve(const char *address)
+MOCK_IMPL(void,
+dns_cancel_pending_resolve,(const char *address))
{
pending_connection_t *pend;
cached_resolve_t search;
diff --git a/src/or/dns.h b/src/or/dns.h
index b13ab0f890..6af7796dbb 100644
--- a/src/or/dns.h
+++ b/src/or/dns.h
@@ -20,7 +20,7 @@ int dns_reset(void);
void connection_dns_remove(edge_connection_t *conn);
void assert_connection_edge_not_dns_pending(edge_connection_t *conn);
void assert_all_pending_dns_resolves_ok(void);
-void dns_cancel_pending_resolve(const char *question);
+MOCK_DECL(void,dns_cancel_pending_resolve,(const char *question));
int dns_resolve(edge_connection_t *exitconn);
void dns_launch_correctness_checks(void);
int dns_seems_to_be_broken(void);
@@ -28,5 +28,21 @@ int dns_seems_to_be_broken_for_ipv6(void);
void dns_reset_correctness_checks(void);
void dump_dns_mem_usage(int severity);
+#ifdef DNS_PRIVATE
+#include "dns_structs.h"
+
+STATIC uint32_t dns_get_expiry_ttl(uint32_t ttl);
+
+MOCK_DECL(STATIC int,dns_resolve_impl,(edge_connection_t *exitconn,
+int is_resolve,or_circuit_t *oncirc, char **hostname_out,
+int *made_connection_pending_out, cached_resolve_t **resolve_out));
+
+MOCK_DECL(STATIC void,send_resolved_cell,(edge_connection_t *conn,
+uint8_t answer_type,const cached_resolve_t *resolved));
+
+MOCK_DECL(STATIC void,send_resolved_hostname_cell,(edge_connection_t *conn,
+const char *hostname));
+#endif
+
#endif
diff --git a/src/or/dns_structs.h b/src/or/dns_structs.h
new file mode 100644
index 0000000000..bb67459d7b
--- /dev/null
+++ b/src/or/dns_structs.h
@@ -0,0 +1,90 @@
+#ifndef TOR_DNS_STRUCTS_H
+#define TOR_DNS_STRUCTS_H
+
+/** Longest hostname we're willing to resolve. */
+#define MAX_ADDRESSLEN 256
+
+/** Linked list of connections waiting for a DNS answer. */
+typedef struct pending_connection_t {
+ edge_connection_t *conn;
+ struct pending_connection_t *next;
+} pending_connection_t;
+
+/** Value of 'magic' field for cached_resolve_t. Used to try to catch bad
+ * pointers and memory stomping. */
+#define CACHED_RESOLVE_MAGIC 0x1234F00D
+
+/* Possible states for a cached resolve_t */
+/** We are waiting for the resolver system to tell us an answer here.
+ * When we get one, or when we time out, the state of this cached_resolve_t
+ * will become "DONE" and we'll possibly add a CACHED
+ * entry. This cached_resolve_t will be in the hash table so that we will
+ * know not to launch more requests for this addr, but rather to add more
+ * connections to the pending list for the addr. */
+#define CACHE_STATE_PENDING 0
+/** This used to be a pending cached_resolve_t, and we got an answer for it.
+ * Now we're waiting for this cached_resolve_t to expire. This should
+ * have no pending connections, and should not appear in the hash table. */
+#define CACHE_STATE_DONE 1
+/** We are caching an answer for this address. This should have no pending
+ * connections, and should appear in the hash table. */
+#define CACHE_STATE_CACHED 2
+
+/** @name status values for a single DNS request.
+ *
+ * @{ */
+/** The DNS request is in progress. */
+#define RES_STATUS_INFLIGHT 1
+/** The DNS request finished and gave an answer */
+#define RES_STATUS_DONE_OK 2
+/** The DNS request finished and gave an error */
+#define RES_STATUS_DONE_ERR 3
+/**@}*/
+
+/** A DNS request: possibly completed, possibly pending; cached_resolve
+ * structs are stored at the OR side in a hash table, and as a linked
+ * list from oldest to newest.
+ */
+typedef struct cached_resolve_t {
+ HT_ENTRY(cached_resolve_t) node;
+ uint32_t magic; /**< Must be CACHED_RESOLVE_MAGIC */
+ char address[MAX_ADDRESSLEN]; /**< The hostname to be resolved. */
+
+ union {
+ uint32_t addr_ipv4; /**< IPv4 addr for <b>address</b>, if successful.
+ * (In host order.) */
+ int err_ipv4; /**< One of DNS_ERR_*, if IPv4 lookup failed. */
+ } result_ipv4; /**< Outcome of IPv4 lookup */
+ union {
+ struct in6_addr addr_ipv6; /**< IPv6 addr for <b>address</b>, if
+ * successful */
+ int err_ipv6; /**< One of DNS_ERR_*, if IPv6 lookup failed. */
+ } result_ipv6; /**< Outcome of IPv6 lookup, if any */
+ union {
+ char *hostname; /** A hostname, if PTR lookup happened successfully*/
+ int err_hostname; /** One of DNS_ERR_*, if PTR lookup failed. */
+ } result_ptr;
+ /** @name Status fields
+ *
+ * These take one of the RES_STATUS_* values, depending on the state
+ * of the corresponding lookup.
+ *
+ * @{ */
+ unsigned int res_status_ipv4 : 2;
+ unsigned int res_status_ipv6 : 2;
+ unsigned int res_status_hostname : 2;
+ /**@}*/
+ uint8_t state; /**< Is this cached entry pending/done/informative? */
+
+ time_t expire; /**< Remove items from cache after this time. */
+ uint32_t ttl_ipv4; /**< What TTL did the nameserver tell us? */
+ uint32_t ttl_ipv6; /**< What TTL did the nameserver tell us? */
+ uint32_t ttl_hostname; /**< What TTL did the nameserver tell us? */
+ /** Connections that want to know when we get an answer for this resolve. */
+ pending_connection_t *pending_connections;
+ /** Position of this element in the heap*/
+ int minheap_idx;
+} cached_resolve_t;
+
+#endif
+
diff --git a/src/or/include.am b/src/or/include.am
index 5566d3cd46..7b12b56eb1 100644
--- a/src/or/include.am
+++ b/src/or/include.am
@@ -123,9 +123,9 @@ src_or_tor_cov_LDADD = src/or/libtor-testing.a src/common/libor-testing.a \
src/common/libor-event-testing.a src/trunnel/libor-trunnel-testing.a \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \
@TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ @TOR_SYSTEMD_LIBS@
-TESTING_TOR_BINARY = $(top_builddir)/src/or/tor-cov
+export TESTING_TOR_BINARY = $(top_builddir)/src/or/tor-cov
else
-TESTING_TOR_BINARY = $(top_builddir)/src/or/tor
+export TESTING_TOR_BINARY = $(top_builddir)/src/or/tor
endif
ORHEADERS = \
@@ -153,6 +153,7 @@ ORHEADERS = \
src/or/dirserv.h \
src/or/dirvote.h \
src/or/dns.h \
+ src/or/dns_structs.h \
src/or/dnsserv.h \
src/or/eventdns_tor.h \
src/or/ext_orport.h \
diff --git a/src/or/main.c b/src/or/main.c
index 69718107df..693d13cd13 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -3042,12 +3042,19 @@ sandbox_init_filter(void)
OPEN_DATADIR_SUFFIX("state", ".tmp");
OPEN_DATADIR_SUFFIX("unparseable-desc", ".tmp");
OPEN_DATADIR_SUFFIX("v3-status-votes", ".tmp");
+ OPEN_DATADIR("key-pinning-journal");
OPEN("/dev/srandom");
OPEN("/dev/urandom");
OPEN("/dev/random");
OPEN("/etc/hosts");
OPEN("/proc/meminfo");
+ if (options->BridgeAuthoritativeDir)
+ OPEN_DATADIR_SUFFIX("networkstatus-bridges", ".tmp");
+
+ if (authdir_mode_handles_descs(options, -1))
+ OPEN_DATADIR("approved-routers");
+
if (options->ServerDNSResolvConfFile)
sandbox_cfg_allow_open_filename(&cfg,
tor_strdup(options->ServerDNSResolvConfFile));
@@ -3088,6 +3095,9 @@ sandbox_init_filter(void)
RENAME_SUFFIX("unparseable-desc", ".tmp");
RENAME_SUFFIX("v3-status-votes", ".tmp");
+ if (options->BridgeAuthoritativeDir)
+ RENAME_SUFFIX("networkstatus-bridges", ".tmp");
+
#define STAT_DATADIR(name) \
sandbox_cfg_allow_stat_filename(&cfg, get_datadir_fname(name))
@@ -3156,6 +3166,13 @@ sandbox_init_filter(void)
OPEN_DATADIR2("keys", "secret_onion_key.old");
OPEN_DATADIR2("keys", "secret_onion_key_ntor.old");
+ OPEN_DATADIR2_SUFFIX("keys", "ed25519_master_id_secret_key", ".tmp");
+ OPEN_DATADIR2_SUFFIX("keys", "ed25519_master_id_secret_key_encrypted",
+ ".tmp");
+ OPEN_DATADIR2_SUFFIX("keys", "ed25519_master_id_public_key", ".tmp");
+ OPEN_DATADIR2_SUFFIX("keys", "ed25519_signing_secret_key", ".tmp");
+ OPEN_DATADIR2_SUFFIX("keys", "ed25519_signing_cert", ".tmp");
+
OPEN_DATADIR2_SUFFIX("stats", "bridge-stats", ".tmp");
OPEN_DATADIR2_SUFFIX("stats", "dirreq-stats", ".tmp");
@@ -3186,6 +3203,12 @@ sandbox_init_filter(void)
RENAME_SUFFIX("hashed-fingerprint", ".tmp");
RENAME_SUFFIX("router-stability", ".tmp");
+ RENAME_SUFFIX2("keys", "ed25519_master_id_secret_key", ".tmp");
+ RENAME_SUFFIX2("keys", "ed25519_master_id_secret_key_encrypted", ".tmp");
+ RENAME_SUFFIX2("keys", "ed25519_master_id_public_key", ".tmp");
+ RENAME_SUFFIX2("keys", "ed25519_signing_secret_key", ".tmp");
+ RENAME_SUFFIX2("keys", "ed25519_signing_cert", ".tmp");
+
sandbox_cfg_allow_rename(&cfg,
get_datadir_fname2("keys", "secret_onion_key"),
get_datadir_fname2("keys", "secret_onion_key.old"));
diff --git a/src/or/or.h b/src/or/or.h
index 8c40f1ab67..6660a0dcdc 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -1155,6 +1155,8 @@ typedef struct entry_port_cfg_t {
/** When both no-auth and user/pass are advertised by a SOCKS client, select
* no-auth. */
unsigned int socks_prefer_no_auth : 1;
+ /** When ISO_SOCKSAUTH is in use, Keep-Alive circuits indefinitely. */
+ unsigned int socks_iso_keep_alive : 1;
/* Client port types only: */
unsigned int ipv4_traffic : 1;
@@ -2877,6 +2879,11 @@ typedef struct circuit_t {
* circuits entered certain states. This usage probably won't
* interfere with this field's primary purpose, but we should
* document it more thoroughly to make sure of that.
+ *
+ * XXX027 The SocksPort option KeepaliveIsolateSOCKSAuth will artificially
+ * adjust this value forward each time a suitable stream is attached to an
+ * already constructed circuit, potentially keeping the circuit alive
+ * indefinitely.
*/
time_t timestamp_dirty;
diff --git a/src/or/rendcache.c b/src/or/rendcache.c
index 9a33046fb6..fe9a1344f6 100644
--- a/src/or/rendcache.c
+++ b/src/or/rendcache.c
@@ -330,7 +330,7 @@ cache_failure_intro_lookup(const uint8_t *identity, const char *service_id,
*intro_entry = intro_elem;
}
return 1;
-not_found:
+ not_found:
return 0;
}
diff --git a/src/or/rendclient.c b/src/or/rendclient.c
index c6f29a7707..a39e518e99 100644
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@ -1021,7 +1021,7 @@ rend_client_report_intro_point_failure(extend_info_t *failed_intro,
/* fall through */
case INTRO_POINT_FAILURE_GENERIC:
rend_cache_intro_failure_note(failure_type,
- (uint8_t *) failed_intro->identity_digest,
+ (uint8_t *)failed_intro->identity_digest,
rend_query->onion_address);
rend_intro_point_free(intro);
smartlist_del(ent->parsed->intro_nodes, i);
@@ -1038,9 +1038,10 @@ rend_client_report_intro_point_failure(extend_info_t *failed_intro,
intro->unreachable_count,
zap_intro_point ? " Removing from descriptor.": "");
if (zap_intro_point) {
- rend_cache_intro_failure_note(failure_type,
- (uint8_t *) failed_intro->identity_digest,
- rend_query->onion_address);
+ rend_cache_intro_failure_note(
+ failure_type,
+ (uint8_t *) failed_intro->identity_digest,
+ rend_query->onion_address);
rend_intro_point_free(intro);
smartlist_del(ent->parsed->intro_nodes, i);
}
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index db6bc4b72e..8ba5327b1d 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -40,7 +40,7 @@ static rend_intro_point_t *find_expiring_intro_point(
static extend_info_t *find_rp_for_intro(
const rend_intro_cell_t *intro,
- uint8_t *need_free_out, char **err_msg_out);
+ char **err_msg_out);
static int intro_point_accepted_intro_count(rend_intro_point_t *intro);
static int intro_point_should_expire_now(rend_intro_point_t *intro,
@@ -1456,13 +1456,6 @@ rend_service_receive_introduction(origin_circuit_t *circuit,
rend_intro_cell_t *parsed_req = NULL;
/* Rendezvous point */
extend_info_t *rp = NULL;
- /*
- * We need to look up and construct the extend_info_t for v0 and v1,
- * but all the info is in the cell and it's constructed by the parser
- * for v2 and v3, so freeing it would be a double-free. Use this to
- * keep track of whether we should free it.
- */
- uint8_t need_rp_free = 0;
/* XXX not handled yet */
char buf[RELAY_PAYLOAD_SIZE];
char keys[DIGEST_LEN+CPATH_KEY_MATERIAL_LEN]; /* Holds KH, Df, Db, Kf, Kb */
@@ -1602,7 +1595,7 @@ rend_service_receive_introduction(origin_circuit_t *circuit,
++(intro_point->accepted_introduce2_count);
/* Find the rendezvous point */
- rp = find_rp_for_intro(parsed_req, &need_rp_free, &err_msg);
+ rp = find_rp_for_intro(parsed_req, &err_msg);
if (!rp)
goto log_error;
@@ -1761,27 +1754,25 @@ rend_service_receive_introduction(origin_circuit_t *circuit,
/* Free the parsed cell */
rend_service_free_intro(parsed_req);
- /* Free rp if we must */
- if (need_rp_free) extend_info_free(rp);
+ /* Free rp */
+ extend_info_free(rp);
return status;
}
/** Given a parsed and decrypted INTRODUCE2, find the rendezvous point or
- * return NULL and an error string if we can't.
- */
-
+ * return NULL and an error string if we can't. Return a newly allocated
+ * extend_info_t* for the rendezvous point. */
static extend_info_t *
find_rp_for_intro(const rend_intro_cell_t *intro,
- uint8_t *need_free_out, char **err_msg_out)
+ char **err_msg_out)
{
extend_info_t *rp = NULL;
char *err_msg = NULL;
const char *rp_nickname = NULL;
const node_t *node = NULL;
- uint8_t need_free = 0;
- if (!intro || !need_free_out) {
+ if (!intro) {
if (err_msg_out)
err_msg = tor_strdup("Bad parameters to find_rp_for_intro()");
@@ -1812,13 +1803,11 @@ find_rp_for_intro(const rend_intro_cell_t *intro,
}
goto err;
- } else {
- need_free = 1;
}
} else if (intro->version == 2) {
- rp = intro->u.v2.extend_info;
+ rp = extend_info_dup(intro->u.v2.extend_info);
} else if (intro->version == 3) {
- rp = intro->u.v3.extend_info;
+ rp = extend_info_dup(intro->u.v3.extend_info);
} else {
if (err_msg_out) {
tor_asprintf(&err_msg,
@@ -1836,8 +1825,6 @@ find_rp_for_intro(const rend_intro_cell_t *intro,
else tor_free(err_msg);
done:
- if (rp && need_free_out) *need_free_out = need_free;
-
return rp;
}
diff --git a/src/or/routerkeys.c b/src/or/routerkeys.c
index ad915479c2..1120578c28 100644
--- a/src/or/routerkeys.c
+++ b/src/or/routerkeys.c
@@ -295,6 +295,7 @@ ed_key_init_from_file(const char *fname, uint32_t flags,
if (rv == 0) {
have_secret = 1;
loaded_secret_fname = secret_fname;
+ tor_assert(got_tag);
} else {
if (errno != ENOENT && norepair) {
tor_log(severity, LD_OR, "Unable to read %s: %s", secret_fname,
@@ -482,10 +483,12 @@ ed_key_init_from_file(const char *fname, uint32_t flags,
tor_log(severity, LD_OR, "Cert was for wrong key");
bad_cert = 1;
} else if (signing_key &&
- tor_cert_checksig(cert, &signing_key->pubkey, now) < 0 &&
- (signing_key || cert->cert_expired)) {
+ tor_cert_checksig(cert, &signing_key->pubkey, now) < 0) {
tor_log(severity, LD_OR, "Can't check certificate");
bad_cert = 1;
+ } else if (cert->cert_expired) {
+ tor_log(severity, LD_OR, "Certificate is expired");
+ bad_cert = 1;
} else if (signing_key && cert->signing_key_included &&
! ed25519_pubkey_eq(&signing_key->pubkey, &cert->signing_key)) {
tor_log(severity, LD_OR, "Certificate signed by unexpectd key!");
diff --git a/src/or/routerset.c b/src/or/routerset.c
index 99de11ed5e..9fe5dffdeb 100644
--- a/src/or/routerset.c
+++ b/src/or/routerset.c
@@ -162,6 +162,17 @@ routerset_is_empty(const routerset_t *set)
return !set || smartlist_len(set->list) == 0;
}
+/** Return the number of entries in <b>set</b>. This does NOT return a
+ * negative value. */
+int
+routerset_len(const routerset_t *set)
+{
+ if (!set) {
+ return 0;
+ }
+ return smartlist_len(set->list);
+}
+
/** Helper. Return true iff <b>set</b> contains a router based on the other
* provided fields. Return higher values for more specific subentries: a
* single router is more specific than an address range of routers, which is
diff --git a/src/or/routerset.h b/src/or/routerset.h
index 8d41de8b6b..aca7c6e74e 100644
--- a/src/or/routerset.h
+++ b/src/or/routerset.h
@@ -38,6 +38,7 @@ void routerset_subtract_nodes(smartlist_t *out,
char *routerset_to_string(const routerset_t *routerset);
int routerset_equal(const routerset_t *old, const routerset_t *new);
void routerset_free(routerset_t *routerset);
+int routerset_len(const routerset_t *set);
#ifdef ROUTERSET_PRIVATE
STATIC char * routerset_get_countryname(const char *c);
diff --git a/src/or/tor_main.c b/src/or/tor_main.c
index af03b8c06a..65bb020c2c 100644
--- a/src/or/tor_main.c
+++ b/src/or/tor_main.c
@@ -27,6 +27,10 @@ int tor_main(int argc, char *argv[]);
int
main(int argc, char *argv[])
{
- return tor_main(argc, argv);
+ int r = tor_main(argc, argv);
+ if (r < 0 || r > 255)
+ return 1;
+ else
+ return r;
}
diff --git a/src/test/include.am b/src/test/include.am
index 3fe4f50edf..f7c0204832 100644
--- a/src/test/include.am
+++ b/src/test/include.am
@@ -1,12 +1,19 @@
-TESTSCRIPTS = src/test/test_zero_length_keys.sh src/test/test_keygen.sh
+TESTSCRIPTS = src/test/test_zero_length_keys.sh
if USEPYTHON
TESTSCRIPTS += src/test/test_ntor.sh src/test/test_bt.sh
endif
TESTS += src/test/test src/test/test-slow src/test/test-memwipe \
- src/test/test_workqueue $(TESTSCRIPTS)
+ src/test/test_workqueue src/test/test_keygen.sh $(TESTSCRIPTS)
+
+# These flavors are run using automake's test-driver and test-network.sh
+TEST_CHUTNEY_FLAVORS = basic-min bridges-min hs-min bridges+hs
+# only run if we can ping6 ::1 (localhost)
+TEST_CHUTNEY_FLAVORS_IPV6 = bridges+ipv6-min ipv6-exit-min
+# only run if we can find a stable (or simply another) version of tor
+TEST_CHUTNEY_FLAVORS_MIXED = mixed
### This is a lovely feature, but it requires automake >= 1.12, and Tor
### doesn't require that yet. Below is a kludge to work around.
@@ -90,6 +97,7 @@ src_test_test_SOURCES = \
src/test/test_threads.c \
src/test/test_util.c \
src/test/test_helpers.c \
+ src/test/test_dns.c \
src/test/testing_common.c \
src/ext/tinytest.c
@@ -185,4 +193,5 @@ EXTRA_DIST += \
src/test/bt_test.py \
src/test/ntor_ref.py \
src/test/slownacl_curve25519.py \
- src/test/zero_length_keys.sh
+ src/test/zero_length_keys.sh \
+ src/test/test_keygen.sh
diff --git a/src/test/test-network.sh b/src/test/test-network.sh
index cc74c0f823..05080e0c52 100755
--- a/src/test/test-network.sh
+++ b/src/test/test-network.sh
@@ -3,9 +3,9 @@
ECHO_N="/bin/echo -n"
use_coverage_binary=false
-until [ -z $1 ]
+until [ -z "$1" ]
do
- case $1 in
+ case "$1" in
--chutney-path)
export CHUTNEY_PATH="$2"
shift
@@ -55,12 +55,20 @@ do
done
TOR_DIR="${TOR_DIR:-$PWD}"
-NETWORK_FLAVOUR=${NETWORK_FLAVOUR:-basic}
+NETWORK_FLAVOUR=${NETWORK_FLAVOUR:-"bridges+hs"}
CHUTNEY_NETWORK=networks/$NETWORK_FLAVOUR
myname=$(basename $0)
+[ -n "$CHUTNEY_PATH" ] || {
+ echo "$myname: \$CHUTNEY_PATH not set, trying $TOR_DIR/../chutney"
+ CHUTNEY_PATH="$TOR_DIR/../chutney"
+}
+
[ -d "$CHUTNEY_PATH" ] && [ -x "$CHUTNEY_PATH/chutney" ] || {
echo "$myname: missing 'chutney' in CHUTNEY_PATH ($CHUTNEY_PATH)"
+ echo "$myname: Get chutney: git clone https://git.torproject.org/\
+chutney.git"
+ echo "$myname: Set \$CHUTNEY_PATH to a non-standard location: export CHUTNEY_PATH=\`pwd\`/chutney"
exit 1
}
@@ -78,7 +86,7 @@ export CHUTNEY_TOR_GENCERT="${TOR_DIR}/src/tools/${tor_gencert_name}"
# Sleep some, waiting for the network to bootstrap.
# TODO: Add chutney command 'bootstrap-status' and use that instead.
-BOOTSTRAP_TIME=${BOOTSTRAP_TIME:-25}
+BOOTSTRAP_TIME=${BOOTSTRAP_TIME:-35}
$ECHO_N "$myname: sleeping for $BOOTSTRAP_TIME seconds"
n=$BOOTSTRAP_TIME; while [ $n -gt 0 ]; do
sleep 1; n=$(expr $n - 1); $ECHO_N .
diff --git a/src/test/test.c b/src/test/test.c
index 7ad849f49e..e10e260266 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -1158,6 +1158,7 @@ extern struct testcase_t socks_tests[];
extern struct testcase_t status_tests[];
extern struct testcase_t thread_tests[];
extern struct testcase_t util_tests[];
+extern struct testcase_t dns_tests[];
struct testgroup_t testgroups[] = {
{ "", test_array },
@@ -1204,6 +1205,7 @@ struct testgroup_t testgroups[] = {
{ "util/", util_tests },
{ "util/logging/", logging_tests },
{ "util/thread/", thread_tests },
+ { "dns/", dns_tests },
END_OF_GROUPS
};
diff --git a/src/test/test_buffers.c b/src/test/test_buffers.c
index e8fce12314..29ee408616 100644
--- a/src/test/test_buffers.c
+++ b/src/test/test_buffers.c
@@ -206,9 +206,6 @@ test_buffer_pullup(void *arg)
stuff = tor_malloc(16384);
tmp = tor_malloc(16384);
- /* Note: this test doesn't check the nulterminate argument to buf_pullup,
- since nothing actually uses it. We should remove it some time. */
-
buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */
tt_assert(buf);
@@ -218,7 +215,7 @@ test_buffer_pullup(void *arg)
/* There are a bunch of cases for pullup. One is the trivial case. Let's
mess around with an empty buffer. */
- buf_pullup(buf, 16, 1);
+ buf_pullup(buf, 16);
buf_get_first_chunk_data(buf, &cp, &sz);
tt_ptr_op(cp, OP_EQ, NULL);
tt_uint_op(sz, OP_EQ, 0);
@@ -240,7 +237,7 @@ test_buffer_pullup(void *arg)
* can get tested. */
tt_int_op(fetch_from_buf(tmp, 3000, buf), OP_EQ, 3000);
tt_mem_op(tmp,OP_EQ, stuff, 3000);
- buf_pullup(buf, 2048, 0);
+ buf_pullup(buf, 2048);
assert_buf_ok(buf);
buf_get_first_chunk_data(buf, &cp, &sz);
tt_ptr_op(cp, OP_NE, NULL);
@@ -263,7 +260,7 @@ test_buffer_pullup(void *arg)
tt_ptr_op(cp, OP_NE, NULL);
tt_int_op(sz, OP_LE, 4096);
- buf_pullup(buf, 12500, 0);
+ buf_pullup(buf, 12500);
assert_buf_ok(buf);
buf_get_first_chunk_data(buf, &cp, &sz);
tt_ptr_op(cp, OP_NE, NULL);
@@ -286,7 +283,7 @@ test_buffer_pullup(void *arg)
write_to_buf(stuff, 4000, buf);
write_to_buf(stuff+4000, 4000, buf);
fetch_from_buf(tmp, 100, buf); /* dump 100 bytes from first chunk */
- buf_pullup(buf, 16000, 0); /* Way too much. */
+ buf_pullup(buf, 16000); /* Way too much. */
assert_buf_ok(buf);
buf_get_first_chunk_data(buf, &cp, &sz);
tt_ptr_op(cp, OP_NE, NULL);
diff --git a/src/test/test_checkdir.c b/src/test/test_checkdir.c
index a44584c0a3..d6ef353c87 100644
--- a/src/test/test_checkdir.c
+++ b/src/test/test_checkdir.c
@@ -4,7 +4,9 @@
#include "orconfig.h"
#include "or.h"
-#ifndef _WIN32
+#ifdef _WIN32
+#include <direct.h>
+#else
#include <dirent.h>
#endif
diff --git a/src/test/test_dns.c b/src/test/test_dns.c
new file mode 100644
index 0000000000..ad81914ccb
--- /dev/null
+++ b/src/test/test_dns.c
@@ -0,0 +1,311 @@
+#include "or.h"
+#include "test.h"
+
+#define DNS_PRIVATE
+
+#include "dns.h"
+#include "connection.h"
+
+static void
+test_dns_clip_ttl(void *arg)
+{
+ (void)arg;
+
+ uint32_t ttl_mid = MIN_DNS_TTL / 2 + MAX_DNS_TTL / 2;
+
+ tt_int_op(dns_clip_ttl(MIN_DNS_TTL - 1),==,MIN_DNS_TTL);
+ tt_int_op(dns_clip_ttl(ttl_mid),==,ttl_mid);
+ tt_int_op(dns_clip_ttl(MAX_DNS_TTL + 1),==,MAX_DNS_TTL);
+
+ done:
+ return;
+}
+
+static void
+test_dns_expiry_ttl(void *arg)
+{
+ (void)arg;
+
+ uint32_t ttl_mid = MIN_DNS_TTL / 2 + MAX_DNS_ENTRY_AGE / 2;
+
+ tt_int_op(dns_get_expiry_ttl(MIN_DNS_TTL - 1),==,MIN_DNS_TTL);
+ tt_int_op(dns_get_expiry_ttl(ttl_mid),==,ttl_mid);
+ tt_int_op(dns_get_expiry_ttl(MAX_DNS_ENTRY_AGE + 1),==,MAX_DNS_ENTRY_AGE);
+
+ done:
+ return;
+}
+
+static int resolve_retval = 0;
+static int resolve_made_conn_pending = 0;
+static char *resolved_name = NULL;
+static cached_resolve_t *cache_entry = NULL;
+
+static int n_fake_impl = 0;
+
+/** This will be our configurable substitute for <b>dns_resolve_impl</b> in
+ * dns.c. It will return <b>resolve_retval</b>,
+ * and set <b>resolve_made_conn_pending</b> to
+ * <b>made_connection_pending_out</b>. It will set <b>hostname_out</b>
+ * to a duplicate of <b>resolved_name</b> and it will set <b>resolve_out</b>
+ * to <b>cache_entry</b>. Lastly, it will increment <b>n_fake_impl</b< by
+ * 1.
+ */
+static int
+dns_resolve_fake_impl(edge_connection_t *exitconn, int is_resolve,
+ or_circuit_t *oncirc, char **hostname_out,
+ int *made_connection_pending_out,
+ cached_resolve_t **resolve_out)
+{
+ (void)oncirc;
+ (void)exitconn;
+ (void)is_resolve;
+
+ if (made_connection_pending_out)
+ *made_connection_pending_out = resolve_made_conn_pending;
+
+ if (hostname_out && resolved_name)
+ *hostname_out = tor_strdup(resolved_name);
+
+ if (resolve_out && cache_entry)
+ *resolve_out = cache_entry;
+
+ n_fake_impl++;
+
+ return resolve_retval;
+}
+
+static edge_connection_t *conn_for_resolved_cell = NULL;
+
+static int n_send_resolved_cell_replacement = 0;
+static uint8_t last_answer_type = 0;
+static cached_resolve_t *last_resolved;
+
+static void
+send_resolved_cell_replacement(edge_connection_t *conn, uint8_t answer_type,
+ const cached_resolve_t *resolved)
+{
+ conn_for_resolved_cell = conn;
+
+ last_answer_type = answer_type;
+ last_resolved = (cached_resolve_t *)resolved;
+
+ n_send_resolved_cell_replacement++;
+}
+
+static int n_send_resolved_hostname_cell_replacement = 0;
+
+static char *last_resolved_hostname = NULL;
+
+static void
+send_resolved_hostname_cell_replacement(edge_connection_t *conn,
+ const char *hostname)
+{
+ conn_for_resolved_cell = conn;
+
+ tor_free(last_resolved_hostname);
+ last_resolved_hostname = tor_strdup(hostname);
+
+ n_send_resolved_hostname_cell_replacement++;
+}
+
+static int n_dns_cancel_pending_resolve_replacement = 0;
+
+static void
+dns_cancel_pending_resolve_replacement(const char *address)
+{
+ (void) address;
+ n_dns_cancel_pending_resolve_replacement++;
+}
+
+static int n_connection_free = 0;
+static connection_t *last_freed_conn = NULL;
+
+static void
+connection_free_replacement(connection_t *conn)
+{
+ n_connection_free++;
+
+ last_freed_conn = conn;
+}
+
+static void
+test_dns_resolve_outer(void *arg)
+{
+ (void) arg;
+ int retval;
+ int prev_n_send_resolved_hostname_cell_replacement;
+ int prev_n_send_resolved_cell_replacement;
+ int prev_n_connection_free;
+ cached_resolve_t *fake_resolved = tor_malloc(sizeof(cached_resolve_t));
+ edge_connection_t *exitconn = tor_malloc(sizeof(edge_connection_t));
+ edge_connection_t *nextconn = tor_malloc(sizeof(edge_connection_t));
+
+ or_circuit_t *on_circuit = tor_malloc(sizeof(or_circuit_t));
+ memset(on_circuit,0,sizeof(or_circuit_t));
+ on_circuit->base_.magic = OR_CIRCUIT_MAGIC;
+
+ memset(fake_resolved,0,sizeof(cached_resolve_t));
+ memset(exitconn,0,sizeof(edge_connection_t));
+ memset(nextconn,0,sizeof(edge_connection_t));
+
+ MOCK(dns_resolve_impl,dns_resolve_fake_impl);
+ MOCK(send_resolved_cell,send_resolved_cell_replacement);
+ MOCK(send_resolved_hostname_cell,send_resolved_hostname_cell_replacement);
+
+ /*
+ * CASE 1: dns_resolve_impl returns 1 and sets a hostname. purpose is
+ * EXIT_PURPOSE_RESOLVE.
+ *
+ * We want dns_resolve() to call send_resolved_hostname_cell() for a
+ * given exit connection (represented by edge_connection_t object)
+ * with a hostname it received from _impl.
+ */
+
+ prev_n_send_resolved_hostname_cell_replacement =
+ n_send_resolved_hostname_cell_replacement;
+
+ exitconn->base_.purpose = EXIT_PURPOSE_RESOLVE;
+ exitconn->on_circuit = &(on_circuit->base_);
+
+ resolve_retval = 1;
+ resolved_name = tor_strdup("www.torproject.org");
+
+ retval = dns_resolve(exitconn);
+
+ tt_int_op(retval,==,1);
+ tt_str_op(resolved_name,==,last_resolved_hostname);
+ tt_assert(conn_for_resolved_cell == exitconn);
+ tt_int_op(n_send_resolved_hostname_cell_replacement,==,
+ prev_n_send_resolved_hostname_cell_replacement + 1);
+ tt_assert(exitconn->on_circuit == NULL);
+
+ tor_free(last_resolved_hostname);
+ // implies last_resolved_hostname = NULL;
+
+ /* CASE 2: dns_resolve_impl returns 1, but does not set hostname.
+ * Instead, it yields cached_resolve_t object.
+ *
+ * We want dns_resolve to call send_resolved_cell on exitconn with
+ * RESOLVED_TYPE_AUTO and the cached_resolve_t object from _impl.
+ */
+
+ tor_free(resolved_name);
+ resolved_name = NULL;
+
+ exitconn->on_circuit = &(on_circuit->base_);
+
+ cache_entry = fake_resolved;
+
+ prev_n_send_resolved_cell_replacement =
+ n_send_resolved_cell_replacement;
+
+ retval = dns_resolve(exitconn);
+
+ tt_int_op(retval,==,1);
+ tt_assert(conn_for_resolved_cell == exitconn);
+ tt_int_op(n_send_resolved_cell_replacement,==,
+ prev_n_send_resolved_cell_replacement + 1);
+ tt_assert(last_resolved == fake_resolved);
+ tt_int_op(last_answer_type,==,0xff);
+ tt_assert(exitconn->on_circuit == NULL);
+
+ /* CASE 3: The purpose of exit connection is not EXIT_PURPOSE_RESOLVE
+ * and _impl returns 1.
+ *
+ * We want dns_resolve to prepend exitconn to n_streams linked list.
+ * We don't want it to send any cells about hostname being resolved.
+ */
+
+ exitconn->base_.purpose = EXIT_PURPOSE_CONNECT;
+ exitconn->on_circuit = &(on_circuit->base_);
+
+ on_circuit->n_streams = nextconn;
+
+ prev_n_send_resolved_cell_replacement =
+ n_send_resolved_cell_replacement;
+
+ prev_n_send_resolved_hostname_cell_replacement =
+ n_send_resolved_hostname_cell_replacement;
+
+ retval = dns_resolve(exitconn);
+
+ tt_int_op(retval,==,1);
+ tt_assert(on_circuit->n_streams == exitconn);
+ tt_assert(exitconn->next_stream == nextconn);
+ tt_int_op(prev_n_send_resolved_cell_replacement,==,
+ n_send_resolved_cell_replacement);
+ tt_int_op(prev_n_send_resolved_hostname_cell_replacement,==,
+ n_send_resolved_hostname_cell_replacement);
+
+ /* CASE 4: _impl returns 0.
+ *
+ * We want dns_resolve() to set exitconn state to
+ * EXIT_CONN_STATE_RESOLVING and prepend exitconn to resolving_streams
+ * linked list.
+ */
+
+ exitconn->on_circuit = &(on_circuit->base_);
+
+ resolve_retval = 0;
+
+ exitconn->next_stream = NULL;
+ on_circuit->resolving_streams = nextconn;
+
+ retval = dns_resolve(exitconn);
+
+ tt_int_op(retval,==,0);
+ tt_int_op(exitconn->base_.state,==,EXIT_CONN_STATE_RESOLVING);
+ tt_assert(on_circuit->resolving_streams == exitconn);
+ tt_assert(exitconn->next_stream == nextconn);
+
+ /* CASE 5: _impl returns -1 when purpose of exitconn is
+ * EXIT_PURPOSE_RESOLVE. We want dns_resolve to call send_resolved_cell
+ * on exitconn with type being RESOLVED_TYPE_ERROR.
+ */
+
+ MOCK(dns_cancel_pending_resolve,dns_cancel_pending_resolve_replacement);
+ MOCK(connection_free,connection_free_replacement);
+
+ exitconn->on_circuit = &(on_circuit->base_);
+ exitconn->base_.purpose = EXIT_PURPOSE_RESOLVE;
+
+ resolve_retval = -1;
+
+ prev_n_send_resolved_cell_replacement =
+ n_send_resolved_cell_replacement;
+
+ prev_n_connection_free = n_connection_free;
+
+ retval = dns_resolve(exitconn);
+
+ tt_int_op(retval,==,-1);
+ tt_int_op(n_send_resolved_cell_replacement,==,
+ prev_n_send_resolved_cell_replacement + 1);
+ tt_int_op(last_answer_type,==,RESOLVED_TYPE_ERROR);
+ tt_int_op(n_dns_cancel_pending_resolve_replacement,==,1);
+ tt_int_op(n_connection_free,==,prev_n_connection_free + 1);
+ tt_assert(last_freed_conn == TO_CONN(exitconn));
+
+ done:
+ UNMOCK(dns_resolve_impl);
+ UNMOCK(send_resolved_cell);
+ UNMOCK(send_resolved_hostname_cell);
+ UNMOCK(dns_cancel_pending_resolve);
+ UNMOCK(connection_free);
+ tor_free(on_circuit);
+ tor_free(exitconn);
+ tor_free(nextconn);
+ tor_free(resolved_name);
+ tor_free(fake_resolved);
+ tor_free(last_resolved_hostname);
+ return;
+}
+
+struct testcase_t dns_tests[] = {
+ { "clip_ttl", test_dns_clip_ttl, 0, NULL, NULL },
+ { "expiry_ttl", test_dns_expiry_ttl, 0, NULL, NULL },
+ { "resolve_outer", test_dns_resolve_outer, TT_FORK, NULL, NULL },
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_keygen.sh b/src/test/test_keygen.sh
index e8e3c3d219..87012cd283 100755
--- a/src/test/test_keygen.sh
+++ b/src/test/test_keygen.sh
@@ -46,11 +46,12 @@ fi
fi
+dump() { xxd -p "$1" | tr -d '\n '; }
die() { echo "$1" >&2 ; exit 5; }
check_dir() { [ -d "$1" ] || die "$1 did not exist"; }
check_file() { [ -e "$1" ] || die "$1 did not exist"; }
check_no_file() { [ -e "$1" ] && die "$1 was not supposed to exist" || true; }
-check_files_eq() { cmp "$1" "$2" || die "$1 and $2 did not match"; }
+check_files_eq() { cmp "$1" "$2" || die "$1 and $2 did not match: `dump $1` vs `dump $2`"; }
check_keys_eq() { check_files_eq "${SRC}/keys/${1}" "${ME}/keys/${1}"; }
DATA_DIR=`mktemp -d -t tor_keygen_tests.XXXXXX`
@@ -64,9 +65,13 @@ if [ ! -d "$DATA_DIR" ]; then
fi
trap "rm -rf '$DATA_DIR'" 0
+# Use an absolute path for this or Tor will complain
+DATA_DIR=`cd "${DATA_DIR}" && pwd`
+
touch "${DATA_DIR}/empty_torrc"
QUIETLY="--hush"
+SILENTLY="--quiet"
TOR="${TOR_BINARY} ${QUIETLY} --DisableNetwork 1 --ShutdownWaitLength 0 --ORPort 12345 --ExitRelay 0 -f ${DATA_DIR}/empty_torrc"
##### SETUP
@@ -76,9 +81,9 @@ TOR="${TOR_BINARY} ${QUIETLY} --DisableNetwork 1 --ShutdownWaitLength 0 --ORPort
# copying them into different keys directories in order to simulate
# different kinds of configuration problems/issues.
-# Step 1: Start Tor with --list-fingerprint. Make sure everything is there.
+# Step 1: Start Tor with --list-fingerprint --quiet. Make sure everything is there.
mkdir "${DATA_DIR}/orig"
-${TOR} --DataDirectory "${DATA_DIR}/orig" --list-fingerprint > /dev/null
+${TOR} --DataDirectory "${DATA_DIR}/orig" --list-fingerprint ${SILENTLY} > /dev/null
check_dir "${DATA_DIR}/orig/keys"
check_file "${DATA_DIR}/orig/keys/ed25519_master_id_public_key"
@@ -109,7 +114,7 @@ check_file "${DATA_DIR}/encrypted/keys/ed25519_signing_cert"
check_file "${DATA_DIR}/encrypted/keys/ed25519_signing_secret_key"
-echo "=== Starting tests."
+echo "=== Starting keygen tests."
#
# The "case X" numbers below come from s7r's email on
@@ -124,7 +129,7 @@ ME="${DATA_DIR}/case2a"
SRC="${DATA_DIR}/orig"
mkdir -p "${ME}/keys"
cp "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/"
-${TOR} --DataDirectory "${ME}" --list-fingerprint > "${ME}/stdout" && die "Somehow succeeded when missing secret key, certs" || true
+${TOR} --DataDirectory "${ME}" --list-fingerprint > "${ME}/stdout" && die "Somehow succeeded when missing secret key, certs: `cat ${ME}/stdout`" || true
check_files_eq "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/ed25519_master_id_public_key"
grep "We needed to load a secret key.*but couldn't find it" "${ME}/stdout" >/dev/null || die "Tor didn't declare that it was missing a secret key"
@@ -162,7 +167,7 @@ SRC="${DATA_DIR}/orig"
mkdir -p "${ME}/keys"
cp "${SRC}/keys/ed25519_master_id_"* "${ME}/keys/"
-${TOR} --DataDirectory "${ME}" --list-fingerprint >/dev/null || die "Tor failed when starting with only master key"
+${TOR} --DataDirectory "${ME}" --list-fingerprint ${SILENTLY} >/dev/null || die "Tor failed when starting with only master key"
check_files_eq "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/ed25519_master_id_public_key"
check_files_eq "${SRC}/keys/ed25519_master_id_secret_key" "${ME}/keys/ed25519_master_id_secret_key"
check_file "${ME}/keys/ed25519_signing_cert"
@@ -220,11 +225,11 @@ SRC="${DATA_DIR}/orig"
mkdir -p "${ME}/keys"
cp "${SRC}/keys/ed25519_master_id_secret_key" "${ME}/keys/"
-${TOR} --DataDirectory "${ME}" --list-fingerprint > "${ME}/fp1" || die "Tor wouldn't start with only unencrypted secret key"
+${TOR} --DataDirectory "${ME}" --list-fingerprint ${SILENTLY} > "${ME}/fp1" || die "Tor wouldn't start with only unencrypted secret key"
check_file "${ME}/keys/ed25519_master_id_public_key"
check_file "${ME}/keys/ed25519_signing_cert"
check_file "${ME}/keys/ed25519_signing_secret_key"
-${TOR} --DataDirectory "${ME}" --list-fingerprint > "${ME}/fp2" || die "Tor wouldn't start again after starting once with only unencrypted secret key."
+${TOR} --DataDirectory "${ME}" --list-fingerprint ${SILENTLY} > "${ME}/fp2" || die "Tor wouldn't start again after starting once with only unencrypted secret key."
check_files_eq "${ME}/fp1" "${ME}/fp2"
@@ -284,7 +289,7 @@ cp "${SRC}/keys/ed25519_master_id_secret_key" "${ME}/keys/"
cp "${SRC}/keys/ed25519_signing_cert" "${ME}/keys/"
cp "${SRC}/keys/ed25519_signing_secret_key" "${ME}/keys/"
-${TOR} --DataDirectory "${ME}" --list-fingerprint >/dev/null || die "Failed when starting with missing public key"
+${TOR} --DataDirectory "${ME}" --list-fingerprint ${SILENTLY} >/dev/null || die "Failed when starting with missing public key"
check_keys_eq ed25519_master_id_secret_key
check_keys_eq ed25519_master_id_public_key
check_keys_eq ed25519_signing_secret_key
@@ -306,7 +311,7 @@ cp "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/"
cp "${SRC}/keys/ed25519_signing_cert" "${ME}/keys/"
cp "${SRC}/keys/ed25519_signing_secret_key" "${ME}/keys/"
-${TOR} --DataDirectory "${ME}" --list-fingerprint >/dev/null || die "Failed when starting with offline secret key"
+${TOR} --DataDirectory "${ME}" --list-fingerprint ${SILENTLY} >/dev/null || die "Failed when starting with offline secret key"
check_no_file "${ME}/keys/ed25519_master_id_secret_key"
check_keys_eq ed25519_master_id_public_key
check_keys_eq ed25519_signing_secret_key
@@ -327,7 +332,7 @@ mkdir -p "${ME}/keys"
cp "${SRC}/keys/ed25519_signing_cert" "${ME}/keys/"
cp "${SRC}/keys/ed25519_signing_secret_key" "${ME}/keys/"
-${TOR} --DataDirectory "${ME}" --list-fingerprint >/dev/null || die "Failed when starting with only signing material"
+${TOR} --DataDirectory "${ME}" --list-fingerprint ${SILENTLY} >/dev/null || die "Failed when starting with only signing material"
check_no_file "${ME}/keys/ed25519_master_id_secret_key"
check_file "${ME}/keys/ed25519_master_id_public_key"
check_keys_eq ed25519_signing_secret_key
diff --git a/src/test/test_util.c b/src/test/test_util.c
index 8b4513d34c..0a5783e9f5 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -3654,7 +3654,6 @@ test_util_di_map(void *arg)
dimap_free(dimap, tor_free_);
}
-
/**
* Test counting high bits
*/
diff --git a/src/test/test_workqueue.c b/src/test/test_workqueue.c
index 7f20642041..0d79733cf0 100644
--- a/src/test/test_workqueue.c
+++ b/src/test/test_workqueue.c
@@ -70,7 +70,7 @@ mark_handled(int serial)
#endif
}
-static int
+static workqueue_reply_t
workqueue_do_rsa(void *state, void *work)
{
rsa_work_t *rw = work;
@@ -98,7 +98,7 @@ workqueue_do_rsa(void *state, void *work)
return WQ_RPL_REPLY;
}
-static int
+static workqueue_reply_t
workqueue_do_shutdown(void *state, void *work)
{
(void)state;
@@ -108,7 +108,7 @@ workqueue_do_shutdown(void *state, void *work)
return WQ_RPL_SHUTDOWN;
}
-static int
+static workqueue_reply_t
workqueue_do_ecdh(void *state, void *work)
{
ecdh_work_t *ew = work;
@@ -124,6 +124,14 @@ workqueue_do_ecdh(void *state, void *work)
return WQ_RPL_REPLY;
}
+static workqueue_reply_t
+workqueue_shutdown_error(void *state, void *work)
+{
+ (void)state;
+ (void)work;
+ return WQ_RPL_REPLY;
+}
+
static void *
new_state(void *arg)
{
@@ -156,6 +164,7 @@ static int n_sent = 0;
static int rsa_sent = 0;
static int ecdh_sent = 0;
static int n_received = 0;
+static int no_shutdown = 0;
#ifdef TRACK_RESPONSES
bitarray_t *received;
@@ -174,6 +183,14 @@ handle_reply(void *arg)
++n_received;
}
+/* This should never get called. */
+static void
+handle_reply_shutdown(void *arg)
+{
+ (void)arg;
+ no_shutdown = 1;
+}
+
static workqueue_entry_t *
add_work(threadpool_t *tp)
{
@@ -288,6 +305,9 @@ replysock_readable_cb(tor_socket_t sock, short what, void *arg)
shutting_down = 1;
threadpool_queue_update(tp, NULL,
workqueue_do_shutdown, NULL, NULL);
+ // Anything we add after starting the shutdown must not be executed.
+ threadpool_queue_work(tp, workqueue_shutdown_error,
+ handle_reply_shutdown, NULL);
{
struct timeval limit = { 2, 0 };
tor_event_base_loopexit(tor_libevent_get_base(), &limit);
@@ -416,6 +436,9 @@ main(int argc, char **argv)
printf("%d+%d vs %d\n", n_received, n_successful_cancel, n_sent);
puts("FAIL");
return 1;
+ } else if (no_shutdown) {
+ puts("Accepted work after shutdown\n");
+ puts("FAIL");
} else {
puts("OK");
return 0;
diff --git a/src/tools/tor-resolve.c b/src/tools/tor-resolve.c
index 08bce15e69..29f85c4d17 100644
--- a/src/tools/tor-resolve.c
+++ b/src/tools/tor-resolve.c
@@ -327,7 +327,7 @@ do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport,
static void
usage(void)
{
- puts("Syntax: tor-resolve [-4] [-5] [-v] [-x] [-F] [-p port] "
+ puts("Syntax: tor-resolve [-4] [-5] [-v] [-x] [-p port] "
"hostname [sockshost[:socksport]]");
exit(1);
}