summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/app/config/config.c1
-rw-r--r--src/core/include.am14
-rw-r--r--src/core/mainloop/mainloop.c1
-rw-r--r--src/core/mainloop/periodic.c5
-rw-r--r--src/core/or/circuitpadding.c4
-rw-r--r--src/core/or/circuituse.c1
-rw-r--r--src/feature/client/proxymode.c27
-rw-r--r--src/feature/client/proxymode.h17
-rw-r--r--src/feature/client/transports.c6
-rw-r--r--src/feature/control/control_getinfo.c64
-rw-r--r--src/feature/control/control_getinfo.h4
-rw-r--r--src/feature/dirauth/authmode.h1
-rw-r--r--src/feature/dircache/dirserv.c4
-rw-r--r--src/feature/dircache/dirserv.h2
-rw-r--r--src/feature/hibernate/hibernate.c6
-rw-r--r--src/feature/hs/hs_cell.c13
-rw-r--r--src/feature/nodelist/networkstatus.c8
-rw-r--r--src/feature/nodelist/networkstatus.h3
-rw-r--r--src/feature/relay/router.c4
-rw-r--r--src/feature/relay/router.h6
-rw-r--r--src/feature/relay/routermode.c17
-rw-r--r--src/feature/relay/routermode.h20
-rw-r--r--src/feature/rend/rendservice.c2
-rw-r--r--src/lib/err/backtrace.c12
-rw-r--r--src/lib/fs/mmap.c16
-rw-r--r--src/lib/fs/mmap.h5
-rw-r--r--src/lib/process/process_unix.c9
-rw-r--r--src/lib/process/process_win32.c18
-rw-r--r--src/test/conf_examples/bridgeauth_1/expected7
-rw-r--r--src/test/conf_examples/bridgeauth_1/expected_no_dirauth7
-rw-r--r--src/test/conf_examples/bridgeauth_1/expected_no_dirauth_relay6
-rw-r--r--src/test/conf_examples/bridgeauth_1/torrc8
-rw-r--r--src/test/conf_examples/dirauth_1/expected8
-rw-r--r--src/test/conf_examples/dirauth_1/expected_no_dirauth7
-rw-r--r--src/test/conf_examples/dirauth_1/expected_no_dirauth_relay6
-rw-r--r--src/test/conf_examples/dirauth_1/torrc8
-rw-r--r--src/test/conf_examples/ops_1/expected_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/ops_3/expected_no_dirauth_relay2
-rw-r--r--src/test/conf_examples/ops_4/expected_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/ops_5/expected_no_dirauth_relay2
-rw-r--r--src/test/test_controller.c137
-rwxr-xr-xsrc/test/test_key_expiration.sh5
-rwxr-xr-xsrc/test/test_keygen.sh5
-rwxr-xr-xsrc/test/test_parseconf.sh64
-rw-r--r--src/test/test_process_slow.c30
-rw-r--r--src/test/test_rebind.py16
-rwxr-xr-xsrc/test/test_zero_length_keys.sh5
47 files changed, 516 insertions, 99 deletions
diff --git a/src/app/config/config.c b/src/app/config/config.c
index 5f59ce32ff..a19ca13f57 100644
--- a/src/app/config/config.c
+++ b/src/app/config/config.c
@@ -2755,6 +2755,7 @@ list_deprecated_options(void)
static void
list_enabled_modules(void)
{
+ printf("%s: %s\n", "relay", have_module_relay() ? "yes" : "no");
printf("%s: %s\n", "dirauth", have_module_dirauth() ? "yes" : "no");
}
diff --git a/src/core/include.am b/src/core/include.am
index fb2f93d81e..565668abe3 100644
--- a/src/core/include.am
+++ b/src/core/include.am
@@ -72,6 +72,7 @@ LIBTOR_APP_A_SOURCES = \
src/feature/client/circpathbias.c \
src/feature/client/dnsserv.c \
src/feature/client/entrynodes.c \
+ src/feature/client/proxymode.c \
src/feature/client/transports.c \
src/feature/control/btrack.c \
src/feature/control/btrack_circuit.c \
@@ -146,7 +147,6 @@ LIBTOR_APP_A_SOURCES = \
src/feature/relay/relay_sys.c \
src/feature/relay/router.c \
src/feature/relay/routerkeys.c \
- src/feature/relay/routermode.c \
src/feature/relay/selftest.c \
src/feature/rend/rendcache.c \
src/feature/rend/rendclient.c \
@@ -170,6 +170,10 @@ endif
#
LIBTOR_APP_TESTING_A_SOURCES = $(LIBTOR_APP_A_SOURCES)
+# The Relay module.
+MODULE_RELAY_SOURCES = \
+ src/feature/relay/routermode.c
+
# The Directory Authority module.
MODULE_DIRAUTH_SOURCES = \
src/feature/dirauth/authmode.c \
@@ -189,6 +193,10 @@ MODULE_DIRAUTH_SOURCES = \
src/feature/dirauth/shared_random_state.c \
src/feature/dirauth/voteflags.c
+if BUILD_MODULE_RELAY
+LIBTOR_APP_A_SOURCES += $(MODULE_RELAY_SOURCES)
+endif
+
if BUILD_MODULE_DIRAUTH
LIBTOR_APP_A_SOURCES += $(MODULE_DIRAUTH_SOURCES)
endif
@@ -197,6 +205,7 @@ src_core_libtor_app_a_SOURCES = $(LIBTOR_APP_A_SOURCES)
if UNITTESTS_ENABLED
# Add the sources of the modules that are needed for tests to work here.
+LIBTOR_APP_TESTING_A_SOURCES += $(MODULE_RELAY_SOURCES)
LIBTOR_APP_TESTING_A_SOURCES += $(MODULE_DIRAUTH_SOURCES)
src_core_libtor_app_testing_a_SOURCES = $(LIBTOR_APP_TESTING_A_SOURCES)
@@ -306,6 +315,7 @@ noinst_HEADERS += \
src/feature/client/circpathbias.h \
src/feature/client/dnsserv.h \
src/feature/client/entrynodes.h \
+ src/feature/client/proxymode.h \
src/feature/client/transports.h \
src/feature/control/btrack_circuit.h \
src/feature/control/btrack_orconn.h \
@@ -324,7 +334,7 @@ noinst_HEADERS += \
src/feature/control/fmt_serverstatus.h \
src/feature/control/getinfo_geoip.h \
src/feature/dirauth/authmode.h \
- src/feature/dirauth/bridgeauth.h \
+ src/feature/dirauth/bridgeauth.h \
src/feature/dirauth/bwauth.h \
src/feature/dirauth/dirauth_periodic.h \
src/feature/dirauth/dirauth_sys.h \
diff --git a/src/core/mainloop/mainloop.c b/src/core/mainloop/mainloop.c
index 2f8be9961d..d58f263bdc 100644
--- a/src/core/mainloop/mainloop.c
+++ b/src/core/mainloop/mainloop.c
@@ -71,6 +71,7 @@
#include "feature/client/bridges.h"
#include "feature/client/dnsserv.h"
#include "feature/client/entrynodes.h"
+#include "feature/client/proxymode.h"
#include "feature/client/transports.h"
#include "feature/control/control.h"
#include "feature/control/control_events.h"
diff --git a/src/core/mainloop/periodic.c b/src/core/mainloop/periodic.c
index 51a0165d19..efc6a63165 100644
--- a/src/core/mainloop/periodic.c
+++ b/src/core/mainloop/periodic.c
@@ -153,6 +153,11 @@ periodic_event_disconnect(periodic_event_item_t *event)
{
if (!event)
return;
+
+ /* First disable the event so we first cancel the event and set its enabled
+ * flag properly. */
+ periodic_event_disable(event);
+
mainloop_event_free(event->ev);
event->last_action_time = 0;
}
diff --git a/src/core/or/circuitpadding.c b/src/core/or/circuitpadding.c
index 99c68d5f6b..178f066baf 100644
--- a/src/core/or/circuitpadding.c
+++ b/src/core/or/circuitpadding.c
@@ -2179,8 +2179,8 @@ circpad_add_matching_machines(origin_circuit_t *on_circ,
circ->padding_machine[i] = NULL;
on_circ->padding_negotiation_failed = 1;
} else {
- /* Success. Don't try any more machines */
- return;
+ /* Success. Don't try any more machines on this index */
+ break;
}
}
} SMARTLIST_FOREACH_END(machine);
diff --git a/src/core/or/circuituse.c b/src/core/or/circuituse.c
index 606c5e2dd2..a74ecbfd54 100644
--- a/src/core/or/circuituse.c
+++ b/src/core/or/circuituse.c
@@ -42,6 +42,7 @@
#include "feature/client/bridges.h"
#include "feature/client/circpathbias.h"
#include "feature/client/entrynodes.h"
+#include "feature/client/proxymode.h"
#include "feature/control/control_events.h"
#include "feature/dircommon/directory.h"
#include "feature/hs/hs_circuit.h"
diff --git a/src/feature/client/proxymode.c b/src/feature/client/proxymode.c
new file mode 100644
index 0000000000..3b5fba5cda
--- /dev/null
+++ b/src/feature/client/proxymode.c
@@ -0,0 +1,27 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "core/or/or.h"
+
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "core/or/port_cfg_st.h"
+#include "feature/client/proxymode.h"
+
+/** Return true iff we are trying to proxy client connections. */
+int
+proxy_mode(const or_options_t *options)
+{
+ (void)options;
+ SMARTLIST_FOREACH_BEGIN(get_configured_ports(), const port_cfg_t *, p) {
+ if (p->type == CONN_TYPE_AP_LISTENER ||
+ p->type == CONN_TYPE_AP_TRANS_LISTENER ||
+ p->type == CONN_TYPE_AP_DNS_LISTENER ||
+ p->type == CONN_TYPE_AP_NATD_LISTENER)
+ return 1;
+ } SMARTLIST_FOREACH_END(p);
+ return 0;
+}
diff --git a/src/feature/client/proxymode.h b/src/feature/client/proxymode.h
new file mode 100644
index 0000000000..f8352922c7
--- /dev/null
+++ b/src/feature/client/proxymode.h
@@ -0,0 +1,17 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file proxymode.h
+ * \brief Header file for proxymode.c.
+ **/
+
+#ifndef TOR_PROXYMODE_H
+#define TOR_PROXYMODE_H
+
+int proxy_mode(const or_options_t *options);
+
+#endif
diff --git a/src/feature/client/transports.c b/src/feature/client/transports.c
index 97bfc8ae30..3f731ac7d4 100644
--- a/src/feature/client/transports.c
+++ b/src/feature/client/transports.c
@@ -1826,15 +1826,13 @@ managed_proxy_stdout_callback(process_t *process,
managed_proxy_t *mp = process_get_data(process);
- if (BUG(mp == NULL))
+ if (mp == NULL)
return;
handle_proxy_line(line, mp);
- if (proxy_configuration_finished(mp)) {
+ if (proxy_configuration_finished(mp))
handle_finished_proxy(mp);
- tor_assert(mp->conf_state == PT_PROTO_COMPLETED);
- }
}
/** Callback function that is called when our PT process have data on its
diff --git a/src/feature/control/control_getinfo.c b/src/feature/control/control_getinfo.c
index 3e31bb9e8f..979fa4480d 100644
--- a/src/feature/control/control_getinfo.c
+++ b/src/feature/control/control_getinfo.c
@@ -325,6 +325,41 @@ getinfo_helper_current_time(control_connection_t *control_conn,
return 0;
}
+/** GETINFO helper for dumping different consensus flavors
+ * returns: 0 on success -1 on error. */
+STATIC int
+getinfo_helper_current_consensus(consensus_flavor_t flavor,
+ char** answer,
+ const char** errmsg)
+{
+ const char *flavor_name = networkstatus_get_flavor_name(flavor);
+ if (BUG(!strcmp(flavor_name, "??"))) {
+ *errmsg = "Internal error: unrecognized flavor name.";
+ return -1;
+ }
+ if (we_want_to_fetch_flavor(get_options(), flavor)) {
+ /** Check from the cache */
+ const cached_dir_t *consensus = dirserv_get_consensus(flavor_name);
+ if (consensus) {
+ *answer = tor_strdup(consensus->dir);
+ }
+ }
+ if (!*answer) { /* try loading it from disk */
+
+ tor_mmap_t *mapped = networkstatus_map_cached_consensus(flavor_name);
+ if (mapped) {
+ *answer = tor_memdup_nulterm(mapped->data, mapped->size);
+ tor_munmap_file(mapped);
+ }
+ if (!*answer) { /* generate an error */
+ *errmsg = "Could not open cached consensus. "
+ "Make sure FetchUselessDescriptors is set to 1.";
+ return -1;
+ }
+ }
+ return 0;
+}
+
/** Implementation helper for GETINFO: knows the answers for questions about
* directory information. */
STATIC int
@@ -576,23 +611,18 @@ getinfo_helper_dir(control_connection_t *control_conn,
smartlist_free(descs);
} else if (!strcmpstart(question, "dir/status/")) {
*answer = tor_strdup("");
- } else if (!strcmp(question, "dir/status-vote/current/consensus")) { /* v3 */
- if (we_want_to_fetch_flavor(get_options(), FLAV_NS)) {
- const cached_dir_t *consensus = dirserv_get_consensus("ns");
- if (consensus)
- *answer = tor_strdup(consensus->dir);
+ } else if (!strcmp(question, "dir/status-vote/current/consensus")) {
+ int consensus_result = getinfo_helper_current_consensus(FLAV_NS,
+ answer, errmsg);
+ if (consensus_result < 0) {
+ return -1;
}
- if (!*answer) { /* try loading it from disk */
- tor_mmap_t *mapped = networkstatus_map_cached_consensus("ns");
- if (mapped) {
- *answer = tor_memdup_nulterm(mapped->data, mapped->size);
- tor_munmap_file(mapped);
- }
- if (!*answer) { /* generate an error */
- *errmsg = "Could not open cached consensus. "
- "Make sure FetchUselessDescriptors is set to 1.";
- return -1;
- }
+ } else if (!strcmp(question,
+ "dir/status-vote/current/consensus-microdesc")) {
+ int consensus_result = getinfo_helper_current_consensus(FLAV_MICRODESC,
+ answer, errmsg);
+ if (consensus_result < 0) {
+ return -1;
}
} else if (!strcmp(question, "network-status")) { /* v1 */
static int network_status_warned = 0;
@@ -1513,6 +1543,8 @@ static const getinfo_item_t getinfo_items[] = {
"v2 networkstatus docs as retrieved from a DirPort."),
ITEM("dir/status-vote/current/consensus", dir,
"v3 Networkstatus consensus as retrieved from a DirPort."),
+ ITEM("dir/status-vote/current/consensus-microdesc", dir,
+ "v3 Microdescriptor consensus as retrieved from a DirPort."),
ITEM("exit-policy/default", policies,
"The default value appended to the configured exit policy."),
ITEM("exit-policy/reject-private/default", policies,
diff --git a/src/feature/control/control_getinfo.h b/src/feature/control/control_getinfo.h
index 52978686d8..86aaf7c4f7 100644
--- a/src/feature/control/control_getinfo.h
+++ b/src/feature/control/control_getinfo.h
@@ -48,6 +48,10 @@ STATIC int getinfo_helper_downloads(
control_connection_t *control_conn,
const char *question, char **answer,
const char **errmsg);
+STATIC int getinfo_helper_current_consensus(
+ consensus_flavor_t flavor,
+ char **answer,
+ const char **errmsg);
STATIC int getinfo_helper_dir(
control_connection_t *control_conn,
const char *question, char **answer,
diff --git a/src/feature/dirauth/authmode.h b/src/feature/dirauth/authmode.h
index bfd5f4dc04..11bc40d8d1 100644
--- a/src/feature/dirauth/authmode.h
+++ b/src/feature/dirauth/authmode.h
@@ -27,6 +27,7 @@ authdir_mode_v3(const or_options_t *options)
return authdir_mode(options) && options->V3AuthoritativeDir != 0;
}
+/* Is the dirauth module enabled? */
#define have_module_dirauth() (1)
#else /* !defined(HAVE_MODULE_DIRAUTH) */
diff --git a/src/feature/dircache/dirserv.c b/src/feature/dircache/dirserv.c
index 79400bf15f..85331bfeaa 100644
--- a/src/feature/dircache/dirserv.c
+++ b/src/feature/dircache/dirserv.c
@@ -259,8 +259,8 @@ dirserv_set_cached_consensus_networkstatus(const char *networkstatus,
/** Return the latest downloaded consensus networkstatus in encoded, signed,
* optionally compressed format, suitable for sending to clients. */
-cached_dir_t *
-dirserv_get_consensus(const char *flavor_name)
+MOCK_IMPL(cached_dir_t *,
+dirserv_get_consensus,(const char *flavor_name))
{
if (!cached_consensuses)
return NULL;
diff --git a/src/feature/dircache/dirserv.h b/src/feature/dircache/dirserv.h
index 7f944459da..0c15c9ad19 100644
--- a/src/feature/dircache/dirserv.h
+++ b/src/feature/dircache/dirserv.h
@@ -82,7 +82,7 @@ int directory_permits_begindir_requests(const or_options_t *options);
int directory_too_idle_to_fetch_descriptors(const or_options_t *options,
time_t now);
-cached_dir_t *dirserv_get_consensus(const char *flavor_name);
+MOCK_DECL(cached_dir_t *, dirserv_get_consensus, (const char *flavor_name));
void dirserv_set_cached_consensus_networkstatus(const char *consensus,
size_t consensus_len,
const char *flavor_name,
diff --git a/src/feature/hibernate/hibernate.c b/src/feature/hibernate/hibernate.c
index 674fe3c813..f7847d9a16 100644
--- a/src/feature/hibernate/hibernate.c
+++ b/src/feature/hibernate/hibernate.c
@@ -67,7 +67,7 @@ static hibernate_state_t hibernate_state = HIBERNATE_STATE_INITIAL;
/** If are hibernating, when do we plan to wake up? Set to 0 if we
* aren't hibernating. */
static time_t hibernate_end_time = 0;
-/** If we are shutting down, when do we plan finally exit? Set to 0 if we
+/** If we are shutting down, when do we plan to finally exit? Set to 0 if we
* aren't shutting down. (This is obsolete; scheduled shutdowns are supposed
* to happen from mainloop_schedule_shutdown() now.) */
static time_t shutdown_time = 0;
@@ -562,7 +562,7 @@ time_to_record_bandwidth_usage(time_t now)
/* Note every 600 sec */
#define NOTE_INTERVAL (600)
/* Or every 20 megabytes */
-#define NOTE_BYTES 20*(1024*1024)
+#define NOTE_BYTES (20*1024*1024)
static uint64_t last_read_bytes_noted = 0;
static uint64_t last_written_bytes_noted = 0;
static time_t last_time_noted = 0;
@@ -815,7 +815,7 @@ hibernate_soft_limit_reached(void)
* We want to stop accepting connections when ALL of the following are true:
* - We expect to use up the remaining bytes in under 3 hours
* - We have used up 95% of our bytes.
- * - We have less than 500MB of bytes left.
+ * - We have less than 500MBytes left.
*/
uint64_t soft_limit = (uint64_t) (acct_max * SOFT_LIM_PCT);
if (acct_max > SOFT_LIM_BYTES && acct_max - SOFT_LIM_BYTES > soft_limit) {
diff --git a/src/feature/hs/hs_cell.c b/src/feature/hs/hs_cell.c
index 2d4a761eb9..eaf8820e9f 100644
--- a/src/feature/hs/hs_cell.c
+++ b/src/feature/hs/hs_cell.c
@@ -503,8 +503,8 @@ build_establish_intro_dos_extension(const hs_service_config_t *service_config,
ssize_t ret;
size_t dos_ext_encoded_len;
uint8_t *field_array;
- trn_cell_extension_field_t *field;
- trn_cell_extension_dos_t *dos_ext;
+ trn_cell_extension_field_t *field = NULL;
+ trn_cell_extension_dos_t *dos_ext = NULL;
tor_assert(service_config);
tor_assert(extensions);
@@ -530,7 +530,7 @@ build_establish_intro_dos_extension(const hs_service_config_t *service_config,
/* Set the field with the encoded DoS extension. */
ret = trn_cell_extension_dos_encoded_len(dos_ext);
if (BUG(ret <= 0)) {
- return -1;
+ goto err;
}
dos_ext_encoded_len = ret;
/* Set length field and the field array size length. */
@@ -541,7 +541,7 @@ build_establish_intro_dos_extension(const hs_service_config_t *service_config,
ret = trn_cell_extension_dos_encode(field_array,
trn_cell_extension_field_getlen_field(field), dos_ext);
if (BUG(ret <= 0)) {
- return -1;
+ goto err;
}
tor_assert(ret == (ssize_t) dos_ext_encoded_len);
@@ -557,6 +557,11 @@ build_establish_intro_dos_extension(const hs_service_config_t *service_config,
trn_cell_extension_dos_free(dos_ext);
return 0;
+
+ err:
+ trn_cell_extension_field_free(field);
+ trn_cell_extension_dos_free(dos_ext);
+ return -1;
}
/* ========== */
diff --git a/src/feature/nodelist/networkstatus.c b/src/feature/nodelist/networkstatus.c
index 496bafb865..b4b98301b0 100644
--- a/src/feature/nodelist/networkstatus.c
+++ b/src/feature/nodelist/networkstatus.c
@@ -216,10 +216,10 @@ networkstatus_reset_download_failures(void)
}
/** Return the filename used to cache the consensus of a given flavor */
-static char *
-networkstatus_get_cache_fname(int flav,
- const char *flavorname,
- int unverified_consensus)
+MOCK_IMPL(char *,
+networkstatus_get_cache_fname,(int flav,
+ const char *flavorname,
+ int unverified_consensus))
{
char buf[128];
const char *prefix;
diff --git a/src/feature/nodelist/networkstatus.h b/src/feature/nodelist/networkstatus.h
index 600fd7fbd5..e2c6ba611a 100644
--- a/src/feature/nodelist/networkstatus.h
+++ b/src/feature/nodelist/networkstatus.h
@@ -16,6 +16,9 @@
void networkstatus_reset_warnings(void);
void networkstatus_reset_download_failures(void);
+MOCK_DECL(char *,networkstatus_get_cache_fname,(int flav,
+ const char *flavorname,
+ int unverified_consensus));
tor_mmap_t *networkstatus_map_cached_consensus(const char *flavorname);
int router_reload_consensus_networkstatus(void);
void routerstatus_free_(routerstatus_t *rs);
diff --git a/src/feature/relay/router.c b/src/feature/relay/router.c
index ab0762e17e..92803f88a9 100644
--- a/src/feature/relay/router.c
+++ b/src/feature/relay/router.c
@@ -372,6 +372,8 @@ assert_identity_keys_ok(void)
}
}
+#ifdef HAVE_MODULE_RELAY
+
/** Returns the current server identity key; requires that the key has
* been set, and that we are running as a Tor server.
*/
@@ -384,6 +386,8 @@ get_server_identity_key,(void))
return server_identitykey;
}
+#endif
+
/** Return true iff we are a server and the server identity key
* has been set. */
int
diff --git a/src/feature/relay/router.h b/src/feature/relay/router.h
index 55b9ef9e68..a708b24889 100644
--- a/src/feature/relay/router.h
+++ b/src/feature/relay/router.h
@@ -28,7 +28,13 @@ struct ed25519_keypair_t;
MOCK_DECL(crypto_pk_t *,get_onion_key,(void));
time_t get_onion_key_set_at(void);
void set_server_identity_key(crypto_pk_t *k);
+/* Some compilers are clever enough to know that when relay mode is disabled,
+ * this function never returns. */
+#ifdef HAVE_MODULE_RELAY
MOCK_DECL(crypto_pk_t *,get_server_identity_key,(void));
+#else
+#define get_server_identity_key() (tor_abort_(),NULL)
+#endif
int server_identity_key_is_set(void);
void set_client_identity_key(crypto_pk_t *k);
crypto_pk_t *get_tlsclient_identity_key(void);
diff --git a/src/feature/relay/routermode.c b/src/feature/relay/routermode.c
index 2a9ddeac4d..3613841b1e 100644
--- a/src/feature/relay/routermode.c
+++ b/src/feature/relay/routermode.c
@@ -7,8 +7,6 @@
#include "core/or/or.h"
#include "app/config/config.h"
-#include "core/mainloop/connection.h"
-#include "core/or/port_cfg_st.h"
#include "feature/relay/router.h"
#include "feature/relay/routermode.h"
@@ -25,21 +23,6 @@ dir_server_mode(const or_options_t *options)
(server_mode(options) && router_has_bandwidth_to_be_dirserver(options));
}
-/** Return true iff we are trying to proxy client connections. */
-int
-proxy_mode(const or_options_t *options)
-{
- (void)options;
- SMARTLIST_FOREACH_BEGIN(get_configured_ports(), const port_cfg_t *, p) {
- if (p->type == CONN_TYPE_AP_LISTENER ||
- p->type == CONN_TYPE_AP_TRANS_LISTENER ||
- p->type == CONN_TYPE_AP_DNS_LISTENER ||
- p->type == CONN_TYPE_AP_NATD_LISTENER)
- return 1;
- } SMARTLIST_FOREACH_END(p);
- return 0;
-}
-
/** Return true iff we are trying to be a server.
*/
MOCK_IMPL(int,
diff --git a/src/feature/relay/routermode.h b/src/feature/relay/routermode.h
index be535af478..f6195a8698 100644
--- a/src/feature/relay/routermode.h
+++ b/src/feature/relay/routermode.h
@@ -12,13 +12,31 @@
#ifndef TOR_ROUTERMODE_H
#define TOR_ROUTERMODE_H
+#ifdef HAVE_MODULE_RELAY
+
int dir_server_mode(const or_options_t *options);
MOCK_DECL(int, server_mode, (const or_options_t *options));
MOCK_DECL(int, public_server_mode, (const or_options_t *options));
MOCK_DECL(int, advertised_server_mode, (void));
-int proxy_mode(const or_options_t *options);
void set_server_advertised(int s);
+/** Is the relay module enabled? */
+#define have_module_relay() (1)
+
+#else
+
+#define dir_server_mode(options) (((void)(options)),0)
+#define server_mode(options) (((void)(options)),0)
+#define public_server_mode(options) (((void)(options)),0)
+#define advertised_server_mode() (0)
+
+/* We shouldn't be publishing descriptors when relay mode is disabled. */
+#define set_server_advertised(s) tor_assert_nonfatal(!(s))
+
+#define have_module_relay() (0)
+
+#endif
+
#endif /* !defined(TOR_ROUTERMODE_H) */
diff --git a/src/feature/rend/rendservice.c b/src/feature/rend/rendservice.c
index 4d8a21e6a1..e0cf06b9df 100644
--- a/src/feature/rend/rendservice.c
+++ b/src/feature/rend/rendservice.c
@@ -3999,7 +3999,7 @@ remove_invalid_intro_points(rend_service_t *service,
* accounted for when considiring uploading a descriptor. */
intro->circuit_established = 0;
- /* Node is gone or we've reached our maximum circuit creationg retry
+ /* Node is gone or we've reached our maximum circuit creation retry
* count, clean up everything, we'll find a new one. */
if (node == NULL ||
intro->circuit_retries >= MAX_INTRO_POINT_CIRCUIT_RETRIES) {
diff --git a/src/lib/err/backtrace.c b/src/lib/err/backtrace.c
index bc3ca286ec..ce8ddcd7c0 100644
--- a/src/lib/err/backtrace.c
+++ b/src/lib/err/backtrace.c
@@ -85,7 +85,7 @@ static pthread_mutex_t cb_buf_mutex = PTHREAD_MUTEX_INITIALIZER;
/** Lock and return a static stack pointer buffer that can hold up to
* MAX_DEPTH function pointers. */
-static void *
+static void **
lock_cb_buf(void)
{
/* Lock the mutex first, before even declaring the buffer. */
@@ -102,7 +102,7 @@ lock_cb_buf(void)
/** Unlock the static stack pointer buffer. */
static void
-unlock_cb_buf(void *cb_buf)
+unlock_cb_buf(void **cb_buf)
{
memset(cb_buf, 0, SIZEOF_CB_BUF);
pthread_mutex_unlock(&cb_buf_mutex);
@@ -149,7 +149,7 @@ log_backtrace_impl(int severity, log_domain_mask_t domain, const char *msg,
char **symbols;
size_t i;
- void *cb_buf = lock_cb_buf();
+ void **cb_buf = lock_cb_buf();
depth = backtrace(cb_buf, MAX_DEPTH);
symbols = backtrace_symbols(cb_buf, (int)depth);
@@ -183,7 +183,7 @@ crash_handler(int sig, siginfo_t *si, void *ctx_)
int n_fds, i;
const int *fds = NULL;
- void *cb_buf = lock_cb_buf();
+ void **cb_buf = lock_cb_buf();
(void) si;
@@ -214,7 +214,7 @@ dump_stack_symbols_to_error_fds(void)
const int *fds = NULL;
size_t depth;
- void *cb_buf = lock_cb_buf();
+ void **cb_buf = lock_cb_buf();
depth = backtrace(cb_buf, MAX_DEPTH);
@@ -256,7 +256,7 @@ install_bt_handler(void)
* libc has pre-loaded the symbols we need to dump things, so that later
* reads won't be denied by the sandbox code */
char **symbols;
- void *cb_buf = lock_cb_buf();
+ void **cb_buf = lock_cb_buf();
size_t depth = backtrace(cb_buf, MAX_DEPTH);
symbols = backtrace_symbols(cb_buf, (int) depth);
if (symbols)
diff --git a/src/lib/fs/mmap.c b/src/lib/fs/mmap.c
index f71c0cff7a..9d50a476bd 100644
--- a/src/lib/fs/mmap.c
+++ b/src/lib/fs/mmap.c
@@ -42,8 +42,8 @@
* failure, return NULL. Sets errno properly, using ERANGE to mean
* "empty file". Must only be called on trusted Tor-owned files, as changing
* the underlying file's size causes unspecified behavior. */
-tor_mmap_t *
-tor_mmap_file(const char *filename)
+MOCK_IMPL(tor_mmap_t *,
+tor_mmap_file,(const char *filename))
{
int fd; /* router file */
char *string;
@@ -111,8 +111,8 @@ tor_mmap_file(const char *filename)
}
/** Release storage held for a memory mapping; returns 0 on success,
* or -1 on failure (and logs a warning). */
-int
-tor_munmap_file(tor_mmap_t *handle)
+MOCK_IMPL(int,
+tor_munmap_file,(tor_mmap_t *handle))
{
int res;
@@ -132,8 +132,8 @@ tor_munmap_file(tor_mmap_t *handle)
return res;
}
#elif defined(_WIN32)
-tor_mmap_t *
-tor_mmap_file(const char *filename)
+MOCK_IMPL(tor_mmap_t *,
+tor_mmap_file,(const char *filename))
{
TCHAR tfilename[MAX_PATH]= {0};
tor_mmap_t *res = tor_malloc_zero(sizeof(tor_mmap_t));
@@ -213,8 +213,8 @@ tor_mmap_file(const char *filename)
}
/* Unmap the file, and return 0 for success or -1 for failure */
-int
-tor_munmap_file(tor_mmap_t *handle)
+MOCK_IMPL(int,
+tor_munmap_file,(tor_mmap_t *handle))
{
if (handle == NULL)
return 0;
diff --git a/src/lib/fs/mmap.h b/src/lib/fs/mmap.h
index 61aad544b2..beb0535109 100644
--- a/src/lib/fs/mmap.h
+++ b/src/lib/fs/mmap.h
@@ -13,6 +13,7 @@
#define TOR_MMAP_H
#include "lib/cc/compat_compiler.h"
+#include "lib/testsupport/testsupport.h"
#include <stddef.h>
#ifdef _WIN32
@@ -35,7 +36,7 @@ typedef struct tor_mmap_t {
} tor_mmap_t;
-tor_mmap_t *tor_mmap_file(const char *filename);
-int tor_munmap_file(tor_mmap_t *handle);
+MOCK_DECL(tor_mmap_t *, tor_mmap_file, (const char *filename));
+MOCK_DECL(int, tor_munmap_file, (tor_mmap_t *handle));
#endif /* !defined(TOR_MMAP_H) */
diff --git a/src/lib/process/process_unix.c b/src/lib/process/process_unix.c
index 332b432c54..8191bdc1f0 100644
--- a/src/lib/process/process_unix.c
+++ b/src/lib/process/process_unix.c
@@ -253,22 +253,15 @@ process_unix_exec(process_t *process)
process_environment_t *env = process_get_environment(process);
/* Call the requested program. */
- retval = execve(argv[0], argv, env->unixoid_environment_block);
+ execve(argv[0], argv, env->unixoid_environment_block);
/* If we made it here it is because execve failed :-( */
- if (-1 == retval)
- fprintf(stderr, "Call to execve() failed: %s", strerror(errno));
-
tor_free(argv);
process_environment_free(env);
- tor_assert_unreached();
-
error:
- /* LCOV_EXCL_START */
fprintf(stderr, "Error from child process: %s", strerror(errno));
_exit(1);
- /* LCOV_EXCL_STOP */
}
/* We are in the parent process. */
diff --git a/src/lib/process/process_win32.c b/src/lib/process/process_win32.c
index 624333d4a3..7e4082ad13 100644
--- a/src/lib/process/process_win32.c
+++ b/src/lib/process/process_win32.c
@@ -234,6 +234,24 @@ process_win32_exec(process_t *process)
CloseHandle(stdin_pipe_read);
CloseHandle(stdin_pipe_write);
+ /* In the Unix backend, we do not get an error in the Tor process when a
+ * child process fails to spawn its target executable since we need to
+ * first do the fork() call in the Tor process and then the child process
+ * is responsible for doing the call to execve().
+ *
+ * This means that the user of the process_exec() API must check for
+ * whether it returns PROCESS_STATUS_ERROR, which will rarely happen on
+ * Unix, but will happen for error cases on Windows where it does not
+ * happen on Unix. For example: when the target executable does not exist
+ * on the file system.
+ *
+ * To have somewhat feature compatibility between the Unix and the Windows
+ * backend, we here notify the process_t owner that the process have exited
+ * (even though it never managed to run) to ensure that the exit callback
+ * is executed.
+ */
+ process_notify_event_exit(process, 0);
+
return PROCESS_STATUS_ERROR;
}
diff --git a/src/test/conf_examples/bridgeauth_1/expected b/src/test/conf_examples/bridgeauth_1/expected
new file mode 100644
index 0000000000..d43aaf2c8b
--- /dev/null
+++ b/src/test/conf_examples/bridgeauth_1/expected
@@ -0,0 +1,7 @@
+Address 198.51.100.123
+AuthoritativeDirectory 1
+BridgeAuthoritativeDir 1
+ContactInfo tor_parse_test@example.com
+DirPort 80
+Nickname Unnamed
+ORPort 443
diff --git a/src/test/conf_examples/bridgeauth_1/expected_no_dirauth b/src/test/conf_examples/bridgeauth_1/expected_no_dirauth
new file mode 100644
index 0000000000..d43aaf2c8b
--- /dev/null
+++ b/src/test/conf_examples/bridgeauth_1/expected_no_dirauth
@@ -0,0 +1,7 @@
+Address 198.51.100.123
+AuthoritativeDirectory 1
+BridgeAuthoritativeDir 1
+ContactInfo tor_parse_test@example.com
+DirPort 80
+Nickname Unnamed
+ORPort 443
diff --git a/src/test/conf_examples/bridgeauth_1/expected_no_dirauth_relay b/src/test/conf_examples/bridgeauth_1/expected_no_dirauth_relay
new file mode 100644
index 0000000000..e059d79971
--- /dev/null
+++ b/src/test/conf_examples/bridgeauth_1/expected_no_dirauth_relay
@@ -0,0 +1,6 @@
+Address 198.51.100.123
+AuthoritativeDirectory 1
+BridgeAuthoritativeDir 1
+ContactInfo tor_parse_test@example.com
+DirPort 80
+ORPort 443
diff --git a/src/test/conf_examples/bridgeauth_1/torrc b/src/test/conf_examples/bridgeauth_1/torrc
new file mode 100644
index 0000000000..740bc6c2eb
--- /dev/null
+++ b/src/test/conf_examples/bridgeauth_1/torrc
@@ -0,0 +1,8 @@
+AuthoritativeDirectory 1
+BridgeAuthoritativeDir 1
+
+ContactInfo tor_parse_test@example.com
+
+Address 198.51.100.123
+ORPort 443
+DirPort 80
diff --git a/src/test/conf_examples/dirauth_1/expected b/src/test/conf_examples/dirauth_1/expected
new file mode 100644
index 0000000000..901f7d947f
--- /dev/null
+++ b/src/test/conf_examples/dirauth_1/expected
@@ -0,0 +1,8 @@
+Address 192.0.2.1
+AuthoritativeDirectory 1
+ContactInfo tor_parse_test@example.net
+DirPort 9030
+DownloadExtraInfo 1
+Nickname Unnamed
+ORPort 9001
+V3AuthoritativeDirectory 1
diff --git a/src/test/conf_examples/dirauth_1/expected_no_dirauth b/src/test/conf_examples/dirauth_1/expected_no_dirauth
new file mode 100644
index 0000000000..f006c6f8f2
--- /dev/null
+++ b/src/test/conf_examples/dirauth_1/expected_no_dirauth
@@ -0,0 +1,7 @@
+Address 192.0.2.1
+AuthoritativeDirectory 1
+ContactInfo tor_parse_test@example.net
+DirPort 9030
+Nickname Unnamed
+ORPort 9001
+V3AuthoritativeDirectory 1
diff --git a/src/test/conf_examples/dirauth_1/expected_no_dirauth_relay b/src/test/conf_examples/dirauth_1/expected_no_dirauth_relay
new file mode 100644
index 0000000000..4b9ad49bb2
--- /dev/null
+++ b/src/test/conf_examples/dirauth_1/expected_no_dirauth_relay
@@ -0,0 +1,6 @@
+Address 192.0.2.1
+AuthoritativeDirectory 1
+ContactInfo tor_parse_test@example.net
+DirPort 9030
+ORPort 9001
+V3AuthoritativeDirectory 1
diff --git a/src/test/conf_examples/dirauth_1/torrc b/src/test/conf_examples/dirauth_1/torrc
new file mode 100644
index 0000000000..b870e6e8e0
--- /dev/null
+++ b/src/test/conf_examples/dirauth_1/torrc
@@ -0,0 +1,8 @@
+AuthoritativeDirectory 1
+V3AuthoritativeDirectory 1
+
+ContactInfo tor_parse_test@example.net
+
+Address 192.0.2.1
+ORPort 9001
+DirPort 9030
diff --git a/src/test/conf_examples/ops_1/expected_no_dirauth_relay b/src/test/conf_examples/ops_1/expected_no_dirauth_relay
new file mode 100644
index 0000000000..2bb9bfa132
--- /dev/null
+++ b/src/test/conf_examples/ops_1/expected_no_dirauth_relay
@@ -0,0 +1 @@
+ORPort 1000
diff --git a/src/test/conf_examples/ops_3/expected_no_dirauth_relay b/src/test/conf_examples/ops_3/expected_no_dirauth_relay
new file mode 100644
index 0000000000..93dea50eeb
--- /dev/null
+++ b/src/test/conf_examples/ops_3/expected_no_dirauth_relay
@@ -0,0 +1,2 @@
+ORPort 9999
+ORPort 1000
diff --git a/src/test/conf_examples/ops_4/expected_no_dirauth_relay b/src/test/conf_examples/ops_4/expected_no_dirauth_relay
new file mode 100644
index 0000000000..56b3a5b71f
--- /dev/null
+++ b/src/test/conf_examples/ops_4/expected_no_dirauth_relay
@@ -0,0 +1 @@
+ORPort 9099
diff --git a/src/test/conf_examples/ops_5/expected_no_dirauth_relay b/src/test/conf_examples/ops_5/expected_no_dirauth_relay
new file mode 100644
index 0000000000..834a785090
--- /dev/null
+++ b/src/test/conf_examples/ops_5/expected_no_dirauth_relay
@@ -0,0 +1,2 @@
+ORPort 9000
+ORPort 9099
diff --git a/src/test/test_controller.c b/src/test/test_controller.c
index 55eb79e448..8d9c3e8eaf 100644
--- a/src/test/test_controller.c
+++ b/src/test/test_controller.c
@@ -27,6 +27,7 @@
#include "feature/dirclient/download_status_st.h"
#include "feature/nodelist/microdesc_st.h"
#include "feature/nodelist/node_st.h"
+#include "feature/dircache/dirserv.c"
typedef struct {
const char *input;
@@ -1691,6 +1692,138 @@ test_download_status_bridge(void *arg)
return;
}
+/** Mock cached consensus */
+static cached_dir_t *mock_ns_consensus_cache;
+static cached_dir_t *mock_microdesc_consensus_cache;
+
+/** Mock the function that retrieves consensus from cache. These use a
+ * global variable so that they can be cleared from within the test.
+ * The actual code retains the pointer to the consensus data, but
+ * we are doing this here, to prevent memory leaks
+ * from within the tests */
+static cached_dir_t *
+mock_dirserv_get_consensus(const char *flavor_name)
+{
+ if (!strcmp(flavor_name, "ns")) {
+ mock_ns_consensus_cache = tor_malloc_zero(sizeof(cached_dir_t));
+ mock_ns_consensus_cache->dir = tor_strdup("mock_ns_consensus");
+ return mock_ns_consensus_cache;
+ } else {
+ mock_microdesc_consensus_cache = tor_malloc_zero(sizeof(cached_dir_t));
+ mock_microdesc_consensus_cache->dir = tor_strdup(
+ "mock_microdesc_consensus");
+ return mock_microdesc_consensus_cache;
+ }
+}
+
+/** Mock the function that retrieves consensuses
+ * from a files in the directory. */
+static tor_mmap_t *
+mock_tor_mmap_file(const char* filename)
+{
+ tor_mmap_t *res;
+ res = tor_malloc_zero(sizeof(tor_mmap_t));
+ if (strstr(filename, "cached-consensus") != NULL) {
+ res->data = "mock_ns_consensus";
+ } else if (strstr(filename, "cached-microdesc-consensus") != NULL) {
+ res->data = "mock_microdesc_consensus";
+ } else {
+ res->data = ".";
+ }
+ res->size = strlen(res->data);
+ return res;
+}
+
+/** Mock the function that clears file data
+ * loaded into the memory */
+static int
+mock_tor_munmap_file(tor_mmap_t *handle)
+{
+ tor_free(handle);
+ return 0;
+}
+
+static void
+test_getinfo_helper_current_consensus_from_file(void *arg)
+{
+ /* We just need one of these to pass, it doesn't matter what's in it */
+ control_connection_t dummy;
+ /* Get results out */
+ char *answer = NULL;
+ const char *errmsg = NULL;
+
+ (void)arg;
+
+ MOCK(tor_mmap_file, mock_tor_mmap_file);
+ MOCK(tor_munmap_file, mock_tor_munmap_file);
+
+ getinfo_helper_dir(&dummy,
+ "dir/status-vote/current/consensus",
+ &answer,
+ &errmsg);
+ tt_str_op(answer, OP_EQ, "mock_ns_consensus");
+ tt_ptr_op(errmsg, OP_EQ, NULL);
+ tor_free(answer);
+ errmsg = NULL;
+
+ getinfo_helper_dir(&dummy,
+ "dir/status-vote/current/consensus-microdesc",
+ &answer,
+ &errmsg);
+ tt_str_op(answer, OP_EQ, "mock_microdesc_consensus");
+ tt_ptr_op(errmsg, OP_EQ, NULL);
+ errmsg = NULL;
+
+ done:
+ tor_free(answer);
+ UNMOCK(tor_mmap_file);
+ UNMOCK(tor_munmap_file);
+ return;
+}
+
+static void
+test_getinfo_helper_current_consensus_from_cache(void *arg)
+{
+ /* We just need one of these to pass, it doesn't matter what's in it */
+ control_connection_t dummy;
+ /* Get results out */
+ char *answer = NULL;
+ const char *errmsg = NULL;
+
+ (void)arg;
+ or_options_t *options = get_options_mutable();
+ options->FetchUselessDescriptors = 1;
+ MOCK(dirserv_get_consensus, mock_dirserv_get_consensus);
+
+ getinfo_helper_dir(&dummy,
+ "dir/status-vote/current/consensus",
+ &answer,
+ &errmsg);
+ tt_str_op(answer, OP_EQ, "mock_ns_consensus");
+ tt_ptr_op(errmsg, OP_EQ, NULL);
+ tor_free(answer);
+ tor_free(mock_ns_consensus_cache->dir);
+ tor_free(mock_ns_consensus_cache);
+ errmsg = NULL;
+
+ getinfo_helper_dir(&dummy,
+ "dir/status-vote/current/consensus-microdesc",
+ &answer,
+ &errmsg);
+ tt_str_op(answer, OP_EQ, "mock_microdesc_consensus");
+ tt_ptr_op(errmsg, OP_EQ, NULL);
+ tor_free(mock_microdesc_consensus_cache->dir);
+ tor_free(answer);
+ errmsg = NULL;
+
+ done:
+ options->FetchUselessDescriptors = 0;
+ tor_free(answer);
+ tor_free(mock_microdesc_consensus_cache);
+ UNMOCK(dirserv_get_consensus);
+ return;
+}
+
/** Set timeval to a mock date and time. This is necessary
* to make tor_gettimeofday() mockable. */
static void
@@ -1840,6 +1973,10 @@ struct testcase_t controller_tests[] = {
NULL },
{ "download_status_consensus", test_download_status_consensus, 0, NULL,
NULL },
+ {"getinfo_helper_current_consensus_from_cache",
+ test_getinfo_helper_current_consensus_from_cache, 0, NULL, NULL },
+ {"getinfo_helper_current_consensus_from_file",
+ test_getinfo_helper_current_consensus_from_file, 0, NULL, NULL },
{ "download_status_cert", test_download_status_cert, 0, NULL,
NULL },
{ "download_status_desc", test_download_status_desc, 0, NULL, NULL },
diff --git a/src/test/test_key_expiration.sh b/src/test/test_key_expiration.sh
index 54abb4a2fa..9d42c1cc4c 100755
--- a/src/test/test_key_expiration.sh
+++ b/src/test/test_key_expiration.sh
@@ -28,6 +28,11 @@ else
TOR_BINARY="${TESTING_TOR_BINARY}"
fi
+if "$TOR_BINARY" --list-modules | grep -q "relay: no"; then
+ echo "This test requires the relay module. Skipping." >&2
+ exit 77
+fi
+
if [ $# -ge 1 ]; then
dflt=0
else
diff --git a/src/test/test_keygen.sh b/src/test/test_keygen.sh
index cbdfd1909c..57df888274 100755
--- a/src/test/test_keygen.sh
+++ b/src/test/test_keygen.sh
@@ -28,7 +28,10 @@ else
TOR_BINARY="${TESTING_TOR_BINARY}"
fi
-
+if "$TOR_BINARY" --list-modules | grep -q "relay: no"; then
+ echo "This test requires the relay module. Skipping." >&2
+ exit 77
+fi
if [ $# -ge 1 ]; then
dflt=0
diff --git a/src/test/test_parseconf.sh b/src/test/test_parseconf.sh
index eeb80cdfa7..d46be5e5cd 100755
--- a/src/test/test_parseconf.sh
+++ b/src/test/test_parseconf.sh
@@ -36,6 +36,27 @@
# matched by some line in the output of "--verify-config", which must
# fail. Exactly one of "expected" or "error" must be present, or the
# test will fail.
+#
+# {expected,error}_no_${TOR_MODULES_DISABLED} -- If this file is present,
+# then the outcome is different when some modules are disabled. If there
+# is no result file matching the exact list of disabled modules, the
+# standard result file is used.
+#
+# For example:
+# A test that succeeds, regardless of any disabled modules:
+# - expected
+# A test that has a different result if the relay module is disabled
+# (but the same result if just the dirauth module is disabled):
+# - expected
+# - expected_no_relay_dirauth
+# A test that fails if the dirauth module is disabled:
+# - expected
+# - error_no_dirauth
+# - error_no_relay_dirauth
+# (Disabling the relay module also disables dirauth module. But we don't
+# want to encode that knowledge in this test script, so we supply a
+# separate result file for every combination of disabled modules that
+# has a different result.)
umask 077
set -e
@@ -64,6 +85,11 @@ fi
TOR_BINARY="$(abspath "$TOR_BINARY")"
+TOR_MODULES_DISABLED="$("$TOR_BINARY" --list-modules | grep ": no" \
+ | cut -d ":" -f1 | sort | tr "\n" "_")"
+# Remove the last underscore, if there is one
+TOR_MODULES_DISABLED=${TOR_MODULES_DISABLED%_}
+
# make a safe space for temporary files
DATA_DIR=$(mktemp -d -t tor_parseconf_tests.XXXXXX)
trap 'rm -rf "$DATA_DIR"' 0
@@ -125,12 +151,30 @@ for dir in "${EXAMPLEDIR}"/*; do
CMDLINE=""
fi
- if test -f "./expected"; then
- if test -f "./error"; then
- echo "FAIL: Found both ${dir}/expected and ${dir}/error."
- echo "(Only one of these files should exist.)"
- exit $EXITCODE
+ # If tor has some modules disabled, search for a custom result file for
+ # the disabled modules
+ for suffix in "_no_$TOR_MODULES_DISABLED" ""; do
+
+ if test -f "./expected${suffix}"; then
+
+ # Check for broken configs
+ if test -f "./error${suffix}"; then
+ echo "FAIL: Found both ${dir}/expected${suffix}"
+ echo "and ${dir}/error${suffix}."
+ echo "(Only one of these files should exist.)"
+ exit $EXITCODE
+ fi
+
+ EXPECTED="./expected${suffix}"
+ break
+
+ elif test -f "./error${suffix}"; then
+ ERROR="./error${suffix}"
+ break
fi
+ done
+
+ if test -f "$EXPECTED"; then
# This case should succeed: run dump-config and see if it does.
@@ -141,7 +185,7 @@ for dir in "${EXAMPLEDIR}"/*; do
| "${FILTER}" > "${DATA_DIR}/output.${testname}" \
|| die "Failure: Tor exited."
- if cmp "./expected" "${DATA_DIR}/output.${testname}">/dev/null ; then
+ if cmp "$EXPECTED" "${DATA_DIR}/output.${testname}">/dev/null ; then
# Check round-trip.
"${TOR_BINARY}" -f "${DATA_DIR}/output.${testname}" \
--defaults-torrc "${DATA_DIR}/empty" \
@@ -166,11 +210,11 @@ for dir in "${EXAMPLEDIR}"/*; do
--verify-config \
${CMDLINE} || true
fi
- diff -u "./expected" "${DATA_DIR}/output.${testname}" || /bin/true
+ diff -u "$EXPECTED" "${DATA_DIR}/output.${testname}" || /bin/true
exit $EXITCODE
fi
- elif test -f "./error"; then
+ elif test -f "$ERROR"; then
# This case should fail: run verify-config and see if it does.
"${TOR_BINARY}" --verify-config \
@@ -180,7 +224,7 @@ for dir in "${EXAMPLEDIR}"/*; do
> "${DATA_DIR}/output.${testname}" \
&& die "Failure: Tor did not report an error."
- expect_err="$(cat ./error)"
+ expect_err="$(cat $ERROR)"
if grep "${expect_err}" "${DATA_DIR}/output.${testname}" >/dev/null; then
echo "OK"
else
@@ -195,7 +239,7 @@ for dir in "${EXAMPLEDIR}"/*; do
# This case is not actually configured with a success or a failure.
# call that an error.
- echo "FAIL: Did not find ${dir}/expected or ${dir}/error."
+ echo "FAIL: Did not find ${dir}/*expected or ${dir}/*error."
exit $EXITCODE
fi
diff --git a/src/test/test_process_slow.c b/src/test/test_process_slow.c
index 91252c725d..f311e8b293 100644
--- a/src/test/test_process_slow.c
+++ b/src/test/test_process_slow.c
@@ -328,8 +328,38 @@ test_callbacks_terminate(void *arg)
process_free(process);
}
+static void
+test_nonexistent_executable(void *arg)
+{
+ (void)arg;
+
+ /* Process callback data. */
+ process_data_t *process_data = process_data_new();
+
+ /* Setup our process. */
+ process_t *process = process_new("binary-does-not-exist");
+ process_set_data(process, process_data);
+ process_set_exit_callback(process, process_exit_callback);
+
+ /* Run our process. */
+ process_exec(process);
+
+ /* Start our main loop. */
+ run_main_loop(process_data);
+
+ /* Ensure that the exit callback was actually called even though the binary
+ * did not exist.
+ */
+ tt_assert(process_data->did_exit);
+
+ done:
+ process_data_free(process_data);
+ process_free(process);
+}
+
struct testcase_t slow_process_tests[] = {
{ "callbacks", test_callbacks, 0, NULL, NULL },
{ "callbacks_terminate", test_callbacks_terminate, 0, NULL, NULL },
+ { "nonexistent_executable", test_nonexistent_executable, 0, NULL, NULL },
END_OF_TESTCASES
};
diff --git a/src/test/test_rebind.py b/src/test/test_rebind.py
index 232b200326..c9b9200b2d 100644
--- a/src/test/test_rebind.py
+++ b/src/test/test_rebind.py
@@ -32,15 +32,17 @@ def wait_for_log(s):
cutoff = time.time() + LOG_TIMEOUT
while time.time() < cutoff:
l = tor_process.stdout.readline()
- l = l.decode('utf8')
+ l = l.decode('utf8', 'backslashreplace')
if s in l:
logging.info('Tor logged: "{}"'.format(l.strip()))
return
- logging.info('Tor logged: "{}", waiting for "{}"'.format(l.strip(), s))
# readline() returns a blank string when there is no output
# avoid busy-waiting
- if len(s) == 0:
+ if len(l) == 0:
+ logging.debug('Tor has not logged anything, waiting for "{}"'.format(s))
time.sleep(LOG_WAIT)
+ else:
+ logging.info('Tor logged: "{}", waiting for "{}"'.format(l.strip(), s))
fail('Could not find "{}" in logs after {} seconds'.format(s, LOG_TIMEOUT))
def pick_random_port():
@@ -120,18 +122,18 @@ if control_socket.connect_ex(('127.0.0.1', control_port)):
tor_process.terminate()
fail('Cannot connect to ControlPort')
-control_socket.sendall('AUTHENTICATE \r\n'.encode('utf8'))
-control_socket.sendall('SETCONF SOCKSPort=0.0.0.0:{}\r\n'.format(socks_port).encode('utf8'))
+control_socket.sendall('AUTHENTICATE \r\n'.encode('ascii'))
+control_socket.sendall('SETCONF SOCKSPort=0.0.0.0:{}\r\n'.format(socks_port).encode('ascii'))
wait_for_log('Opened Socks listener')
try_connecting_to_socksport()
-control_socket.sendall('SETCONF SOCKSPort=127.0.0.1:{}\r\n'.format(socks_port).encode('utf8'))
+control_socket.sendall('SETCONF SOCKSPort=127.0.0.1:{}\r\n'.format(socks_port).encode('ascii'))
wait_for_log('Opened Socks listener')
try_connecting_to_socksport()
-control_socket.sendall('SIGNAL HALT\r\n'.encode('utf8'))
+control_socket.sendall('SIGNAL HALT\r\n'.encode('ascii'))
wait_for_log('exiting cleanly')
logging.info('OK')
diff --git a/src/test/test_zero_length_keys.sh b/src/test/test_zero_length_keys.sh
index 84ca513b0a..eeabab352d 100755
--- a/src/test/test_zero_length_keys.sh
+++ b/src/test/test_zero_length_keys.sh
@@ -1,6 +1,11 @@
#!/bin/sh
# Check that tor regenerates keys when key files are zero-length
+if "${builddir:-.}/src/app/tor" --list-modules | grep -q "relay: no"; then
+ echo "This test requires the relay module. Skipping." >&2
+ exit 77
+fi
+
exitcode=0
"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "${builddir:-.}/src/app/tor" -z || exitcode=1