aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/app/config/config.c18
-rw-r--r--src/app/config/or_options_st.h2
-rw-r--r--src/app/main/main.c5
-rw-r--r--src/app/main/shutdown.c1
-rw-r--r--src/config/torrc.sample.in4
-rw-r--r--src/core/crypto/include.am2
-rw-r--r--src/core/crypto/onion_crypto.c50
-rw-r--r--src/core/crypto/onion_tap.c246
-rw-r--r--src/core/crypto/onion_tap.h40
-rw-r--r--src/core/or/circuitbuild.c70
-rw-r--r--src/core/or/circuitbuild.h1
-rw-r--r--src/core/or/circuitlist.c10
-rw-r--r--src/core/or/circuitlist.h1
-rw-r--r--src/core/or/circuituse.c2
-rw-r--r--src/core/or/command.c8
-rw-r--r--src/core/or/conflux_pool.c43
-rw-r--r--src/core/or/conflux_pool.h2
-rw-r--r--src/core/or/connection_edge.c110
-rw-r--r--src/core/or/connection_edge.h2
-rw-r--r--src/core/or/connection_or.c4
-rw-r--r--src/core/or/crypt_path_st.h1
-rw-r--r--src/core/or/dos.c127
-rw-r--r--src/core/or/dos.h34
-rw-r--r--src/core/or/dos_options.inc13
-rw-r--r--src/core/or/extend_info_st.h2
-rw-r--r--src/core/or/extendinfo.c22
-rw-r--r--src/core/or/extendinfo.h2
-rw-r--r--src/core/or/half_edge_st.h4
-rw-r--r--src/core/or/onion.c119
-rw-r--r--src/core/or/or_circuit_st.h4
-rw-r--r--src/core/or/policies.c2
-rw-r--r--src/core/or/protover.c6
-rw-r--r--src/core/or/relay.c3
-rw-r--r--src/core/or/scheduler_kist.c14
-rw-r--r--src/core/proto/proto_socks.c18
-rw-r--r--src/feature/client/bridges.c6
-rw-r--r--src/feature/client/entrynodes.c2
-rw-r--r--src/feature/dirauth/dirauth_config.c55
-rw-r--r--src/feature/dirauth/dirauth_options.inc3
-rw-r--r--src/feature/dirauth/dirvote.c109
-rw-r--r--src/feature/dirauth/dirvote.h32
-rw-r--r--src/feature/dirauth/process_descs.c14
-rw-r--r--src/feature/dirauth/voteflags.c17
-rw-r--r--src/feature/dirparse/microdesc_parse.c7
-rw-r--r--src/feature/dirparse/parsecommon.c13
-rw-r--r--src/feature/dirparse/parsecommon.h1
-rw-r--r--src/feature/dirparse/routerparse.c128
-rw-r--r--src/feature/hs/hs_common.c2
-rw-r--r--src/feature/hs/hs_service.c21
-rw-r--r--src/feature/hs/hs_service.h2
-rw-r--r--src/feature/nodelist/microdesc.c2
-rw-r--r--src/feature/nodelist/microdesc_st.h8
-rw-r--r--src/feature/nodelist/nodelist.c31
-rw-r--r--src/feature/nodelist/nodelist.h1
-rw-r--r--src/feature/nodelist/routerinfo_st.h9
-rw-r--r--src/feature/nodelist/routerlist.c25
-rw-r--r--src/feature/relay/circuitbuild_relay.c7
-rw-r--r--src/feature/relay/dns.c10
-rw-r--r--src/feature/relay/dns.h4
-rw-r--r--src/feature/relay/onion_queue.c90
-rw-r--r--src/feature/relay/relay_config.c4
-rw-r--r--src/feature/relay/relay_metrics.c71
-rw-r--r--src/feature/relay/relay_metrics.h6
-rw-r--r--src/feature/relay/router.c60
-rw-r--r--src/feature/relay/selftest.c6
-rw-r--r--src/feature/stats/rephist.c35
-rw-r--r--src/feature/stats/rephist.h6
-rw-r--r--src/lib/crypt_ops/crypto_openssl_mgt.c5
-rw-r--r--src/lib/crypt_ops/crypto_openssl_mgt.h5
-rw-r--r--src/lib/fs/files.c10
-rw-r--r--src/lib/log/.may_include2
-rw-r--r--src/lib/log/log.c6
-rw-r--r--src/lib/log/log_sys.c29
-rw-r--r--src/lib/log/util_bug.c27
-rw-r--r--src/lib/log/util_bug.h29
-rw-r--r--src/lib/sandbox/sandbox.c241
-rw-r--r--src/lib/string/util_string.c2
-rw-r--r--src/test/bench.c71
-rw-r--r--src/test/test.c207
-rw-r--r--src/test/test_cell_formats.c127
-rw-r--r--src/test/test_circuitpadding.c2
-rw-r--r--src/test/test_conflux_pool.c6
-rw-r--r--src/test/test_dir.c92
-rw-r--r--src/test/test_dirvote.c25
-rw-r--r--src/test/test_entrynodes.c2
-rw-r--r--src/test/test_hs_client.c8
-rw-r--r--src/test/test_hs_service.c2
-rw-r--r--src/test/test_microdesc.c70
-rw-r--r--src/test/test_protover.c4
-rw-r--r--src/test/test_router.c4
-rw-r--r--src/test/test_sandbox.c20
-rw-r--r--src/test/test_socks.c65
-rw-r--r--src/test/test_status.c13
-rw-r--r--src/tools/tor-resolve.c2
94 files changed, 1379 insertions, 1476 deletions
diff --git a/src/app/config/config.c b/src/app/config/config.c
index a10329c552..102d1bbc04 100644
--- a/src/app/config/config.c
+++ b/src/app/config/config.c
@@ -483,6 +483,13 @@ static const config_var_t option_vars_[] = {
#ifdef _WIN32
V(GeoIPFile, FILENAME, "<default>"),
V(GeoIPv6File, FILENAME, "<default>"),
+#elif defined(__ANDROID__)
+ /* Android apps use paths that are configured at runtime.
+ * /data/local/tmp is guaranteed to exist, but will only be
+ * usable by the 'shell' and 'root' users, so this fallback is
+ * for debugging only. */
+ V(GeoIPFile, FILENAME, "/data/local/tmp/geoip"),
+ V(GeoIPv6File, FILENAME, "/data/local/tmp/geoip6"),
#else
V(GeoIPFile, FILENAME,
SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "geoip"),
@@ -637,6 +644,7 @@ static const config_var_t option_vars_[] = {
V(RephistTrackTime, INTERVAL, "24 hours"),
V_IMMUTABLE(RunAsDaemon, BOOL, "0"),
V(ReducedExitPolicy, BOOL, "0"),
+ V(ReevaluateExitPolicy, BOOL, "0"),
OBSOLETE("RunTesting"), // currently unused
V_IMMUTABLE(Sandbox, BOOL, "0"),
V(SafeLogging, STRING, "1"),
@@ -996,6 +1004,7 @@ set_options(or_options_t *new_val, char **msg)
config_line_t *changes =
config_get_changes(get_options_mgr(), old_options, new_val);
control_event_conf_changed(changes);
+ connection_reapply_exit_policy(changes);
config_free_lines(changes);
}
@@ -6898,6 +6907,15 @@ get_data_directory(const char *val)
} else {
return tor_strdup(get_windows_conf_root());
}
+#elif defined(__ANDROID__)
+ /* Android apps can only use paths that are configured at runtime.
+ * /data/local/tmp is guaranteed to exist, but is only usable by the
+ * 'shell' and 'root' users, so this fallback is for debugging only. */
+ if (val) {
+ return tor_strdup(val);
+ } else {
+ return tor_strdup("/data/local/tmp");
+ }
#else /* !defined(_WIN32) */
const char *d = val;
if (!d)
diff --git a/src/app/config/or_options_st.h b/src/app/config/or_options_st.h
index 36b00662b5..624dc61bc5 100644
--- a/src/app/config/or_options_st.h
+++ b/src/app/config/or_options_st.h
@@ -141,6 +141,8 @@ struct or_options_t {
* Includes OutboundBindAddresses and
* configured ports. */
int ReducedExitPolicy; /**<Should we use the Reduced Exit Policy? */
+ int ReevaluateExitPolicy; /**<Should we re-evaluate Exit Policy on existing
+ * connections when it changes? */
struct config_line_t *SocksPolicy; /**< Lists of socks policy components */
struct config_line_t *DirPolicy; /**< Lists of dir policy components */
/** Local address to bind outbound sockets */
diff --git a/src/app/main/main.c b/src/app/main/main.c
index a50a0aad6f..6d05bd1f5e 100644
--- a/src/app/main/main.c
+++ b/src/app/main/main.c
@@ -926,6 +926,11 @@ sandbox_init_filter(void)
OPEN_DATADIR("approved-routers");
OPEN_DATADIR_SUFFIX("my-consensus-microdesc", ".tmp");
OPEN_DATADIR_SUFFIX("my-consensus-ns", ".tmp");
+ if (options->V3BandwidthsFile) {
+ log_notice(LD_GENERAL, "Adding V3BandwidthsFile %s to sandboxing set.",
+ options->V3BandwidthsFile);
+ OPEN(options->V3BandwidthsFile);
+ }
}
if (options->ServerDNSResolvConfFile)
diff --git a/src/app/main/shutdown.c b/src/app/main/shutdown.c
index 325cb27134..ddbc2ea584 100644
--- a/src/app/main/shutdown.c
+++ b/src/app/main/shutdown.c
@@ -122,6 +122,7 @@ tor_free_all(int postfork)
dirserv_free_all();
rep_hist_free_all();
bwhist_free_all();
+ conflux_notify_shutdown();
circuit_free_all();
conflux_pool_free_all();
circpad_machines_free();
diff --git a/src/config/torrc.sample.in b/src/config/torrc.sample.in
index 639d7c4d68..97ff941459 100644
--- a/src/config/torrc.sample.in
+++ b/src/config/torrc.sample.in
@@ -225,6 +225,10 @@
#ExitPolicy accept6 *6:119 # accept nntp ports on IPv6 only as well as default exit policy
#ExitPolicy reject *:* # no exits allowed
+## Uncomment this if you want your exit relay to reevaluate its exit policy on
+## existing connections when the exit policy is modified.
+#ReevaluateExitPolicy 1
+
## Bridge relays (or "bridges") are Tor relays that aren't listed in the
## main directory. Since there is no complete public list of them, even an
## ISP that filters connections to all the known Tor relays probably
diff --git a/src/core/crypto/include.am b/src/core/crypto/include.am
index 2d53b3cb0b..651e8803d4 100644
--- a/src/core/crypto/include.am
+++ b/src/core/crypto/include.am
@@ -6,7 +6,6 @@ LIBTOR_APP_A_SOURCES += \
src/core/crypto/onion_fast.c \
src/core/crypto/onion_ntor.c \
src/core/crypto/onion_ntor_v3.c \
- src/core/crypto/onion_tap.c \
src/core/crypto/relay_crypto.c
# ADD_C_FILE: INSERT HEADERS HERE.
@@ -16,5 +15,4 @@ noinst_HEADERS += \
src/core/crypto/onion_fast.h \
src/core/crypto/onion_ntor.h \
src/core/crypto/onion_ntor_v3.h \
- src/core/crypto/onion_tap.h \
src/core/crypto/relay_crypto.h
diff --git a/src/core/crypto/onion_crypto.c b/src/core/crypto/onion_crypto.c
index 0839d8903f..232dbcc5df 100644
--- a/src/core/crypto/onion_crypto.c
+++ b/src/core/crypto/onion_crypto.c
@@ -9,9 +9,9 @@
* \brief Functions to handle different kinds of circuit extension crypto.
*
* In this module, we provide a set of abstractions to create a uniform
- * interface over the three circuit extension handshakes that Tor has used
- * over the years (TAP, CREATE_FAST, and ntor). These handshakes are
- * implemented in onion_tap.c, onion_fast.c, and onion_ntor.c respectively.
+ * interface over the circuit extension handshakes that Tor has used
+ * over the years (CREATE_FAST, ntor, hs_ntor, and ntorv3).
+ * These handshakes are implemented in the onion_*.c modules.
*
* All[*] of these handshakes follow a similar pattern: a client, knowing
* some key from the relay it wants to extend through, generates the
@@ -36,7 +36,6 @@
#include "core/crypto/onion_fast.h"
#include "core/crypto/onion_ntor.h"
#include "core/crypto/onion_ntor_v3.h"
-#include "core/crypto/onion_tap.h"
#include "feature/relay/router.h"
#include "lib/crypt_ops/crypto_dh.h"
#include "lib/crypt_ops/crypto_util.h"
@@ -98,8 +97,6 @@ onion_handshake_state_release(onion_handshake_state_t *state)
{
switch (state->tag) {
case ONION_HANDSHAKE_TYPE_TAP:
- crypto_dh_free(state->u.tap);
- state->u.tap = NULL;
break;
case ONION_HANDSHAKE_TYPE_FAST:
fast_handshake_state_free(state->u.fast);
@@ -139,18 +136,7 @@ onion_skin_create(int type,
switch (type) {
case ONION_HANDSHAKE_TYPE_TAP:
- if (onion_skin_out_maxlen < TAP_ONIONSKIN_CHALLENGE_LEN)
- return -1;
- if (!node->onion_key)
- return -1;
-
- if (onion_skin_TAP_create(node->onion_key,
- &state_out->u.tap,
- (char*)onion_skin_out) < 0)
- return -1;
-
- r = TAP_ONIONSKIN_CHALLENGE_LEN;
- break;
+ return -1;
case ONION_HANDSHAKE_TYPE_FAST:
if (fast_onionskin_create(&state_out->u.fast, onion_skin_out) < 0)
return -1;
@@ -288,18 +274,7 @@ onion_skin_server_handshake(int type,
switch (type) {
case ONION_HANDSHAKE_TYPE_TAP:
- if (reply_out_maxlen < TAP_ONIONSKIN_REPLY_LEN)
- return -1;
- if (onionskin_len != TAP_ONIONSKIN_CHALLENGE_LEN)
- return -1;
- if (onion_skin_TAP_server_handshake((const char*)onion_skin,
- keys->onion_key, keys->last_onion_key,
- (char*)reply_out,
- (char*)keys_out, keys_out_len)<0)
- return -1;
- r = TAP_ONIONSKIN_REPLY_LEN;
- memcpy(rend_nonce_out, reply_out+DH1024_KEY_LEN, DIGEST_LEN);
- break;
+ return -1;
case ONION_HANDSHAKE_TYPE_FAST:
if (reply_out_maxlen < CREATED_FAST_LEN)
return -1;
@@ -474,20 +449,7 @@ onion_skin_client_handshake(int type,
switch (type) {
case ONION_HANDSHAKE_TYPE_TAP:
- if (reply_len != TAP_ONIONSKIN_REPLY_LEN) {
- if (msg_out)
- *msg_out = "TAP reply was not of the correct length.";
- return -1;
- }
- if (onion_skin_TAP_client_handshake(handshake_state->u.tap,
- (const char*)reply,
- (char *)keys_out, keys_out_len,
- msg_out) < 0)
- return -1;
-
- memcpy(rend_authenticator_out, reply+DH1024_KEY_LEN, DIGEST_LEN);
-
- return 0;
+ return -1;
case ONION_HANDSHAKE_TYPE_FAST:
if (reply_len != CREATED_FAST_LEN) {
if (msg_out)
diff --git a/src/core/crypto/onion_tap.c b/src/core/crypto/onion_tap.c
deleted file mode 100644
index 08ec3ec936..0000000000
--- a/src/core/crypto/onion_tap.c
+++ /dev/null
@@ -1,246 +0,0 @@
-/* Copyright (c) 2001 Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2021, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file onion_tap.c
- * \brief Functions to implement the original Tor circuit extension handshake
- * (a.k.a TAP).
- *
- * The "TAP" handshake is the first one that was widely used in Tor: It
- * combines RSA1024-OAEP and AES128-CTR to perform a hybrid encryption over
- * the first message DH1024 key exchange. (The RSA-encrypted part of the
- * encryption is authenticated; the AES-encrypted part isn't. This was
- * not a smart choice.)
- *
- * We didn't call it "TAP" ourselves -- Ian Goldberg named it in "On the
- * Security of the Tor Authentication Protocol". (Spoiler: it's secure, but
- * its security is kind of fragile and implementation dependent. Never modify
- * this implementation without reading and understanding that paper at least.)
- *
- * We have deprecated TAP since the ntor handshake came into general use. It
- * is still used for hidden service IP and RP connections, however.
- *
- * This handshake, like the other circuit-extension handshakes, is
- * invoked from onion.c.
- **/
-
-#include "core/or/or.h"
-#include "app/config/config.h"
-#include "lib/crypt_ops/crypto_dh.h"
-#include "lib/crypt_ops/crypto_rand.h"
-#include "lib/crypt_ops/crypto_util.h"
-#include "core/crypto/onion_tap.h"
-#include "feature/stats/rephist.h"
-
-/*----------------------------------------------------------------------*/
-
-/** Given a router's 128 byte public key,
- * stores the following in onion_skin_out:
- * - [42 bytes] OAEP padding
- * - [16 bytes] Symmetric key for encrypting blob past RSA
- * - [70 bytes] g^x part 1 (inside the RSA)
- * - [58 bytes] g^x part 2 (symmetrically encrypted)
- *
- * Stores the DH private key into handshake_state_out for later completion
- * of the handshake.
- *
- * The meeting point/cookies and auth are zeroed out for now.
- */
-int
-onion_skin_TAP_create(crypto_pk_t *dest_router_key,
- crypto_dh_t **handshake_state_out,
- char *onion_skin_out) /* TAP_ONIONSKIN_CHALLENGE_LEN bytes */
-{
- char challenge[DH1024_KEY_LEN];
- crypto_dh_t *dh = NULL;
- int dhbytes, pkbytes;
-
- tor_assert(dest_router_key);
- tor_assert(handshake_state_out);
- tor_assert(onion_skin_out);
- *handshake_state_out = NULL;
- memset(onion_skin_out, 0, TAP_ONIONSKIN_CHALLENGE_LEN);
-
- if (!(dh = crypto_dh_new(DH_TYPE_CIRCUIT)))
- goto err;
-
- dhbytes = crypto_dh_get_bytes(dh);
- pkbytes = (int) crypto_pk_keysize(dest_router_key);
- tor_assert(dhbytes == 128);
- tor_assert(pkbytes == 128);
-
- if (crypto_dh_get_public(dh, challenge, dhbytes))
- goto err;
-
- /* set meeting point, meeting cookie, etc here. Leave zero for now. */
- if (crypto_pk_obsolete_public_hybrid_encrypt(dest_router_key, onion_skin_out,
- TAP_ONIONSKIN_CHALLENGE_LEN,
- challenge, DH1024_KEY_LEN,
- PK_PKCS1_OAEP_PADDING, 1)<0)
- goto err;
-
- memwipe(challenge, 0, sizeof(challenge));
- *handshake_state_out = dh;
-
- return 0;
- err:
- /* LCOV_EXCL_START
- * We only get here if RSA encryption fails or DH keygen fails. Those
- * shouldn't be possible. */
- memwipe(challenge, 0, sizeof(challenge));
- if (dh) crypto_dh_free(dh);
- return -1;
- /* LCOV_EXCL_STOP */
-}
-
-/** Given an encrypted DH public key as generated by onion_skin_create,
- * and the private key for this onion router, generate the reply (128-byte
- * DH plus the first 20 bytes of shared key material), and store the
- * next key_out_len bytes of key material in key_out.
- */
-int
-onion_skin_TAP_server_handshake(
- /*TAP_ONIONSKIN_CHALLENGE_LEN*/
- const char *onion_skin,
- crypto_pk_t *private_key,
- crypto_pk_t *prev_private_key,
- /*TAP_ONIONSKIN_REPLY_LEN*/
- char *handshake_reply_out,
- char *key_out,
- size_t key_out_len)
-{
- char challenge[TAP_ONIONSKIN_CHALLENGE_LEN];
- crypto_dh_t *dh = NULL;
- ssize_t len;
- char *key_material=NULL;
- size_t key_material_len=0;
- int i;
- crypto_pk_t *k;
-
- len = -1;
- for (i=0;i<2;++i) {
- k = i==0?private_key:prev_private_key;
- if (!k)
- break;
- len = crypto_pk_obsolete_private_hybrid_decrypt(k, challenge,
- TAP_ONIONSKIN_CHALLENGE_LEN,
- onion_skin,
- TAP_ONIONSKIN_CHALLENGE_LEN,
- PK_PKCS1_OAEP_PADDING,0);
- if (len>0)
- break;
- }
- if (len<0) {
- log_info(LD_PROTOCOL,
- "Couldn't decrypt onionskin: client may be using old onion key");
- goto err;
- } else if (len != DH1024_KEY_LEN) {
- log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
- "Unexpected onionskin length after decryption: %ld",
- (long)len);
- goto err;
- }
-
- dh = crypto_dh_new(DH_TYPE_CIRCUIT);
- if (!dh) {
- /* LCOV_EXCL_START
- * Failure to allocate a DH key should be impossible.
- */
- log_warn(LD_BUG, "Couldn't allocate DH key");
- goto err;
- /* LCOV_EXCL_STOP */
- }
- if (crypto_dh_get_public(dh, handshake_reply_out, DH1024_KEY_LEN)) {
- /* LCOV_EXCL_START
- * This can only fail if the length of the key we just allocated is too
- * big. That should be impossible. */
- log_info(LD_GENERAL, "crypto_dh_get_public failed.");
- goto err;
- /* LCOV_EXCL_STOP */
- }
-
- key_material_len = DIGEST_LEN+key_out_len;
- key_material = tor_malloc(key_material_len);
- len = crypto_dh_compute_secret(LOG_PROTOCOL_WARN, dh, challenge,
- DH1024_KEY_LEN, key_material,
- key_material_len);
- if (len < 0) {
- log_info(LD_GENERAL, "crypto_dh_compute_secret failed.");
- goto err;
- }
-
- /* send back H(K|0) as proof that we learned K. */
- memcpy(handshake_reply_out+DH1024_KEY_LEN, key_material, DIGEST_LEN);
-
- /* use the rest of the key material for our shared keys, digests, etc */
- memcpy(key_out, key_material+DIGEST_LEN, key_out_len);
-
- memwipe(challenge, 0, sizeof(challenge));
- memwipe(key_material, 0, key_material_len);
- tor_free(key_material);
- crypto_dh_free(dh);
- return 0;
- err:
- memwipe(challenge, 0, sizeof(challenge));
- if (key_material) {
- memwipe(key_material, 0, key_material_len);
- tor_free(key_material);
- }
- if (dh) crypto_dh_free(dh);
-
- return -1;
-}
-
-/** Finish the client side of the DH handshake.
- * Given the 128 byte DH reply + 20 byte hash as generated by
- * onion_skin_server_handshake and the handshake state generated by
- * onion_skin_create, verify H(K) with the first 20 bytes of shared
- * key material, then generate key_out_len more bytes of shared key
- * material and store them in key_out.
- *
- * After the invocation, call crypto_dh_free on handshake_state.
- */
-int
-onion_skin_TAP_client_handshake(crypto_dh_t *handshake_state,
- const char *handshake_reply, /* TAP_ONIONSKIN_REPLY_LEN bytes */
- char *key_out,
- size_t key_out_len,
- const char **msg_out)
-{
- ssize_t len;
- char *key_material=NULL;
- size_t key_material_len;
- tor_assert(crypto_dh_get_bytes(handshake_state) == DH1024_KEY_LEN);
-
- key_material_len = DIGEST_LEN + key_out_len;
- key_material = tor_malloc(key_material_len);
- len = crypto_dh_compute_secret(LOG_PROTOCOL_WARN, handshake_state,
- handshake_reply, DH1024_KEY_LEN, key_material,
- key_material_len);
- if (len < 0) {
- if (msg_out)
- *msg_out = "DH computation failed.";
- goto err;
- }
-
- if (tor_memneq(key_material, handshake_reply+DH1024_KEY_LEN, DIGEST_LEN)) {
- /* H(K) does *not* match. Something fishy. */
- if (msg_out)
- *msg_out = "Digest DOES NOT MATCH on onion handshake. Bug or attack.";
- goto err;
- }
-
- /* use the rest of the key material for our shared keys, digests, etc */
- memcpy(key_out, key_material+DIGEST_LEN, key_out_len);
-
- memwipe(key_material, 0, key_material_len);
- tor_free(key_material);
- return 0;
- err:
- memwipe(key_material, 0, key_material_len);
- tor_free(key_material);
- return -1;
-}
diff --git a/src/core/crypto/onion_tap.h b/src/core/crypto/onion_tap.h
deleted file mode 100644
index 341270c981..0000000000
--- a/src/core/crypto/onion_tap.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* Copyright (c) 2001 Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2021, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file onion_tap.h
- * \brief Header file for onion_tap.c.
- **/
-
-#ifndef TOR_ONION_TAP_H
-#define TOR_ONION_TAP_H
-
-#define TAP_ONIONSKIN_CHALLENGE_LEN (PKCS1_OAEP_PADDING_OVERHEAD+\
- CIPHER_KEY_LEN+\
- DH1024_KEY_LEN)
-#define TAP_ONIONSKIN_REPLY_LEN (DH1024_KEY_LEN+DIGEST_LEN)
-
-struct crypto_dh_t;
-struct crypto_pk_t;
-
-int onion_skin_TAP_create(struct crypto_pk_t *router_key,
- struct crypto_dh_t **handshake_state_out,
- char *onion_skin_out);
-
-int onion_skin_TAP_server_handshake(const char *onion_skin,
- struct crypto_pk_t *private_key,
- struct crypto_pk_t *prev_private_key,
- char *handshake_reply_out,
- char *key_out,
- size_t key_out_len);
-
-int onion_skin_TAP_client_handshake(struct crypto_dh_t *handshake_state,
- const char *handshake_reply,
- char *key_out,
- size_t key_out_len,
- const char **msg_out);
-
-#endif /* !defined(TOR_ONION_TAP_H) */
diff --git a/src/core/or/circuitbuild.c b/src/core/or/circuitbuild.c
index dc1912294b..bcf44ca248 100644
--- a/src/core/or/circuitbuild.c
+++ b/src/core/or/circuitbuild.c
@@ -33,7 +33,6 @@
#include "core/crypto/hs_ntor.h"
#include "core/crypto/onion_crypto.h"
#include "core/crypto/onion_fast.h"
-#include "core/crypto/onion_tap.h"
#include "core/mainloop/connection.h"
#include "core/mainloop/mainloop.h"
#include "core/or/channel.h"
@@ -412,13 +411,6 @@ onion_populate_cpath(origin_circuit_t *circ)
/* We would like every path to support ntor, but we have to allow for some
* edge cases. */
tor_assert(circuit_get_cpath_len(circ));
- if (circuit_can_use_tap(circ)) {
- /* Circuits from clients to intro points, and hidden services to rend
- * points do not support ntor, because the hidden service protocol does
- * not include ntor onion keys. This is also true for Single Onion
- * Services. */
- return 0;
- }
if (circuit_get_cpath_len(circ) == 1) {
/* Allow for bootstrapping: when we're fetching directly from a fallback,
@@ -890,20 +882,14 @@ circuit_pick_create_handshake(uint8_t *cell_type_out,
{
/* torspec says: In general, clients SHOULD use CREATE whenever they are
* using the TAP handshake, and CREATE2 otherwise. */
- if (extend_info_supports_ntor(ei)) {
- *cell_type_out = CELL_CREATE2;
- /* Only use ntor v3 with exits that support congestion control,
- * and only when it is enabled. */
- if (ei->exit_supports_congestion_control &&
- congestion_control_enabled())
- *handshake_type_out = ONION_HANDSHAKE_TYPE_NTOR_V3;
- else
- *handshake_type_out = ONION_HANDSHAKE_TYPE_NTOR;
- } else {
- /* XXXX030 Remove support for deciding to use TAP and EXTEND. */
- *cell_type_out = CELL_CREATE;
- *handshake_type_out = ONION_HANDSHAKE_TYPE_TAP;
- }
+ *cell_type_out = CELL_CREATE2;
+ /* Only use ntor v3 with exits that support congestion control,
+ * and only when it is enabled. */
+ if (ei->exit_supports_congestion_control &&
+ congestion_control_enabled())
+ *handshake_type_out = ONION_HANDSHAKE_TYPE_NTOR_V3;
+ else
+ *handshake_type_out = ONION_HANDSHAKE_TYPE_NTOR;
}
/** Decide whether to use a TAP or ntor handshake for extending to <b>ei</b>
@@ -924,16 +910,8 @@ circuit_pick_extend_handshake(uint8_t *cell_type_out,
uint8_t t;
circuit_pick_create_handshake(&t, handshake_type_out, ei);
- /* torspec says: Clients SHOULD use the EXTEND format whenever sending a TAP
- * handshake... In other cases, clients SHOULD use EXTEND2. */
- if (*handshake_type_out != ONION_HANDSHAKE_TYPE_TAP) {
- *cell_type_out = RELAY_COMMAND_EXTEND2;
- *create_cell_type_out = CELL_CREATE2;
- } else {
- /* XXXX030 Remove support for deciding to use TAP and EXTEND. */
- *cell_type_out = RELAY_COMMAND_EXTEND;
- *create_cell_type_out = CELL_CREATE;
- }
+ *cell_type_out = RELAY_COMMAND_EXTEND2;
+ *create_cell_type_out = CELL_CREATE2;
}
/**
@@ -1343,7 +1321,7 @@ circuit_finish_handshake(origin_circuit_t *circ,
hop->ccontrol = congestion_control_new(&params, CC_PATH_EXIT);
} else {
/* This is likely directory requests, which should block on orconn
- * before congestion control, but lets give them the lower sbws
+ * before congestion control, but let's give them the lower sbws
* param set anyway just in case. */
log_info(LD_CIRC,
"Unexpected path length %d for exit circuit %d, purpose %d",
@@ -2641,29 +2619,6 @@ build_state_get_exit_nickname(cpath_build_state_t *state)
return state->chosen_exit->nickname;
}
-/* Is circuit purpose allowed to use the deprecated TAP encryption protocol?
- * The hidden service protocol still uses TAP for some connections, because
- * ntor onion keys aren't included in HS descriptors or INTRODUCE cells. */
-static int
-circuit_purpose_can_use_tap_impl(uint8_t purpose)
-{
- return (purpose == CIRCUIT_PURPOSE_S_CONNECT_REND ||
- purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
-}
-
-/* Is circ allowed to use the deprecated TAP encryption protocol?
- * The hidden service protocol still uses TAP for some connections, because
- * ntor onion keys aren't included in HS descriptors or INTRODUCE cells. */
-int
-circuit_can_use_tap(const origin_circuit_t *circ)
-{
- tor_assert(circ);
- tor_assert(circ->cpath);
- tor_assert(circ->cpath->extend_info);
- return (circuit_purpose_can_use_tap_impl(circ->base_.purpose) &&
- extend_info_supports_tap(circ->cpath->extend_info));
-}
-
/* Does circ have an onion key which it's allowed to use? */
int
circuit_has_usable_onion_key(const origin_circuit_t *circ)
@@ -2671,8 +2626,7 @@ circuit_has_usable_onion_key(const origin_circuit_t *circ)
tor_assert(circ);
tor_assert(circ->cpath);
tor_assert(circ->cpath->extend_info);
- return (extend_info_supports_ntor(circ->cpath->extend_info) ||
- circuit_can_use_tap(circ));
+ return extend_info_supports_ntor(circ->cpath->extend_info);
}
/** Find the circuits that are waiting to find out whether their guards are
diff --git a/src/core/or/circuitbuild.h b/src/core/or/circuitbuild.h
index c76259fc29..ac3bf52135 100644
--- a/src/core/or/circuitbuild.h
+++ b/src/core/or/circuitbuild.h
@@ -48,7 +48,6 @@ MOCK_DECL(int, circuit_all_predicted_ports_handled, (time_t now,
int circuit_append_new_exit(origin_circuit_t *circ, extend_info_t *info);
int circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *info);
-int circuit_can_use_tap(const origin_circuit_t *circ);
int circuit_has_usable_onion_key(const origin_circuit_t *circ);
const uint8_t *build_state_get_exit_rsa_id(cpath_build_state_t *state);
MOCK_DECL(const node_t *,
diff --git a/src/core/or/circuitlist.c b/src/core/or/circuitlist.c
index b90c7ebb58..8f8ed915fb 100644
--- a/src/core/or/circuitlist.c
+++ b/src/core/or/circuitlist.c
@@ -65,6 +65,7 @@
#include "core/or/conflux.h"
#include "core/or/conflux_pool.h"
#include "core/or/crypt_path.h"
+#include "core/or/dos.h"
#include "core/or/extendinfo.h"
#include "core/or/status.h"
#include "core/or/trace_probes_circuit.h"
@@ -159,6 +160,10 @@ double cc_stats_circ_close_ss_cwnd_ma = 0;
uint64_t cc_stats_circs_closed = 0;
+/** Total number of circuit protocol violation. This is incremented when the
+ * END_CIRC_REASON_TORPROTOCOL is used to close a circuit. */
+uint64_t circ_n_proto_violation = 0;
+
/********* END VARIABLES ************/
/* Implement circuit handle helpers. */
@@ -1130,6 +1135,7 @@ or_circuit_new(circid_t p_circ_id, channel_t *p_chan)
cell_queue_init(&circ->p_chan_cells);
init_circuit_base(TO_CIRCUIT(circ));
+ dos_stream_init_circ_tbf(circ);
tor_trace(TR_SUBSYS(circuit), TR_EV(new_or), circ);
return circ;
@@ -2195,6 +2201,10 @@ circuit_mark_for_close_, (circuit_t *circ, int reason, int line,
tor_assert(line);
tor_assert(file);
+ if (reason == END_CIRC_REASON_TORPROTOCOL) {
+ circ_n_proto_violation++;
+ }
+
/* Check whether the circuitpadding subsystem wants to block this close */
if (circpad_marked_circuit_for_padding(circ, reason)) {
return;
diff --git a/src/core/or/circuitlist.h b/src/core/or/circuitlist.h
index ca3c5bd0ee..0c8f958d2a 100644
--- a/src/core/or/circuitlist.h
+++ b/src/core/or/circuitlist.h
@@ -172,6 +172,7 @@
extern double cc_stats_circ_close_cwnd_ma;
extern double cc_stats_circ_close_ss_cwnd_ma;
extern uint64_t cc_stats_circs_closed;
+extern uint64_t circ_n_proto_violation;
/** Convert a circuit_t* to a pointer to the enclosing or_circuit_t. Assert
* if the cast is impossible. */
diff --git a/src/core/or/circuituse.c b/src/core/or/circuituse.c
index abfb51c662..6a73fbe87c 100644
--- a/src/core/or/circuituse.c
+++ b/src/core/or/circuituse.c
@@ -2478,7 +2478,7 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn,
extend_info = extend_info_new(conn->chosen_exit_name+1,
digest,
NULL, /* Ed25519 ID */
- NULL, NULL, /* onion keys */
+ NULL, /* onion keys */
&addr, conn->socks_request->port,
NULL,
false);
diff --git a/src/core/or/command.c b/src/core/or/command.c
index cad7a173b6..c35400d7a1 100644
--- a/src/core/or/command.c
+++ b/src/core/or/command.c
@@ -331,6 +331,14 @@ command_process_create_cell(cell_t *cell, channel_t *chan)
return;
}
+ /* We no longer accept TAP, for any reason. */
+ if (create_cell->handshake_type == ONION_HANDSHAKE_TYPE_TAP) {
+ tor_free(create_cell);
+ /* TODO: Should we collect statistics here? Should we log? */
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL);
+ return;
+ }
+
/* Mark whether this circuit used TAP in case we need to use this
* information for onion service statistics later on. */
if (create_cell->handshake_type == ONION_HANDSHAKE_TYPE_FAST ||
diff --git a/src/core/or/conflux_pool.c b/src/core/or/conflux_pool.c
index 74781b307a..82043d607f 100644
--- a/src/core/or/conflux_pool.c
+++ b/src/core/or/conflux_pool.c
@@ -1624,7 +1624,22 @@ linked_circuit_free(circuit_t *circ, bool is_client)
/* Circuit can be freed without being closed and so we try to delete this leg
* so we can learn if this circuit is the last leg or not. */
- cfx_del_leg(circ->conflux, circ);
+ if (cfx_del_leg(circ->conflux, circ)) {
+ /* Check for instances of bug #40870, which we suspect happen
+ * during exit. If any happen outside of exit, BUG and warn. */
+ if (!circ->conflux->in_full_teardown) {
+ /* We should bug and warn if we're not in a shutdown process; that
+ * means we got here somehow without a close. */
+ if (BUG(!shutting_down)) {
+ log_warn(LD_BUG,
+ "Conflux circuit %p being freed without being marked for "
+ "full teardown via close, with shutdown state %d. "
+ "Please report this.", circ, shutting_down);
+ conflux_log_set(LOG_WARN, circ->conflux, is_client);
+ }
+ circ->conflux->in_full_teardown = true;
+ }
+ }
if (CONFLUX_NUM_LEGS(circ->conflux) > 0) {
/* The last leg will free the streams but until then, we nullify to avoid
@@ -2146,14 +2161,36 @@ conflux_log_set(int loglevel, const conflux_t *cfx, bool is_client)
}
}
+/**
+ * Conflux needs a notification when tor_shutdown() begins, so that
+ * when circuits are freed, new legs are not launched.
+ *
+ * This needs a separate notification from conflux_pool_free_all(),
+ * because circuits must be freed before that function.
+ */
+void
+conflux_notify_shutdown(void)
+{
+ shutting_down = true;
+}
+
+#ifdef TOR_UNIT_TESTS
+/**
+ * For unit tests: Clear the shutting down state so we resume building legs.
+ */
+void
+conflux_clear_shutdown(void)
+{
+ shutting_down = false;
+}
+#endif
+
/** Free and clean up the conflux pool subsystem. This is called by the subsys
* manager AFTER all circuits have been freed which implies that all objects in
* the pools aren't referenced anymore. */
void
conflux_pool_free_all(void)
{
- shutting_down = true;
-
digest256map_free(client_linked_pool, free_conflux_void_);
digest256map_free(server_linked_pool, free_conflux_void_);
digest256map_free(client_unlinked_pool, free_unlinked_void_);
diff --git a/src/core/or/conflux_pool.h b/src/core/or/conflux_pool.h
index afa4d9d058..eba726b03a 100644
--- a/src/core/or/conflux_pool.h
+++ b/src/core/or/conflux_pool.h
@@ -12,6 +12,7 @@
#include "core/or/or.h"
void conflux_pool_init(void);
+void conflux_notify_shutdown(void);
void conflux_pool_free_all(void);
origin_circuit_t *conflux_get_circ_for_conn(const entry_connection_t *conn,
@@ -41,6 +42,7 @@ void conflux_log_set(int loglevel, const conflux_t *cfx, bool is_client);
#ifdef TOR_UNIT_TESTS
bool launch_new_set(int num_legs);
+void conflux_clear_shutdown(void);
digest256map_t *get_linked_pool(bool is_client);
digest256map_t *get_unlinked_pool(bool is_client);
extern uint8_t DEFAULT_CLIENT_UX;
diff --git a/src/core/or/connection_edge.c b/src/core/or/connection_edge.c
index f21779a80c..b36d0d9013 100644
--- a/src/core/or/connection_edge.c
+++ b/src/core/or/connection_edge.c
@@ -73,6 +73,7 @@
#include "core/or/conflux_util.h"
#include "core/or/circuitstats.h"
#include "core/or/connection_or.h"
+#include "core/or/dos.h"
#include "core/or/extendinfo.h"
#include "core/or/policies.h"
#include "core/or/reasons.h"
@@ -105,6 +106,7 @@
#include "lib/buf/buffers.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/crypt_ops/crypto_util.h"
+#include "lib/encoding/confline.h"
#include "core/or/cell_st.h"
#include "core/or/cpath_build_state_st.h"
@@ -3989,6 +3991,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
begin_cell_t bcell;
int rv;
uint8_t end_reason=0;
+ dos_stream_defense_type_t dos_defense_type;
assert_circuit_ok(circ);
if (!CIRCUIT_IS_ORIGIN(circ)) {
@@ -4147,6 +4150,24 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
log_debug(LD_EXIT,"about to start the dns_resolve().");
+ // in the future we may want to have a similar defense for BEGIN_DIR and
+ // BEGIN sent to OS.
+ dos_defense_type = dos_stream_new_begin_or_resolve_cell(or_circ);
+ switch (dos_defense_type) {
+ case DOS_STREAM_DEFENSE_NONE:
+ break;
+ case DOS_STREAM_DEFENSE_REFUSE_STREAM:
+ // we don't use END_STREAM_REASON_RESOURCELIMIT because it would make a
+ // client mark us as non-functional until they get a new consensus.
+ relay_send_end_cell_from_edge(rh.stream_id, circ, END_STREAM_REASON_MISC,
+ layer_hint);
+ connection_free_(TO_CONN(n_stream));
+ return 0;
+ case DOS_STREAM_DEFENSE_CLOSE_CIRCUIT:
+ connection_free_(TO_CONN(n_stream));
+ return -END_CIRC_REASON_RESOURCELIMIT;
+ }
+
/* send it off to the gethostbyname farm */
switch (dns_resolve(n_stream)) {
case 1: /* resolve worked; now n_stream is attached to circ. */
@@ -4170,17 +4191,21 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
* Called when we receive a RELAY_COMMAND_RESOLVE cell 'cell' along the
* circuit <b>circ</b>;
* begin resolving the hostname, and (eventually) reply with a RESOLVED cell.
+ *
+ * Return -(some circuit end reason) if we want to tear down <b>circ</b>.
+ * Else return 0.
*/
int
connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ)
{
edge_connection_t *dummy_conn;
relay_header_t rh;
+ dos_stream_defense_type_t dos_defense_type;
assert_circuit_ok(TO_CIRCUIT(circ));
relay_header_unpack(&rh, cell->payload);
if (rh.length > RELAY_PAYLOAD_SIZE)
- return -1;
+ return 0;
/* Note the RESOLVE stream as seen. */
rep_hist_note_exit_stream(RELAY_COMMAND_RESOLVE);
@@ -4203,6 +4228,19 @@ connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ)
dummy_conn->on_circuit = TO_CIRCUIT(circ);
+ dos_defense_type = dos_stream_new_begin_or_resolve_cell(circ);
+ switch (dos_defense_type) {
+ case DOS_STREAM_DEFENSE_NONE:
+ break;
+ case DOS_STREAM_DEFENSE_REFUSE_STREAM:
+ dns_send_resolved_error_cell(dummy_conn, RESOLVED_TYPE_ERROR_TRANSIENT);
+ connection_free_(TO_CONN(dummy_conn));
+ return 0;
+ case DOS_STREAM_DEFENSE_CLOSE_CIRCUIT:
+ connection_free_(TO_CONN(dummy_conn));
+ return -END_CIRC_REASON_RESOURCELIMIT;
+ }
+
/* send it off to the gethostbyname farm */
switch (dns_resolve(dummy_conn)) {
case -1: /* Impossible to resolve; a resolved cell was sent. */
@@ -4237,6 +4275,76 @@ my_exit_policy_rejects(const tor_addr_t *addr,
return 0;
}
+/* Reapply exit policy to existing connections, possibly terminating
+ * connections
+ * no longer allowed by the policy.
+ */
+void
+connection_reapply_exit_policy(config_line_t *changes)
+{
+ int marked_for_close = 0;
+ smartlist_t *conn_list = NULL;
+ smartlist_t *policy = NULL;
+ int config_change_relevant = 0;
+
+ if (get_options()->ReevaluateExitPolicy == 0) {
+ return;
+ }
+
+ for (const config_line_t *line = changes;
+ line && !config_change_relevant;
+ line = line->next) {
+ const char* exit_policy_options[] = {
+ "ExitRelay",
+ "ExitPolicy",
+ "ReducedExitPolicy",
+ "ReevaluateExitPolicy",
+ "IPv6Exit",
+ NULL
+ };
+ for (unsigned int i = 0; exit_policy_options[i] != NULL; ++i) {
+ if (strcmp(line->key, exit_policy_options[i]) == 0) {
+ config_change_relevant = 1;
+ break;
+ }
+ }
+ }
+
+ if (!config_change_relevant) {
+ /* Policy did not change: no need to iterate over connections */
+ return;
+ }
+
+ // we can't use router_compare_to_my_exit_policy as it depend on the
+ // descriptor, which is regenerated asynchronously, so we have to parse the
+ // policy ourselves.
+ // We don't verify for our own IP, it's not part of the configuration.
+ if (BUG(policies_parse_exit_policy_from_options(get_options(), NULL, NULL,
+ &policy) != 0)) {
+ return;
+ }
+
+ conn_list = connection_list_by_type_purpose(CONN_TYPE_EXIT,
+ EXIT_PURPOSE_CONNECT);
+
+ SMARTLIST_FOREACH_BEGIN(conn_list, connection_t *, conn) {
+ addr_policy_result_t verdict = compare_tor_addr_to_addr_policy(&conn->addr,
+ conn->port,
+ policy);
+ if (verdict != ADDR_POLICY_ACCEPTED) {
+ connection_edge_end(TO_EDGE_CONN(conn), END_STREAM_REASON_EXITPOLICY);
+ connection_mark_for_close(conn);
+ ++marked_for_close;
+ }
+ } SMARTLIST_FOREACH_END(conn);
+
+ smartlist_free(conn_list);
+ smartlist_free(policy);
+
+ log_info(LD_GENERAL, "Marked %d connections to be closed as no longer "
+ "allowed per ExitPolicy", marked_for_close);
+}
+
/** Return true iff the consensus allows network reentry. The default value is
* false if the parameter is not found. */
static bool
diff --git a/src/core/or/connection_edge.h b/src/core/or/connection_edge.h
index 59fc17dea5..1bb0e6d368 100644
--- a/src/core/or/connection_edge.h
+++ b/src/core/or/connection_edge.h
@@ -13,6 +13,7 @@
#define TOR_CONNECTION_EDGE_H
#include "lib/testsupport/testsupport.h"
+#include "lib/encoding/confline.h"
#include "feature/hs/hs_service.h"
@@ -101,6 +102,7 @@ void connection_entry_set_controller_wait(entry_connection_t *conn);
void connection_ap_about_to_close(entry_connection_t *edge_conn);
void connection_exit_about_to_close(edge_connection_t *edge_conn);
+void connection_reapply_exit_policy(config_line_t *changes);
MOCK_DECL(int,
connection_ap_handshake_send_begin,(entry_connection_t *ap_conn));
diff --git a/src/core/or/connection_or.c b/src/core/or/connection_or.c
index 343c1a67ed..30ce5e0c57 100644
--- a/src/core/or/connection_or.c
+++ b/src/core/or/connection_or.c
@@ -104,7 +104,7 @@ static void connection_or_check_canonicity(or_connection_t *conn,
/**
* Cast a `connection_t *` to an `or_connection_t *`.
*
- * Exit with an assertion failure if the input is not an `or_connnection_t`.
+ * Exit with an assertion failure if the input is not an `or_connection_t`.
**/
or_connection_t *
TO_OR_CONN(connection_t *c)
@@ -116,7 +116,7 @@ TO_OR_CONN(connection_t *c)
/**
* Cast a `const connection_t *` to a `const or_connection_t *`.
*
- * Exit with an assertion failure if the input is not an `or_connnection_t`.
+ * Exit with an assertion failure if the input is not an `or_connection_t`.
**/
const or_connection_t *
CONST_TO_OR_CONN(const connection_t *c)
diff --git a/src/core/or/crypt_path_st.h b/src/core/or/crypt_path_st.h
index fdc6b6fbb2..fc6391f2f8 100644
--- a/src/core/or/crypt_path_st.h
+++ b/src/core/or/crypt_path_st.h
@@ -26,7 +26,6 @@ struct onion_handshake_state_t {
uint16_t tag;
union {
struct fast_handshake_state_t *fast;
- struct crypto_dh_t *tap;
struct ntor_handshake_state_t *ntor;
struct ntor3_handshake_state_t *ntor3;
} u;
diff --git a/src/core/or/dos.c b/src/core/or/dos.c
index ccdb30dbee..b789f87aae 100644
--- a/src/core/or/dos.c
+++ b/src/core/or/dos.c
@@ -79,6 +79,24 @@ static uint64_t conn_num_addr_connect_rejected;
static uint32_t dos_num_circ_max_outq;
/*
+ * Stream denial of service mitigation.
+ *
+ * Namespace used for this mitigation framework is "dos_stream_".
+ */
+
+/* Is the connection DoS mitigation enabled? */
+static unsigned int dos_stream_enabled = 0;
+
+/* Consensus parameters. They can be changed when a new consensus arrives.
+ * They are initialized with the hardcoded default values. */
+static dos_stream_defense_type_t dos_stream_defense_type;
+static uint32_t dos_stream_rate = DOS_STREAM_RATE_DEFAULT;
+static uint32_t dos_stream_burst = DOS_STREAM_BURST_DEFAULT;
+
+/* Keep some stats for the heartbeat so we can report out. */
+static uint64_t stream_num_rejected;
+
+/*
* General interface of the denial of service mitigation subsystem.
*/
@@ -258,6 +276,59 @@ get_param_conn_connect_defense_time_period(const networkstatus_t *ns)
INT32_MAX);
}
+/* Return true iff the stream creation mitigation is enabled. We look at the
+ * consensus for this else a default value is returned. */
+MOCK_IMPL(STATIC unsigned int,
+get_param_stream_enabled, (const networkstatus_t *ns))
+{
+ if (dos_get_options()->DoSStreamCreationEnabled != -1) {
+ return dos_get_options()->DoSStreamCreationEnabled;
+ }
+
+ return !!networkstatus_get_param(ns, "DoSStreamCreationEnabled",
+ DOS_STREAM_ENABLED_DEFAULT, 0, 1);
+}
+
+/* Return the parameter for the time rate that is how many stream per circuit
+ * over this time span. */
+static uint32_t
+get_param_stream_rate(const networkstatus_t *ns)
+{
+ /* This is in seconds. */
+ if (dos_get_options()->DoSStreamCreationRate) {
+ return dos_get_options()->DoSStreamCreationRate;
+ }
+ return networkstatus_get_param(ns, "DoSStreamCreationRate",
+ DOS_STREAM_RATE_DEFAULT,
+ 1, INT32_MAX);
+}
+
+/* Return the parameter for the maximum circuit count for the circuit time
+ * rate. */
+static uint32_t
+get_param_stream_burst(const networkstatus_t *ns)
+{
+ if (dos_get_options()->DoSStreamCreationBurst) {
+ return dos_get_options()->DoSStreamCreationBurst;
+ }
+ return networkstatus_get_param(ns, "DoSStreamCreationBurst",
+ DOS_STREAM_BURST_DEFAULT,
+ 1, INT32_MAX);
+}
+
+/* Return the consensus parameter of the circuit creation defense type. */
+static uint32_t
+get_param_stream_defense_type(const networkstatus_t *ns)
+{
+ if (dos_get_options()->DoSStreamCreationDefenseType) {
+ return dos_get_options()->DoSStreamCreationDefenseType;
+ }
+ return networkstatus_get_param(ns, "DoSStreamCreationDefenseType",
+ DOS_STREAM_DEFENSE_TYPE_DEFAULT,
+ DOS_STREAM_DEFENSE_NONE,
+ DOS_STREAM_DEFENSE_MAX);
+}
+
/* Set circuit creation parameters located in the consensus or their default
* if none are present. Called at initialization or when the consensus
* changes. */
@@ -283,6 +354,12 @@ set_dos_parameters(const networkstatus_t *ns)
/* Circuit. */
dos_num_circ_max_outq = get_param_dos_num_circ_max_outq(ns);
+
+ /* Stream. */
+ dos_stream_enabled = get_param_stream_enabled(ns);
+ dos_stream_defense_type = get_param_stream_defense_type(ns);
+ dos_stream_rate = get_param_stream_rate(ns);
+ dos_stream_burst = get_param_stream_burst(ns);
}
/* Free everything for the circuit creation DoS mitigation subsystem. */
@@ -760,6 +837,48 @@ dos_conn_addr_get_defense_type(const tor_addr_t *addr)
return DOS_CONN_DEFENSE_NONE;
}
+/* Stream creation public API. */
+
+/** Return the number of rejected stream and resolve. */
+uint64_t
+dos_get_num_stream_rejected(void)
+{
+ return stream_num_rejected;
+}
+
+/* Return the action to take against a BEGIN or RESOLVE cell. Return
+ * DOS_STREAM_DEFENSE_NONE when no action should be taken.
+ * Increment the appropriate counter when the cell was found to go over a
+ * limit. */
+dos_stream_defense_type_t
+dos_stream_new_begin_or_resolve_cell(or_circuit_t *circ)
+{
+ if (!dos_stream_enabled || circ == NULL)
+ return DOS_STREAM_DEFENSE_NONE;
+
+ token_bucket_ctr_refill(&circ->stream_limiter,
+ (uint32_t) monotime_coarse_absolute_sec());
+
+ if (token_bucket_ctr_get(&circ->stream_limiter) > 0) {
+ token_bucket_ctr_dec(&circ->stream_limiter, 1);
+ return DOS_STREAM_DEFENSE_NONE;
+ }
+ /* if defense type is DOS_STREAM_DEFENSE_NONE but DoSStreamEnabled is true,
+ * we count offending cells as rejected, despite them being actually
+ * accepted. */
+ ++stream_num_rejected;
+ return dos_stream_defense_type;
+}
+
+/* Initialize the token bucket for stream rate limit on a circuit. */
+void
+dos_stream_init_circ_tbf(or_circuit_t *circ)
+{
+ token_bucket_ctr_init(&circ->stream_limiter, dos_stream_rate,
+ dos_stream_burst,
+ (uint32_t) monotime_coarse_absolute_sec());
+}
+
/* General API */
/* Take any appropriate actions for the given geoip entry that is about to get
@@ -945,6 +1064,14 @@ dos_log_heartbeat(void)
"[DoSRefuseSingleHopClientRendezvous disabled]");
}
+ if (dos_stream_enabled) {
+ smartlist_add_asprintf(elems,
+ "%" PRIu64 " stream rejected",
+ stream_num_rejected);
+ } else {
+ smartlist_add_asprintf(elems, "[DoSStreamCreationEnabled disabled]");
+ }
+
/* HS DoS stats. */
smartlist_add_asprintf(elems,
"%" PRIu64 " INTRODUCE2 rejected",
diff --git a/src/core/or/dos.h b/src/core/or/dos.h
index 4a2227f132..03606287d1 100644
--- a/src/core/or/dos.h
+++ b/src/core/or/dos.h
@@ -90,6 +90,7 @@ uint64_t dos_get_num_cc_rejected(void);
uint64_t dos_get_num_conn_addr_rejected(void);
uint64_t dos_get_num_conn_addr_connect_rejected(void);
uint64_t dos_get_num_single_hop_refused(void);
+uint64_t dos_get_num_stream_rejected(void);
/*
* Circuit creation DoS mitigation subsystemn interface.
@@ -159,6 +160,37 @@ typedef enum dos_conn_defense_type_t {
dos_conn_defense_type_t dos_conn_addr_get_defense_type(const tor_addr_t *addr);
+/*
+ * Stream creation DoS mitigation subsystem interface.
+ */
+
+/* DoSStreamCreationEnabled default. Disabled by deault. */
+#define DOS_STREAM_ENABLED_DEFAULT 0
+/* DoSStreamCreationDefenseType maps to the dos_stream_defense_type_t enum */
+#define DOS_STREAM_DEFENSE_TYPE_DEFAULT DOS_STREAM_DEFENSE_REFUSE_STREAM
+/* DosStreamCreationRate is 100 per seconds. */
+#define DOS_STREAM_RATE_DEFAULT 100
+/* DosStreamCreationBurst default. */
+#define DOS_STREAM_BURST_DEFAULT 300
+
+/* Type of defense that we can use for the stream creation DoS mitigation. */
+typedef enum dos_stream_defense_type_t {
+ /* No defense used. */
+ DOS_STREAM_DEFENSE_NONE = 1,
+ /* Reject the stream */
+ DOS_STREAM_DEFENSE_REFUSE_STREAM = 2,
+ /* Close the circuit */
+ DOS_STREAM_DEFENSE_CLOSE_CIRCUIT = 3,
+
+ /* Maximum value that can be used. Useful for the boundaries of the
+ * consensus parameter. */
+ DOS_STREAM_DEFENSE_MAX = 3,
+} dos_stream_defense_type_t;
+
+dos_stream_defense_type_t dos_stream_new_begin_or_resolve_cell(
+ or_circuit_t *circ);
+void dos_stream_init_circ_tbf(or_circuit_t *circ);
+
#ifdef DOS_PRIVATE
STATIC uint32_t get_param_conn_max_concurrent_count(
@@ -176,6 +208,8 @@ MOCK_DECL(STATIC unsigned int, get_param_cc_enabled,
(const networkstatus_t *ns));
MOCK_DECL(STATIC unsigned int, get_param_conn_enabled,
(const networkstatus_t *ns));
+MOCK_DECL(STATIC unsigned int, get_param_stream_enabled,
+ (const networkstatus_t *ns));
#endif /* defined(DOS_PRIVATE) */
diff --git a/src/core/or/dos_options.inc b/src/core/or/dos_options.inc
index 9baa7a35b8..4d15c33f3d 100644
--- a/src/core/or/dos_options.inc
+++ b/src/core/or/dos_options.inc
@@ -50,6 +50,19 @@ CONF_VAR(DoSConnectionConnectBurst, POSINT, 0, "0")
/** Allowed rate of client connection allowed per address. */
CONF_VAR(DoSConnectionConnectRate, POSINT, 0, "0")
+/** Autobool: Is the stream creation DoS mitigation subsystem enabled? */
+CONF_VAR(DoSStreamCreationEnabled, AUTOBOOL, 0, "auto")
+
+/** Stream rate used to refill the token bucket. */
+CONF_VAR(DoSStreamCreationRate, POSINT, 0, "0")
+
+/** Maximum allowed burst of stream. */
+CONF_VAR(DoSStreamCreationBurst, POSINT, 0, "0")
+
+/** When an circuit is detected as malicious, what defense should be used
+ * against it. See the dos_stream_defense_type_t enum. */
+CONF_VAR(DoSStreamCreationDefenseType, INT, 0, "0")
+
/** For how much time (in seconds) the connection connect rate defense is
* applicable for a malicious address. A random time delta is added to the
* defense time of an address which will be between 1 second and half of this
diff --git a/src/core/or/extend_info_st.h b/src/core/or/extend_info_st.h
index 2ab0beb7e6..5f59bd2299 100644
--- a/src/core/or/extend_info_st.h
+++ b/src/core/or/extend_info_st.h
@@ -34,8 +34,6 @@ struct extend_info_t {
/** IP/Port values for this hop's ORPort(s). Any unused values are set
* to a null address. */
tor_addr_port_t orports[EXTEND_INFO_MAX_ADDRS];
- /** TAP onion key for this hop. */
- crypto_pk_t *onion_key;
/** Ntor onion key for this hop. */
curve25519_public_key_t curve25519_onion_key;
/** True if this hop is to be used as an _exit_,
diff --git a/src/core/or/extendinfo.c b/src/core/or/extendinfo.c
index ca623f09ce..6954335cc2 100644
--- a/src/core/or/extendinfo.c
+++ b/src/core/or/extendinfo.c
@@ -33,7 +33,6 @@ extend_info_t *
extend_info_new(const char *nickname,
const char *rsa_id_digest,
const ed25519_public_key_t *ed_id,
- crypto_pk_t *onion_key,
const curve25519_public_key_t *ntor_key,
const tor_addr_t *addr, uint16_t port,
const protover_summary_flags_t *pv,
@@ -46,8 +45,6 @@ extend_info_new(const char *nickname,
memcpy(&info->ed_identity, ed_id, sizeof(ed25519_public_key_t));
if (nickname)
strlcpy(info->nickname, nickname, sizeof(info->nickname));
- if (onion_key)
- info->onion_key = crypto_pk_dup_key(onion_key);
if (ntor_key)
memcpy(&info->curve25519_onion_key, ntor_key,
sizeof(curve25519_public_key_t));
@@ -100,7 +97,6 @@ extend_info_t *
extend_info_from_node(const node_t *node, int for_direct_connect,
bool for_exit)
{
- crypto_pk_t *rsa_pubkey = NULL;
extend_info_t *info = NULL;
tor_addr_port_t ap;
int valid_addr = 0;
@@ -149,13 +145,11 @@ extend_info_from_node(const node_t *node, int for_direct_connect,
/* Retrieve the curve25519 pubkey. */
const curve25519_public_key_t *curve_pubkey =
node_get_curve25519_onion_key(node);
- rsa_pubkey = node_get_rsa_onion_key(node);
if (valid_addr && node->ri) {
info = extend_info_new(node->ri->nickname,
node->identity,
ed_pubkey,
- rsa_pubkey,
curve_pubkey,
&ap.addr,
ap.port,
@@ -165,7 +159,6 @@ extend_info_from_node(const node_t *node, int for_direct_connect,
info = extend_info_new(node->rs->nickname,
node->identity,
ed_pubkey,
- rsa_pubkey,
curve_pubkey,
&ap.addr,
ap.port,
@@ -173,7 +166,6 @@ extend_info_from_node(const node_t *node, int for_direct_connect,
for_exit);
}
- crypto_pk_free(rsa_pubkey);
return info;
}
@@ -183,7 +175,6 @@ extend_info_free_(extend_info_t *info)
{
if (!info)
return;
- crypto_pk_free(info->onion_key);
tor_free(info);
}
@@ -196,22 +187,9 @@ extend_info_dup(extend_info_t *info)
tor_assert(info);
newinfo = tor_malloc(sizeof(extend_info_t));
memcpy(newinfo, info, sizeof(extend_info_t));
- if (info->onion_key)
- newinfo->onion_key = crypto_pk_dup_key(info->onion_key);
- else
- newinfo->onion_key = NULL;
return newinfo;
}
-/* Does ei have a valid TAP key? */
-int
-extend_info_supports_tap(const extend_info_t* ei)
-{
- tor_assert(ei);
- /* Valid TAP keys are not NULL */
- return ei->onion_key != NULL;
-}
-
/* Does ei have a valid ntor key? */
int
extend_info_supports_ntor(const extend_info_t* ei)
diff --git a/src/core/or/extendinfo.h b/src/core/or/extendinfo.h
index 6d1f20597b..3419a4e043 100644
--- a/src/core/or/extendinfo.h
+++ b/src/core/or/extendinfo.h
@@ -15,7 +15,6 @@
extend_info_t *extend_info_new(const char *nickname,
const char *rsa_id_digest,
const struct ed25519_public_key_t *ed_id,
- crypto_pk_t *onion_key,
const struct curve25519_public_key_t *ntor_key,
const tor_addr_t *addr, uint16_t port,
const struct protover_summary_flags_t *pv,
@@ -27,7 +26,6 @@ void extend_info_free_(extend_info_t *info);
#define extend_info_free(info) \
FREE_AND_NULL(extend_info_t, extend_info_free_, (info))
int extend_info_addr_is_allowed(const tor_addr_t *addr);
-int extend_info_supports_tap(const extend_info_t* ei);
int extend_info_supports_ntor(const extend_info_t* ei);
int extend_info_supports_ntor_v3(const extend_info_t *ei);
int extend_info_has_preferred_onion_key(const extend_info_t* ei);
diff --git a/src/core/or/half_edge_st.h b/src/core/or/half_edge_st.h
index 642d8e1ea5..d8c183a93c 100644
--- a/src/core/or/half_edge_st.h
+++ b/src/core/or/half_edge_st.h
@@ -41,10 +41,10 @@ typedef struct half_edge_t {
/**
* Did this edge use congestion control? If so, use
* timer instead of pending data approach */
- int used_ccontrol : 1;
+ unsigned int used_ccontrol : 1;
/** Is there a connected cell pending? */
- int connected_pending : 1;
+ unsigned int connected_pending : 1;
} half_edge_t;
#endif /* !defined(HALF_EDGE_ST_H) */
diff --git a/src/core/or/onion.c b/src/core/or/onion.c
index 0bdd2a6d35..07c26a80e8 100644
--- a/src/core/or/onion.c
+++ b/src/core/or/onion.c
@@ -44,7 +44,6 @@
#include "core/crypto/onion_crypto.h"
#include "core/crypto/onion_fast.h"
#include "core/crypto/onion_ntor.h"
-#include "core/crypto/onion_tap.h"
#include "core/or/onion.h"
#include "feature/nodelist/networkstatus.h"
@@ -61,10 +60,7 @@ check_create_cell(const create_cell_t *cell, int unknown_ok)
{
switch (cell->cell_type) {
case CELL_CREATE:
- if (cell->handshake_type != ONION_HANDSHAKE_TYPE_TAP &&
- cell->handshake_type != ONION_HANDSHAKE_TYPE_NTOR)
- return -1;
- break;
+ return -1;
case CELL_CREATE_FAST:
if (cell->handshake_type != ONION_HANDSHAKE_TYPE_FAST)
return -1;
@@ -77,9 +73,7 @@ check_create_cell(const create_cell_t *cell, int unknown_ok)
switch (cell->handshake_type) {
case ONION_HANDSHAKE_TYPE_TAP:
- if (cell->handshake_len != TAP_ONIONSKIN_CHALLENGE_LEN)
- return -1;
- break;
+ return -1;
case ONION_HANDSHAKE_TYPE_FAST:
if (cell->handshake_len != CREATE_FAST_LEN)
return -1;
@@ -160,14 +154,7 @@ create_cell_parse(create_cell_t *cell_out, const cell_t *cell_in)
{
switch (cell_in->command) {
case CELL_CREATE:
- if (tor_memeq(cell_in->payload, NTOR_CREATE_MAGIC, 16)) {
- create_cell_init(cell_out, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR,
- NTOR_ONIONSKIN_LEN, cell_in->payload+16);
- } else {
- create_cell_init(cell_out, CELL_CREATE, ONION_HANDSHAKE_TYPE_TAP,
- TAP_ONIONSKIN_CHALLENGE_LEN, cell_in->payload);
- }
- break;
+ return -1;
case CELL_CREATE_FAST:
create_cell_init(cell_out, CELL_CREATE_FAST, ONION_HANDSHAKE_TYPE_FAST,
CREATE_FAST_LEN, cell_in->payload);
@@ -190,10 +177,7 @@ check_created_cell(const created_cell_t *cell)
{
switch (cell->cell_type) {
case CELL_CREATED:
- if (cell->handshake_len != TAP_ONIONSKIN_REPLY_LEN &&
- cell->handshake_len != NTOR_REPLY_LEN)
- return -1;
- break;
+ return -1;
case CELL_CREATED_FAST:
if (cell->handshake_len != CREATED_FAST_LEN)
return -1;
@@ -216,10 +200,7 @@ created_cell_parse(created_cell_t *cell_out, const cell_t *cell_in)
switch (cell_in->command) {
case CELL_CREATED:
- cell_out->cell_type = CELL_CREATED;
- cell_out->handshake_len = TAP_ONIONSKIN_REPLY_LEN;
- memcpy(cell_out->reply, cell_in->payload, TAP_ONIONSKIN_REPLY_LEN);
- break;
+ return -1;
case CELL_CREATED_FAST:
cell_out->cell_type = CELL_CREATED_FAST;
cell_out->handshake_len = CREATED_FAST_LEN;
@@ -260,53 +241,22 @@ check_extend_cell(const extend_cell_t *cell)
}
}
if (cell->create_cell.cell_type == CELL_CREATE) {
- if (cell->cell_type != RELAY_COMMAND_EXTEND)
- return -1;
+ return -1;
} else if (cell->create_cell.cell_type == CELL_CREATE2) {
- if (cell->cell_type != RELAY_COMMAND_EXTEND2 &&
- cell->cell_type != RELAY_COMMAND_EXTEND)
+ if (cell->cell_type != RELAY_COMMAND_EXTEND2)
return -1;
} else {
/* In particular, no CREATE_FAST cells are allowed */
return -1;
}
- if (cell->create_cell.handshake_type == ONION_HANDSHAKE_TYPE_FAST)
+ if (cell->create_cell.handshake_type == ONION_HANDSHAKE_TYPE_FAST ||
+ cell->create_cell.handshake_type == ONION_HANDSHAKE_TYPE_TAP)
return -1;
return check_create_cell(&cell->create_cell, 1);
}
static int
-extend_cell_from_extend1_cell_body(extend_cell_t *cell_out,
- const extend1_cell_body_t *cell)
-{
- tor_assert(cell_out);
- tor_assert(cell);
- memset(cell_out, 0, sizeof(*cell_out));
- tor_addr_make_unspec(&cell_out->orport_ipv4.addr);
- tor_addr_make_unspec(&cell_out->orport_ipv6.addr);
-
- cell_out->cell_type = RELAY_COMMAND_EXTEND;
- tor_addr_from_ipv4h(&cell_out->orport_ipv4.addr, cell->ipv4addr);
- cell_out->orport_ipv4.port = cell->port;
- if (tor_memeq(cell->onionskin, NTOR_CREATE_MAGIC, 16)) {
- cell_out->create_cell.cell_type = CELL_CREATE2;
- cell_out->create_cell.handshake_type = ONION_HANDSHAKE_TYPE_NTOR;
- cell_out->create_cell.handshake_len = NTOR_ONIONSKIN_LEN;
- memcpy(cell_out->create_cell.onionskin, cell->onionskin + 16,
- NTOR_ONIONSKIN_LEN);
- } else {
- cell_out->create_cell.cell_type = CELL_CREATE;
- cell_out->create_cell.handshake_type = ONION_HANDSHAKE_TYPE_TAP;
- cell_out->create_cell.handshake_len = TAP_ONIONSKIN_CHALLENGE_LEN;
- memcpy(cell_out->create_cell.onionskin, cell->onionskin,
- TAP_ONIONSKIN_CHALLENGE_LEN);
- }
- memcpy(cell_out->node_id, cell->identity, DIGEST_LEN);
- return 0;
-}
-
-static int
create_cell_from_create2_cell_body(create_cell_t *cell_out,
const create2_cell_body_t *cell)
{
@@ -408,19 +358,7 @@ extend_cell_parse,(extend_cell_t *cell_out,
switch (command) {
case RELAY_COMMAND_EXTEND:
- {
- extend1_cell_body_t *cell = NULL;
- if (extend1_cell_body_parse(&cell, payload, payload_length)<0 ||
- cell == NULL) {
- if (cell)
- extend1_cell_body_free(cell);
- return -1;
- }
- int r = extend_cell_from_extend1_cell_body(cell_out, cell);
- extend1_cell_body_free(cell);
- if (r < 0)
- return r;
- }
+ return -1;
break;
case RELAY_COMMAND_EXTEND2:
{
@@ -479,13 +417,7 @@ extended_cell_parse(extended_cell_t *cell_out,
switch (command) {
case RELAY_COMMAND_EXTENDED:
- if (payload_len != TAP_ONIONSKIN_REPLY_LEN)
- return -1;
- cell_out->cell_type = RELAY_COMMAND_EXTENDED;
- cell_out->created_cell.cell_type = CELL_CREATED;
- cell_out->created_cell.handshake_len = TAP_ONIONSKIN_REPLY_LEN;
- memcpy(cell_out->created_cell.reply, payload, TAP_ONIONSKIN_REPLY_LEN);
- break;
+ return -1;
case RELAY_COMMAND_EXTENDED2:
{
cell_out->cell_type = RELAY_COMMAND_EXTENDED2;
@@ -627,26 +559,7 @@ extend_cell_format(uint8_t *command_out, uint16_t *len_out,
switch (cell_in->cell_type) {
case RELAY_COMMAND_EXTEND:
- {
- if (BUG(cell_in->create_cell.handshake_type ==
- ONION_HANDSHAKE_TYPE_NTOR_V3)) {
- log_warn(LD_BUG, "Extend cells cannot contain ntorv3!");
- return -1;
- }
- *command_out = RELAY_COMMAND_EXTEND;
- *len_out = 6 + TAP_ONIONSKIN_CHALLENGE_LEN + DIGEST_LEN;
- set_uint32(p, tor_addr_to_ipv4n(&cell_in->orport_ipv4.addr));
- set_uint16(p+4, htons(cell_in->orport_ipv4.port));
- if (cell_in->create_cell.handshake_type == ONION_HANDSHAKE_TYPE_NTOR) {
- memcpy(p+6, NTOR_CREATE_MAGIC, 16);
- memcpy(p+22, cell_in->create_cell.onionskin, NTOR_ONIONSKIN_LEN);
- } else {
- memcpy(p+6, cell_in->create_cell.onionskin,
- TAP_ONIONSKIN_CHALLENGE_LEN);
- }
- memcpy(p+6+TAP_ONIONSKIN_CHALLENGE_LEN, cell_in->node_id, DIGEST_LEN);
- }
- break;
+ return -1;
case RELAY_COMMAND_EXTEND2:
{
uint8_t n_specifiers = 1;
@@ -737,13 +650,7 @@ extended_cell_format(uint8_t *command_out, uint16_t *len_out,
switch (cell_in->cell_type) {
case RELAY_COMMAND_EXTENDED:
- {
- *command_out = RELAY_COMMAND_EXTENDED;
- *len_out = TAP_ONIONSKIN_REPLY_LEN;
- memcpy(payload_out, cell_in->created_cell.reply,
- TAP_ONIONSKIN_REPLY_LEN);
- }
- break;
+ return -1;
case RELAY_COMMAND_EXTENDED2:
{
*command_out = RELAY_COMMAND_EXTENDED2;
diff --git a/src/core/or/or_circuit_st.h b/src/core/or/or_circuit_st.h
index d5a7007928..28e357338a 100644
--- a/src/core/or/or_circuit_st.h
+++ b/src/core/or/or_circuit_st.h
@@ -102,6 +102,10 @@ struct or_circuit_t {
* used if this is a service introduction circuit at the intro point
* (purpose = CIRCUIT_PURPOSE_INTRO_POINT). */
token_bucket_ctr_t introduce2_bucket;
+
+ /** RELAY_BEGIN and RELAY_RESOLVE cell bucket controlling how much can go on
+ * this circuit. Only used if this is the end of a circuit on an exit node.*/
+ token_bucket_ctr_t stream_limiter;
};
#endif /* !defined(OR_CIRCUIT_ST_H) */
diff --git a/src/core/or/policies.c b/src/core/or/policies.c
index 1864b84d5e..4641632b60 100644
--- a/src/core/or/policies.c
+++ b/src/core/or/policies.c
@@ -1066,7 +1066,7 @@ socks_policy_permits_address(const tor_addr_t *addr)
}
/** Return 1 if <b>addr</b> is permitted to connect to our metrics port,
- * based on <b>socks_policy</b>. Else return 0.
+ * based on <b>metrics_policy</b>. Else return 0.
*/
int
metrics_policy_permits_address(const tor_addr_t *addr)
diff --git a/src/core/or/protover.c b/src/core/or/protover.c
index 175bfbdab0..1ac32bf06c 100644
--- a/src/core/or/protover.c
+++ b/src/core/or/protover.c
@@ -389,7 +389,7 @@ protocol_list_supports_protocol_or_later(const char *list,
/* All protocol version that this relay version supports. */
#define PR_CONFLUX_V "1"
#define PR_CONS_V "1-2"
-#define PR_DESC_V "1-2"
+#define PR_DESC_V "1-3"
#define PR_DIRCACHE_V "2"
#define PR_FLOWCTRL_V "1-2"
#define PR_HSDIR_V "2"
@@ -401,9 +401,9 @@ protocol_list_supports_protocol_or_later(const char *list,
#else
#define PR_LINKAUTH_V "3"
#endif
-#define PR_MICRODESC_V "1-2"
+#define PR_MICRODESC_V "1-3"
#define PR_PADDING_V "2"
-#define PR_RELAY_V "1-4"
+#define PR_RELAY_V "2-4"
/** Return the string containing the supported version for the given protocol
* type. */
diff --git a/src/core/or/relay.c b/src/core/or/relay.c
index 3670353ad3..f7d200c18d 100644
--- a/src/core/or/relay.c
+++ b/src/core/or/relay.c
@@ -2030,8 +2030,7 @@ handle_relay_cell_command(cell_t *cell, circuit_t *circ,
circ->purpose);
return 0;
}
- connection_exit_begin_resolve(cell, TO_OR_CIRCUIT(circ));
- return 0;
+ return connection_exit_begin_resolve(cell, TO_OR_CIRCUIT(circ));
case RELAY_COMMAND_RESOLVED:
if (conn) {
log_fn(LOG_PROTOCOL_WARN, domain,
diff --git a/src/core/or/scheduler_kist.c b/src/core/or/scheduler_kist.c
index 69804247c8..c4b15a9950 100644
--- a/src/core/or/scheduler_kist.c
+++ b/src/core/or/scheduler_kist.c
@@ -447,10 +447,16 @@ update_socket_written(socket_table_t *table, channel_t *chan, size_t bytes)
* by only writing a channel's outbuf to the kernel if it has 8 cells or more
* in it.
*
- * Note: The number 8 has been picked for no particular reasons except that it
- * is 4096 bytes which is a common number for buffering. A TLS record can hold
- * up to 16KiB thus using 8 cells means that a relay will at most send a TLS
- * record of 4KiB or 1/4 of the maximum capacity of a TLS record.
+ * Note: The number 8 was picked so that, when using 512-byte cells, it
+ * would produce 4096 bytes: a common number for buffering. A TLS
+ * record can hold up to 16KiB; thus, using 8 512-byte cells means that
+ * a relay will at most send a TLS record of 4KiB or 1/4 of the maximum
+ * capacity of a TLS record.
+ *
+ * Of course, the above calculation became incorrect when we moved to
+ * 514-byte cells in order to accommodate a 4-byte circuit ID; we may
+ * want to consider profiling with '7' to see if it produces better
+ * results. (TODO)
*/
MOCK_IMPL(int, channel_should_write_to_kernel,
(outbuf_table_t *table, channel_t *chan))
diff --git a/src/core/proto/proto_socks.c b/src/core/proto/proto_socks.c
index 78767a94ff..8c53bf6210 100644
--- a/src/core/proto/proto_socks.c
+++ b/src/core/proto/proto_socks.c
@@ -451,6 +451,19 @@ parse_socks5_userpass_auth(const uint8_t *raw_data, socks_request_t *req,
const char *password =
socks5_client_userpass_auth_getconstarray_passwd(trunnel_req);
+ /* Detect invalid SOCKS5 extended-parameter requests. */
+ if (usernamelen >= 8 &&
+ tor_memeq(username, "<torS0X>", 8)) {
+ /* This is indeed an extended-parameter request. */
+ if (usernamelen != 9 ||
+ tor_memneq(username, "<torS0X>0", 9)) {
+ /* This request is an unrecognized version, or it includes an Arti RPC
+ * object ID (which we do not recognize). */
+ res = SOCKS_RESULT_INVALID;
+ goto end;
+ }
+ }
+
if (usernamelen && username) {
tor_free(req->username);
req->username = tor_memdup_nulterm(username, usernamelen);
@@ -919,11 +932,12 @@ static const char SOCKS_PROXY_IS_NOT_AN_HTTP_PROXY_MSG[] =
"<title>This is a SOCKS Proxy, Not An HTTP Proxy</title>\n"
"</head>\n"
"<body>\n"
- "<h1>This is a SOCKs proxy, not an HTTP proxy.</h1>\n"
+ "<h1>This is a SOCKS proxy, not an HTTP proxy.</h1>\n"
"<p>\n"
"It appears you have configured your web browser to use this Tor port as\n"
"an HTTP proxy.\n"
- "</p><p>\n"
+ "</p>\n"
+ "<p>\n"
"This is not correct: This port is configured as a SOCKS proxy, not\n"
"an HTTP proxy. If you need an HTTP proxy tunnel, use the HTTPTunnelPort\n"
"configuration option in place of, or in addition to, SOCKSPort.\n"
diff --git a/src/feature/client/bridges.c b/src/feature/client/bridges.c
index a0375828a7..f4f7ac23a3 100644
--- a/src/feature/client/bridges.c
+++ b/src/feature/client/bridges.c
@@ -316,7 +316,8 @@ addr_is_a_configured_bridge(const tor_addr_t *addr,
/** If we have a bridge configured whose digest matches
* <b>ei->identity_digest</b>, or a bridge with no known digest whose address
* matches <b>ei->addr</b>:<b>ei->port</b>, return 1. Else return 0.
- * If <b>ei->onion_key</b> is NULL, check for address/port matches only.
+ * If <b>ei</b> has no onion key configured, check for address/port matches
+ * only.
*
* Note that if the extend_info_t contains multiple addresses, we return true
* only if _every_ address is a bridge.
@@ -324,7 +325,8 @@ addr_is_a_configured_bridge(const tor_addr_t *addr,
int
extend_info_is_a_configured_bridge(const extend_info_t *ei)
{
- const char *digest = ei->onion_key ? ei->identity_digest : NULL;
+ const char *digest = curve25519_public_key_is_ok(&ei->curve25519_onion_key)
+ ? ei->identity_digest : NULL;
const tor_addr_port_t *ap1 = NULL, *ap2 = NULL;
if (! tor_addr_is_null(&ei->orports[0].addr))
ap1 = &ei->orports[0];
diff --git a/src/feature/client/entrynodes.c b/src/feature/client/entrynodes.c
index 7c469ea84a..dee41fefa8 100644
--- a/src/feature/client/entrynodes.c
+++ b/src/feature/client/entrynodes.c
@@ -2169,7 +2169,7 @@ select_primary_guard_for_circuit(guard_selection_t *gs,
static ratelim_t guardlog = RATELIM_INIT(60);
log_fn_ratelim(&guardlog, LOG_NOTICE, LD_GUARD,
"All current guards excluded by path restriction "
- "type %d; using an additonal guard.",
+ "type %d; using an additional guard.",
rst->type);
} else {
break;
diff --git a/src/feature/dirauth/dirauth_config.c b/src/feature/dirauth/dirauth_config.c
index f98513ef75..9378b0ffe6 100644
--- a/src/feature/dirauth/dirauth_config.c
+++ b/src/feature/dirauth/dirauth_config.c
@@ -16,9 +16,12 @@
#include "lib/encoding/confline.h"
#include "lib/confmgt/confmgt.h"
#include "lib/conf/confdecl.h"
+#include "lib/version/torversion.h"
/* Required for dirinfo_type_t in or_options_t */
#include "core/or/or.h"
+#include "core/or/tor_version_st.h"
+#include "core/or/versions.h"
#include "app/config/config.h"
#include "app/config/resolve_addr.h"
@@ -426,6 +429,7 @@ static int
dirauth_options_validate(const void *arg, char **msg)
{
const dirauth_options_t *options = arg;
+ tor_version_t minimal_accepted_server_version, recommended_version;
if (options->VersioningAuthoritativeDirectory &&
(!options->RecommendedClientVersions ||
@@ -439,12 +443,53 @@ dirauth_options_validate(const void *arg, char **msg)
REJECT("Guard bandwdith threshold fraction is invalid.");
}
- char *t;
+ if (tor_version_parse(options->MinimalAcceptedServerVersion,
+ &minimal_accepted_server_version) != 0) {
+ REJECT("Invalid MinimalAcceptedServerVersion");
+ }
+
+ tor_assertf(tor_version_parse(get_short_version(),
+ &recommended_version) == 0,
+ "We failed to parse our own version");
+ if (tor_version_compare(&recommended_version,
+ &minimal_accepted_server_version) < 0) {
+ REJECT("MinimalAcceptedServerVersion wants to reject the version "
+ "this node is running");
+ }
+
+ char *recommended_versions;
+ int found_recommended_rejected_version = 0;
/* Call these functions to produce warnings only. */
- t = format_recommended_version_list(options->RecommendedClientVersions, 1);
- tor_free(t);
- t = format_recommended_version_list(options->RecommendedServerVersions, 1);
- tor_free(t);
+ recommended_versions = format_recommended_version_list(
+ options->RecommendedClientVersions, 1);
+ tor_free(recommended_versions);
+
+ recommended_versions = format_recommended_version_list(
+ options->RecommendedServerVersions, 1);
+
+ smartlist_t *version_sl = smartlist_new();
+ smartlist_split_string(version_sl, recommended_versions, ",",
+ SPLIT_SKIP_SPACE, 0);
+ SMARTLIST_FOREACH_BEGIN(version_sl, const char *, version) {
+ if (version[0] != '\0' && tor_version_parse(version,
+ &recommended_version) != 0) {
+ COMPLAIN("Found unparseable version in RecommendedServerVersions");
+ continue;
+ }
+
+ if (tor_version_compare(&recommended_version,
+ &minimal_accepted_server_version) < 0) {
+ found_recommended_rejected_version = 1;
+ break;
+ }
+ } SMARTLIST_FOREACH_END(version);
+
+ SMARTLIST_FOREACH(version_sl, char *, version, tor_free(version));
+ smartlist_free(version_sl);
+ tor_free(recommended_versions);
+ if (found_recommended_rejected_version)
+ REJECT("MinimalAcceptedServerVersion wants to reject a recommended "
+ "version");
if (options->TestingAuthDirTimeToLearnReachability > 2*60*60) {
COMPLAIN("TestingAuthDirTimeToLearnReachability is insanely high.");
diff --git a/src/feature/dirauth/dirauth_options.inc b/src/feature/dirauth/dirauth_options.inc
index e2056c9cc7..c6f9c09213 100644
--- a/src/feature/dirauth/dirauth_options.inc
+++ b/src/feature/dirauth/dirauth_options.inc
@@ -76,6 +76,9 @@ CONF_VAR(RecommendedClientVersions, LINELIST, 0, NULL)
/** Which versions of tor should we tell users to run on relays? */
CONF_VAR(RecommendedServerVersions, LINELIST, 0, NULL)
+/** Which minimal version of tor do we accept relay descriptors from? */
+CONF_VAR(MinimalAcceptedServerVersion, STRING, 0, "0.4.8.0-alpha-dev")
+
/** Relays which should be voted Guard regardless of uptime and bandwidth. */
CONF_VAR(AuthDirVoteGuard, ROUTERSET, 0, NULL)
diff --git a/src/feature/dirauth/dirvote.c b/src/feature/dirauth/dirvote.c
index 0783fb1e91..42c0802433 100644
--- a/src/feature/dirauth/dirvote.c
+++ b/src/feature/dirauth/dirvote.c
@@ -1631,7 +1631,11 @@ networkstatus_compute_consensus(smartlist_t *votes,
n_versioning_servers);
client_versions = compute_consensus_versions_list(combined_client_versions,
n_versioning_clients);
- packages = compute_consensus_package_lines(votes);
+
+ if (consensus_method < MIN_METHOD_TO_OMIT_PACKAGE_FINGERPRINTS)
+ packages = tor_strdup("");
+ else
+ packages = compute_consensus_package_lines(votes);
SMARTLIST_FOREACH(combined_server_versions, char *, cp, tor_free(cp));
SMARTLIST_FOREACH(combined_client_versions, char *, cp, tor_free(cp));
@@ -1776,15 +1780,10 @@ networkstatus_compute_consensus(smartlist_t *votes,
}
{
- if (consensus_method < MIN_METHOD_FOR_CORRECT_BWWEIGHTSCALE) {
- max_unmeasured_bw_kb = (int32_t) extract_param_buggy(
- params, "maxunmeasuredbw", DEFAULT_MAX_UNMEASURED_BW_KB);
- } else {
- max_unmeasured_bw_kb = dirvote_get_intermediate_param_value(
- param_list, "maxunmeasuredbw", DEFAULT_MAX_UNMEASURED_BW_KB);
- if (max_unmeasured_bw_kb < 1)
- max_unmeasured_bw_kb = 1;
- }
+ max_unmeasured_bw_kb = dirvote_get_intermediate_param_value(
+ param_list, "maxunmeasuredbw", DEFAULT_MAX_UNMEASURED_BW_KB);
+ if (max_unmeasured_bw_kb < 1)
+ max_unmeasured_bw_kb = 1;
}
/* Add the actual router entries. */
@@ -2130,7 +2129,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
/* Starting with consensus method 32, we handle the middle-only
* flag specially: when it is present, we clear some flags, and
* set others. */
- if (is_middle_only && consensus_method >= MIN_METHOD_FOR_MIDDLEONLY) {
+ if (is_middle_only) {
remove_flag(chosen_flags, "Exit");
remove_flag(chosen_flags, "V2Dir");
remove_flag(chosen_flags, "Guard");
@@ -2367,15 +2366,10 @@ networkstatus_compute_consensus(smartlist_t *votes,
{
int64_t weight_scale;
- if (consensus_method < MIN_METHOD_FOR_CORRECT_BWWEIGHTSCALE) {
- weight_scale = extract_param_buggy(params, "bwweightscale",
- BW_WEIGHT_SCALE);
- } else {
- weight_scale = dirvote_get_intermediate_param_value(
- param_list, "bwweightscale", BW_WEIGHT_SCALE);
- if (weight_scale < 1)
- weight_scale = 1;
- }
+ weight_scale = dirvote_get_intermediate_param_value(
+ param_list, "bwweightscale", BW_WEIGHT_SCALE);
+ if (weight_scale < 1)
+ weight_scale = 1;
added_weights = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D,
T, weight_scale);
}
@@ -2477,53 +2471,6 @@ networkstatus_compute_consensus(smartlist_t *votes,
return result;
}
-/** Extract the value of a parameter from a string encoding a list of
- * parameters, badly.
- *
- * This is a deliberately buggy implementation, for backward compatibility
- * with versions of Tor affected by #19011. Once all authorities have
- * upgraded to consensus method 31 or later, then we can throw away this
- * function. */
-STATIC int64_t
-extract_param_buggy(const char *params,
- const char *param_name,
- int64_t default_value)
-{
- int64_t value = default_value;
- const char *param_str = NULL;
-
- if (params) {
- char *prefix1 = NULL, *prefix2=NULL;
- tor_asprintf(&prefix1, "%s=", param_name);
- tor_asprintf(&prefix2, " %s=", param_name);
- if (strcmpstart(params, prefix1) == 0)
- param_str = params;
- else
- param_str = strstr(params, prefix2);
- tor_free(prefix1);
- tor_free(prefix2);
- }
-
- if (param_str) {
- int ok=0;
- char *eq = strchr(param_str, '=');
- if (eq) {
- value = tor_parse_long(eq+1, 10, 1, INT32_MAX, &ok, NULL);
- if (!ok) {
- log_warn(LD_DIR, "Bad element '%s' in %s",
- escaped(param_str), param_name);
- value = default_value;
- }
- } else {
- log_warn(LD_DIR, "Bad element '%s' in %s",
- escaped(param_str), param_name);
- value = default_value;
- }
- }
-
- return value;
-}
-
/** Given a list of networkstatus_t for each vote, return a newly allocated
* string containing the "package" lines for the vote. */
STATIC char *
@@ -3919,13 +3866,18 @@ dirvote_get_vote(const char *fp, int flags)
STATIC microdesc_t *
dirvote_create_microdescriptor(const routerinfo_t *ri, int consensus_method)
{
+ (void) consensus_method; // Currently unneeded...
microdesc_t *result = NULL;
char *key = NULL, *summary = NULL, *family = NULL;
size_t keylen;
smartlist_t *chunks = smartlist_new();
char *output = NULL;
- crypto_pk_t *rsa_pubkey = router_get_rsa_onion_pkey(ri->onion_pkey,
- ri->onion_pkey_len);
+ crypto_pk_t *rsa_pubkey = router_get_rsa_onion_pkey(ri->tap_onion_pkey,
+ ri->tap_onion_pkey_len);
+ if (!rsa_pubkey) {
+ /* We do not yet support creating MDs for relays without TAP onion keys. */
+ goto done;
+ }
if (crypto_pk_write_public_key_to_string(rsa_pubkey, &key, &keylen)<0)
goto done;
@@ -3937,20 +3889,15 @@ dirvote_create_microdescriptor(const routerinfo_t *ri, int consensus_method)
if (ri->onion_curve25519_pkey) {
char kbuf[CURVE25519_BASE64_PADDED_LEN + 1];
- bool add_padding = (consensus_method < MIN_METHOD_FOR_UNPADDED_NTOR_KEY);
- curve25519_public_to_base64(kbuf, ri->onion_curve25519_pkey, add_padding);
+ curve25519_public_to_base64(kbuf, ri->onion_curve25519_pkey, false);
smartlist_add_asprintf(chunks, "ntor-onion-key %s\n", kbuf);
}
if (family) {
- if (consensus_method < MIN_METHOD_FOR_CANONICAL_FAMILIES_IN_MICRODESCS) {
- smartlist_add_asprintf(chunks, "family %s\n", family);
- } else {
- const uint8_t *id = (const uint8_t *)ri->cache_info.identity_digest;
- char *canonical_family = nodefamily_canonicalize(family, id, 0);
- smartlist_add_asprintf(chunks, "family %s\n", canonical_family);
- tor_free(canonical_family);
- }
+ const uint8_t *id = (const uint8_t *)ri->cache_info.identity_digest;
+ char *canonical_family = nodefamily_canonicalize(family, id, 0);
+ smartlist_add_asprintf(chunks, "family %s\n", canonical_family);
+ tor_free(canonical_family);
}
if (summary && strcmp(summary, "reject 1-65535"))
@@ -4048,10 +3995,6 @@ static const struct consensus_method_range_t {
int high;
} microdesc_consensus_methods[] = {
{MIN_SUPPORTED_CONSENSUS_METHOD,
- MIN_METHOD_FOR_CANONICAL_FAMILIES_IN_MICRODESCS - 1},
- {MIN_METHOD_FOR_CANONICAL_FAMILIES_IN_MICRODESCS,
- MIN_METHOD_FOR_UNPADDED_NTOR_KEY - 1},
- {MIN_METHOD_FOR_UNPADDED_NTOR_KEY,
MAX_SUPPORTED_CONSENSUS_METHOD},
{-1, -1}
};
diff --git a/src/feature/dirauth/dirvote.h b/src/feature/dirauth/dirvote.h
index ae8d43a6f0..6ac07f171a 100644
--- a/src/feature/dirauth/dirvote.h
+++ b/src/feature/dirauth/dirvote.h
@@ -50,29 +50,10 @@
((MIN_VOTE_SECONDS_TESTING)+(MIN_DIST_SECONDS_TESTING)+1)
/** The lowest consensus method that we currently support. */
-#define MIN_SUPPORTED_CONSENSUS_METHOD 28
+#define MIN_SUPPORTED_CONSENSUS_METHOD 32
/** The highest consensus method that we currently support. */
-#define MAX_SUPPORTED_CONSENSUS_METHOD 33
-
-/**
- * Lowest consensus method where microdescriptor lines are put in canonical
- * form for improved compressibility and ease of storage. See proposal 298.
- **/
-#define MIN_METHOD_FOR_CANONICAL_FAMILIES_IN_MICRODESCS 29
-
-/** Lowest consensus method where an unpadded base64 onion-key-ntor is allowed
- * See #7869 */
-#define MIN_METHOD_FOR_UNPADDED_NTOR_KEY 30
-
-/** Lowest consensus method for which we use the correct algorithm for
- * extracting the bwweightscale= and maxunmeasuredbw= parameters. See #19011.
- */
-#define MIN_METHOD_FOR_CORRECT_BWWEIGHTSCALE 31
-
-/** Lowest consensus method for which we handle the MiddleOnly flag specially.
- */
-#define MIN_METHOD_FOR_MIDDLEONLY 32
+#define MAX_SUPPORTED_CONSENSUS_METHOD 34
/**
* Lowest consensus method for which we suppress the published time in
@@ -80,6 +61,12 @@
*/
#define MIN_METHOD_TO_SUPPRESS_MD_PUBLISHED 33
+/**
+ * Lowest (supported) consensus method for which we do not include
+ * any "package" lines.
+ **/
+#define MIN_METHOD_TO_OMIT_PACKAGE_FINGERPRINTS 34
+
/** Default bandwidth to clip unmeasured bandwidths to using method >=
* MIN_METHOD_TO_CLIP_UNMEASURED_BW. (This is not a consensus method; do not
* get confused with the above macros.) */
@@ -274,9 +261,6 @@ STATIC
char *networkstatus_get_detached_signatures(smartlist_t *consensuses);
STATIC microdesc_t *dirvote_create_microdescriptor(const routerinfo_t *ri,
int consensus_method);
-STATIC int64_t extract_param_buggy(const char *params,
- const char *param_name,
- int64_t default_value);
#endif /* defined(DIRVOTE_PRIVATE) */
diff --git a/src/feature/dirauth/process_descs.c b/src/feature/dirauth/process_descs.c
index fafb781330..5b76e937ab 100644
--- a/src/feature/dirauth/process_descs.c
+++ b/src/feature/dirauth/process_descs.c
@@ -404,8 +404,8 @@ dirserv_rejects_tor_version(const char *platform,
static const char please_upgrade_string[] =
"Tor version is insecure or unsupported. Please upgrade!";
- /* Anything before 0.4.8.0 is unsupported. Reject them. */
- if (!tor_version_as_new_as(platform,"0.4.8.0-alpha-dev")) {
+ if (!tor_version_as_new_as(platform,
+ dirauth_get_options()->MinimalAcceptedServerVersion)) {
if (msg) {
*msg = please_upgrade_string;
}
@@ -762,6 +762,16 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source)
log_info(LD_DIR, "Assessing new descriptor: %s: %s",
ri->nickname, ri->platform);
+ /* For now, TAP keys are still required. */
+ if (! ri->tap_onion_pkey) {
+ log_info(LD_DIRSERV, "Rejecting descriptor from %s (source: %s); "
+ "it has no TAP key.",
+ router_describe(ri), source);
+ *msg = "Missing TAP key in descriptor.";
+ r = ROUTER_AUTHDIR_REJECTS;
+ goto fail;
+ }
+
/* Check whether this descriptor is semantically identical to the last one
* from this server. (We do this here and not in router_add_to_routerlist
* because we want to be able to accept the newest router descriptor that
diff --git a/src/feature/dirauth/voteflags.c b/src/feature/dirauth/voteflags.c
index 71ee03e265..2fbac47b30 100644
--- a/src/feature/dirauth/voteflags.c
+++ b/src/feature/dirauth/voteflags.c
@@ -112,8 +112,7 @@ dirserv_thinks_router_is_unreliable(time_t now,
}
/** Return 1 if <b>ri</b>'s descriptor is "active" -- running, valid,
- * not hibernating, having observed bw greater 0, and not too old. Else
- * return 0.
+ * not hibernating, and not too old. Else return 0.
*/
static int
router_is_active(const routerinfo_t *ri, const node_t *node, time_t now)
@@ -125,20 +124,6 @@ router_is_active(const routerinfo_t *ri, const node_t *node, time_t now)
if (!node->is_running || !node->is_valid || ri->is_hibernating) {
return 0;
}
- /* Only require bandwidth capacity in non-test networks, or
- * if TestingTorNetwork, and TestingMinExitFlagThreshold is non-zero */
- if (!ri->bandwidthcapacity) {
- if (get_options()->TestingTorNetwork) {
- if (dirauth_get_options()->TestingMinExitFlagThreshold > 0) {
- /* If we're in a TestingTorNetwork, and TestingMinExitFlagThreshold is,
- * then require bandwidthcapacity */
- return 0;
- }
- } else {
- /* If we're not in a TestingTorNetwork, then require bandwidthcapacity */
- return 0;
- }
- }
return 1;
}
diff --git a/src/feature/dirparse/microdesc_parse.c b/src/feature/dirparse/microdesc_parse.c
index beb38bda30..eef52f14f3 100644
--- a/src/feature/dirparse/microdesc_parse.c
+++ b/src/feature/dirparse/microdesc_parse.c
@@ -30,7 +30,7 @@
/** List of tokens recognized in microdescriptors */
// clang-format off
static token_rule_t microdesc_token_table[] = {
- T1_START("onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024),
+ T1_START("onion-key", K_ONION_KEY, NO_ARGS, OPT_KEY_1024),
T1("ntor-onion-key", K_ONION_KEY_NTOR, GE(1), NO_OBJ ),
T0N("id", K_ID, GE(2), NO_OBJ ),
T0N("a", K_A, GE(1), NO_OBJ ),
@@ -200,14 +200,11 @@ microdesc_parse_fields(microdesc_t *md,
}
tok = find_by_keyword(tokens, K_ONION_KEY);
- if (!crypto_pk_public_exponent_ok(tok->key)) {
+ if (tok && tok->key && !crypto_pk_public_exponent_ok(tok->key)) {
log_warn(LD_DIR,
"Relay's onion key had invalid exponent.");
goto err;
}
- md->onion_pkey = tor_memdup(tok->object_body, tok->object_size);
- md->onion_pkey_len = tok->object_size;
- crypto_pk_free(tok->key);
if ((tok = find_opt_by_keyword(tokens, K_ONION_KEY_NTOR))) {
curve25519_public_key_t k;
diff --git a/src/feature/dirparse/parsecommon.c b/src/feature/dirparse/parsecommon.c
index d7a6d65346..be1457b730 100644
--- a/src/feature/dirparse/parsecommon.c
+++ b/src/feature/dirparse/parsecommon.c
@@ -215,6 +215,16 @@ token_check_object(memarea_t *area, const char *kwd,
RET_ERR(ebuf);
}
break;
+ case OPT_KEY_1024:
+ /* If there is anything, it must be a 1024-bit RSA key. */
+ if (tok->object_body && !tok->key) {
+ tor_snprintf(ebuf, sizeof(ebuf), "Unexpected object for %s", kwd);
+ RET_ERR(ebuf);
+ }
+ if (!tok->key) {
+ break;
+ }
+ FALLTHROUGH;
case NEED_KEY_1024: /* There must be a 1024-bit public key. */
if (tok->key && crypto_pk_num_bits(tok->key) != PK_BYTES*8) {
tor_snprintf(ebuf, sizeof(ebuf), "Wrong size on key for %s: %d bits",
@@ -395,7 +405,8 @@ get_next_token(memarea_t *area,
}
if (!strcmp(tok->object_type, "RSA PUBLIC KEY")) { /* If it's a public key */
- if (o_syn != NEED_KEY && o_syn != NEED_KEY_1024 && o_syn != OBJ_OK) {
+ if (o_syn != OPT_KEY_1024 && o_syn != NEED_KEY &&
+ o_syn != NEED_KEY_1024 && o_syn != OBJ_OK) {
RET_ERR("Unexpected public key.");
}
tok->key = crypto_pk_asn1_decode(tok->object_body, tok->object_size);
diff --git a/src/feature/dirparse/parsecommon.h b/src/feature/dirparse/parsecommon.h
index 9333ec4b27..d48d27499f 100644
--- a/src/feature/dirparse/parsecommon.h
+++ b/src/feature/dirparse/parsecommon.h
@@ -220,6 +220,7 @@ typedef struct directory_token_t {
typedef enum {
NO_OBJ, /**< No object, ever. */
NEED_OBJ, /**< Object is required. */
+ OPT_KEY_1024, /**< If object is present, it must be a 1024 bit public key */
NEED_KEY_1024, /**< Object is required, and must be a 1024 bit public key */
NEED_KEY, /**< Object is required, and must be a public key. */
OBJ_OK, /**< Object is optional. */
diff --git a/src/feature/dirparse/routerparse.c b/src/feature/dirparse/routerparse.c
index 844057c47e..6289b4c018 100644
--- a/src/feature/dirparse/routerparse.c
+++ b/src/feature/dirparse/routerparse.c
@@ -90,7 +90,7 @@ const token_rule_t routerdesc_token_table[] = {
T1_START( "router", K_ROUTER, GE(5), NO_OBJ ),
T01("ipv6-policy", K_IPV6_POLICY, CONCAT_ARGS, NO_OBJ),
T1( "signing-key", K_SIGNING_KEY, NO_ARGS, NEED_KEY_1024 ),
- T1( "onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024 ),
+ T01("onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024 ),
T1("ntor-onion-key", K_ONION_KEY_NTOR, GE(1), NO_OBJ ),
T1_END( "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ ),
T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
@@ -107,7 +107,7 @@ const token_rule_t routerdesc_token_table[] = {
T1("identity-ed25519", K_IDENTITY_ED25519, NO_ARGS, NEED_OBJ ),
T1("master-key-ed25519", K_MASTER_KEY_ED25519, GE(1), NO_OBJ ),
T1("router-sig-ed25519", K_ROUTER_SIG_ED25519, GE(1), NO_OBJ ),
- T1("onion-key-crosscert", K_ONION_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ),
+ T01("onion-key-crosscert", K_ONION_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ),
T1("ntor-onion-key-crosscert", K_NTOR_ONION_KEY_CROSSCERT,
EQ(1), NEED_OBJ ),
@@ -595,15 +595,17 @@ router_parse_entry_from_string(const char *s, const char *end,
if (parse_iso_time(tok->args[0], &router->cache_info.published_on) < 0)
goto err;
- tok = find_by_keyword(tokens, K_ONION_KEY);
- if (!crypto_pk_public_exponent_ok(tok->key)) {
- log_warn(LD_DIR,
- "Relay's onion key had invalid exponent.");
- goto err;
+ tok = find_opt_by_keyword(tokens, K_ONION_KEY);
+ if (tok) {
+ if (!crypto_pk_public_exponent_ok(tok->key)) {
+ log_warn(LD_DIR,
+ "Relay's onion key had invalid exponent.");
+ goto err;
+ }
+ router->tap_onion_pkey = tor_memdup(tok->object_body, tok->object_size);
+ router->tap_onion_pkey_len = tok->object_size;
+ crypto_pk_free(tok->key);
}
- router->onion_pkey = tor_memdup(tok->object_body, tok->object_size);
- router->onion_pkey_len = tok->object_size;
- crypto_pk_free(tok->key);
if ((tok = find_opt_by_keyword(tokens, K_ONION_KEY_NTOR))) {
curve25519_public_key_t k;
@@ -627,26 +629,68 @@ router_parse_entry_from_string(const char *s, const char *end,
{
directory_token_t *ed_sig_tok, *ed_cert_tok, *cc_tap_tok, *cc_ntor_tok,
*master_key_tok;
- ed_sig_tok = find_opt_by_keyword(tokens, K_ROUTER_SIG_ED25519);
- ed_cert_tok = find_opt_by_keyword(tokens, K_IDENTITY_ED25519);
- master_key_tok = find_opt_by_keyword(tokens, K_MASTER_KEY_ED25519);
+ ed_sig_tok = find_by_keyword(tokens, K_ROUTER_SIG_ED25519);
+ ed_cert_tok = find_by_keyword(tokens, K_IDENTITY_ED25519);
+ master_key_tok = find_by_keyword(tokens, K_MASTER_KEY_ED25519);
+ cc_ntor_tok = find_by_keyword(tokens, K_NTOR_ONION_KEY_CROSSCERT);
+ /* This, and only this, is optional. */
cc_tap_tok = find_opt_by_keyword(tokens, K_ONION_KEY_CROSSCERT);
- cc_ntor_tok = find_opt_by_keyword(tokens, K_NTOR_ONION_KEY_CROSSCERT);
- int n_ed_toks = !!ed_sig_tok + !!ed_cert_tok +
- !!cc_tap_tok + !!cc_ntor_tok;
- if ((n_ed_toks != 0 && n_ed_toks != 4) ||
- (n_ed_toks == 4 && !router->onion_curve25519_pkey)) {
- log_warn(LD_DIR, "Router descriptor with only partial ed25519/"
- "cross-certification support");
+
+ if (bool_neq(cc_tap_tok==NULL, router->tap_onion_pkey==NULL)) {
+ log_warn(LD_DIR, "Router descriptor had only one of (onion-key, "
+ "onion-key-crosscert).");
goto err;
}
- if (master_key_tok && !ed_sig_tok) {
- log_warn(LD_DIR, "Router descriptor has ed25519 master key but no "
- "certificate");
+
+ IF_BUG_ONCE(! (ed_sig_tok && ed_cert_tok&& cc_ntor_tok &&master_key_tok)) {
goto err;
}
- if (ed_sig_tok) {
- tor_assert(ed_cert_tok && cc_tap_tok && cc_ntor_tok);
+
+ tor_cert_t *cert;
+ {
+ /* Parse the identity certificate */
+ cert = tor_cert_parse(
+ (const uint8_t*)ed_cert_tok->object_body,
+ ed_cert_tok->object_size);
+ if (! cert) {
+ log_warn(LD_DIR, "Couldn't parse ed25519 cert");
+ goto err;
+ }
+ /* makes sure it gets freed. */
+ router->cache_info.signing_key_cert = cert;
+
+ if (cert->cert_type != CERT_TYPE_ID_SIGNING ||
+ ! cert->signing_key_included) {
+ log_warn(LD_DIR, "Invalid form for ed25519 cert");
+ goto err;
+ }
+ }
+
+ if (cc_tap_tok) {
+ rsa_pubkey = router_get_rsa_onion_pkey(router->tap_onion_pkey,
+ router->tap_onion_pkey_len);
+ if (rsa_pubkey == NULL) {
+ log_warn(LD_DIR, "No pubkey for TAP cross-verification.");
+ goto err;
+ }
+ if (strcmp(cc_tap_tok->object_type, "CROSSCERT")) {
+ log_warn(LD_DIR, "Wrong object type on onion-key-crosscert "
+ "in descriptor");
+ goto err;
+ }
+ if (check_tap_onion_key_crosscert(
+ (const uint8_t*)cc_tap_tok->object_body,
+ (int)cc_tap_tok->object_size,
+ rsa_pubkey,
+ &cert->signing_key,
+ (const uint8_t*)router->cache_info.identity_digest)<0) {
+ log_warn(LD_DIR, "Incorrect TAP cross-verification");
+ goto err;
+ }
+ }
+
+ {
+ tor_assert(ed_sig_tok && ed_cert_tok && cc_ntor_tok);
const int ed_cert_token_pos = smartlist_pos(tokens, ed_cert_tok);
if (ed_cert_token_pos == -1 || router_token_pos == -1 ||
(ed_cert_token_pos != router_token_pos + 1 &&
@@ -668,35 +712,14 @@ router_parse_entry_from_string(const char *s, const char *end,
"in descriptor");
goto err;
}
- if (strcmp(cc_tap_tok->object_type, "CROSSCERT")) {
- log_warn(LD_DIR, "Wrong object type on onion-key-crosscert "
- "in descriptor");
- goto err;
- }
if (strcmp(cc_ntor_tok->args[0], "0") &&
strcmp(cc_ntor_tok->args[0], "1")) {
log_warn(LD_DIR, "Bad sign bit on ntor-onion-key-crosscert");
goto err;
}
int ntor_cc_sign_bit = !strcmp(cc_ntor_tok->args[0], "1");
-
uint8_t d256[DIGEST256_LEN];
const char *signed_start, *signed_end;
- tor_cert_t *cert = tor_cert_parse(
- (const uint8_t*)ed_cert_tok->object_body,
- ed_cert_tok->object_size);
- if (! cert) {
- log_warn(LD_DIR, "Couldn't parse ed25519 cert");
- goto err;
- }
- /* makes sure it gets freed. */
- router->cache_info.signing_key_cert = cert;
-
- if (cert->cert_type != CERT_TYPE_ID_SIGNING ||
- ! cert->signing_key_included) {
- log_warn(LD_DIR, "Invalid form for ed25519 cert");
- goto err;
- }
if (master_key_tok) {
/* This token is optional, but if it's present, it must match
@@ -746,6 +769,7 @@ router_parse_entry_from_string(const char *s, const char *end,
crypto_digest_add_bytes(d, ED_DESC_SIGNATURE_PREFIX,
strlen(ED_DESC_SIGNATURE_PREFIX));
crypto_digest_add_bytes(d, signed_start, signed_end-signed_start);
+
crypto_digest_get_digest(d, (char*)d256, sizeof(d256));
crypto_digest_free(d);
@@ -776,18 +800,6 @@ router_parse_entry_from_string(const char *s, const char *end,
goto err;
}
- rsa_pubkey = router_get_rsa_onion_pkey(router->onion_pkey,
- router->onion_pkey_len);
- if (check_tap_onion_key_crosscert(
- (const uint8_t*)cc_tap_tok->object_body,
- (int)cc_tap_tok->object_size,
- rsa_pubkey,
- &cert->signing_key,
- (const uint8_t*)router->cache_info.identity_digest)<0) {
- log_warn(LD_DIR, "Incorrect TAP cross-verification");
- goto err;
- }
-
/* We check this before adding it to the routerlist. */
router->cert_expiration_time = expires;
}
diff --git a/src/feature/hs/hs_common.c b/src/feature/hs/hs_common.c
index cd7e4890d1..e16ec89ccb 100644
--- a/src/feature/hs/hs_common.c
+++ b/src/feature/hs/hs_common.c
@@ -1686,7 +1686,7 @@ hs_get_extend_info_from_lspecs(const smartlist_t *lspecs,
/* We do have everything for which we think we can connect successfully. */
info = extend_info_new(NULL, legacy_id,
- (have_ed25519_id) ? &ed25519_pk : NULL, NULL,
+ (have_ed25519_id) ? &ed25519_pk : NULL,
onion_key, &ap.addr, ap.port, NULL, false);
done:
return info;
diff --git a/src/feature/hs/hs_service.c b/src/feature/hs/hs_service.c
index 3cc8c23e0b..3fb0220cc0 100644
--- a/src/feature/hs/hs_service.c
+++ b/src/feature/hs/hs_service.c
@@ -410,11 +410,6 @@ get_intro_point_max_introduce2(void)
static int32_t
get_intro_point_min_lifetime(void)
{
-#define MIN_INTRO_POINT_LIFETIME_TESTING 10
- if (get_options()->TestingTorNetwork) {
- return MIN_INTRO_POINT_LIFETIME_TESTING;
- }
-
/* The [0, 2147483647] range is quite large to accommodate anything we decide
* in the future. */
return networkstatus_get_param(NULL, "hs_intro_min_lifetime",
@@ -427,11 +422,6 @@ get_intro_point_min_lifetime(void)
static int32_t
get_intro_point_max_lifetime(void)
{
-#define MAX_INTRO_POINT_LIFETIME_TESTING 30
- if (get_options()->TestingTorNetwork) {
- return MAX_INTRO_POINT_LIFETIME_TESTING;
- }
-
/* The [0, 2147483647] range is quite large to accommodate anything we decide
* in the future. */
return networkstatus_get_param(NULL, "hs_intro_max_lifetime",
@@ -2163,7 +2153,7 @@ build_all_descriptors(time_t now)
continue;
}
- /* Reaching this point means we are pass bootup so at runtime. We should
+ /* Reaching this point means we are past bootup so at runtime. We should
* *never* have an empty current descriptor. If the next descriptor is
* empty, we'll try to build it for the next time period. This only
* happens when we rotate meaning that we are guaranteed to have a new SRV
@@ -2185,7 +2175,7 @@ build_all_descriptors(time_t now)
/** Randomly pick a node to become an introduction point but not present in the
* given exclude_nodes list. The chosen node is put in the exclude list
* regardless of success or not because in case of failure, the node is simply
- * unsusable from that point on.
+ * unusable from that point on.
*
* If direct_conn is set, try to pick a node that our local firewall/policy
* allows us to connect to directly. If we can't find any, return NULL.
@@ -3039,13 +3029,6 @@ get_max_intro_circ_per_period(const hs_service_t *service)
tor_assert(service->config.num_intro_points <=
HS_CONFIG_V3_MAX_INTRO_POINTS);
-/** For a testing network, allow to do it for the maximum amount so circuit
- * creation and rotation and so on can actually be tested without limit. */
-#define MAX_INTRO_POINT_CIRCUIT_RETRIES_TESTING -1
- if (get_options()->TestingTorNetwork) {
- return MAX_INTRO_POINT_CIRCUIT_RETRIES_TESTING;
- }
-
num_wanted_ip = service->config.num_intro_points;
/* The calculation is as follow. We have a number of intro points that we
diff --git a/src/feature/hs/hs_service.h b/src/feature/hs/hs_service.h
index 36d67719ca..b3a4117461 100644
--- a/src/feature/hs/hs_service.h
+++ b/src/feature/hs/hs_service.h
@@ -113,7 +113,7 @@ typedef struct hs_service_intropoints_t {
digest256map_t *map;
/** Contains node's identity key digest that were introduction point for this
- * descriptor but were retried to many times. We keep those so we avoid
+ * descriptor but were retried too many times. We keep those so we avoid
* re-picking them over and over for a circuit retry period.
* XXX: Once we have #22173, change this to only use ed25519 identity. */
digestmap_t *failed_id;
diff --git a/src/feature/nodelist/microdesc.c b/src/feature/nodelist/microdesc.c
index 9e5f0bb9a4..3fd0f23fb5 100644
--- a/src/feature/nodelist/microdesc.c
+++ b/src/feature/nodelist/microdesc.c
@@ -909,8 +909,6 @@ microdesc_free_(microdesc_t *md, const char *fname, int lineno)
//tor_assert(md->held_in_map == 0);
//tor_assert(md->held_by_nodes == 0);
- if (md->onion_pkey)
- tor_free(md->onion_pkey);
tor_free(md->onion_curve25519_pkey);
tor_free(md->ed25519_identity_pkey);
if (md->body && md->saved_location != SAVED_IN_CACHE)
diff --git a/src/feature/nodelist/microdesc_st.h b/src/feature/nodelist/microdesc_st.h
index ad56b6d6c2..c642e6e12b 100644
--- a/src/feature/nodelist/microdesc_st.h
+++ b/src/feature/nodelist/microdesc_st.h
@@ -63,14 +63,6 @@ struct microdesc_t {
/* Fields in the microdescriptor. */
- /**
- * Public RSA TAP key for onions, ASN.1 encoded. We store this
- * in its encoded format since storing it as a crypto_pk_t uses
- * significantly more memory. */
- char *onion_pkey;
- /** Length of onion_pkey, in bytes. */
- size_t onion_pkey_len;
-
/** As routerinfo_t.onion_curve25519_pkey */
struct curve25519_public_key_t *onion_curve25519_pkey;
/** Ed25519 identity key, if included. */
diff --git a/src/feature/nodelist/nodelist.c b/src/feature/nodelist/nodelist.c
index bbaa51a407..735361d417 100644
--- a/src/feature/nodelist/nodelist.c
+++ b/src/feature/nodelist/nodelist.c
@@ -2034,37 +2034,6 @@ node_get_curve25519_onion_key(const node_t *node)
return NULL;
}
-/* Return a newly allocacted RSA onion public key taken from the given node.
- *
- * Return NULL if node is NULL or no RSA onion public key can be found. It is
- * the caller responsibility to free the returned object. */
-crypto_pk_t *
-node_get_rsa_onion_key(const node_t *node)
-{
- crypto_pk_t *pk = NULL;
- const char *onion_pkey;
- size_t onion_pkey_len;
-
- if (!node) {
- goto end;
- }
-
- if (node->ri) {
- onion_pkey = node->ri->onion_pkey;
- onion_pkey_len = node->ri->onion_pkey_len;
- } else if (node->rs && node->md) {
- onion_pkey = node->md->onion_pkey;
- onion_pkey_len = node->md->onion_pkey_len;
- } else {
- /* No descriptor or microdescriptor. */
- goto end;
- }
- pk = router_get_rsa_onion_pkey(onion_pkey, onion_pkey_len);
-
- end:
- return pk;
-}
-
/** Refresh the country code of <b>ri</b>. This function MUST be called on
* each router when the GeoIP database is reloaded, and on all new routers. */
void
diff --git a/src/feature/nodelist/nodelist.h b/src/feature/nodelist/nodelist.h
index 3d5ad9c0ea..948a293f0c 100644
--- a/src/feature/nodelist/nodelist.h
+++ b/src/feature/nodelist/nodelist.h
@@ -109,7 +109,6 @@ void node_get_pref_ipv6_dirport(const node_t *node, tor_addr_port_t *ap_out);
int node_has_curve25519_onion_key(const node_t *node);
const struct curve25519_public_key_t *node_get_curve25519_onion_key(
const node_t *node);
-crypto_pk_t *node_get_rsa_onion_key(const node_t *node);
MOCK_DECL(const smartlist_t *, nodelist_get_list, (void));
diff --git a/src/feature/nodelist/routerinfo_st.h b/src/feature/nodelist/routerinfo_st.h
index 50134b2b96..a5c00c85c5 100644
--- a/src/feature/nodelist/routerinfo_st.h
+++ b/src/feature/nodelist/routerinfo_st.h
@@ -33,10 +33,13 @@ struct routerinfo_t {
/**
* Public RSA TAP key for onions, ASN.1 encoded. We store this
* in its encoded format since storing it as a crypto_pk_t uses
- * significantly more memory. */
- char *onion_pkey;
+ * significantly more memory.
+ *
+ * This may be absent.
+ */
+ char *tap_onion_pkey;
/** Length of onion_pkey, in bytes. */
- size_t onion_pkey_len;
+ size_t tap_onion_pkey_len;
crypto_pk_t *identity_pkey; /**< Public RSA key for signing. */
/** Public curve25519 key for onions */
diff --git a/src/feature/nodelist/routerlist.c b/src/feature/nodelist/routerlist.c
index 63de68dda7..7904f7d032 100644
--- a/src/feature/nodelist/routerlist.c
+++ b/src/feature/nodelist/routerlist.c
@@ -930,8 +930,8 @@ routerinfo_free_(routerinfo_t *router)
tor_free(router->platform);
tor_free(router->protocol_list);
tor_free(router->contact_info);
- if (router->onion_pkey)
- tor_free(router->onion_pkey);
+ if (router->tap_onion_pkey)
+ tor_free(router->tap_onion_pkey);
tor_free(router->onion_curve25519_pkey);
if (router->identity_pkey)
crypto_pk_free(router->identity_pkey);
@@ -2957,6 +2957,24 @@ router_reset_descriptor_download_failures(void)
/** We allow uptime to vary from how much it ought to be by this much. */
#define ROUTER_ALLOW_UPTIME_DRIFT (6*60*60)
+/** Return true iff r1 and r2 have the same TAP onion keys. */
+static int
+router_tap_onion_keys_eq(const routerinfo_t *r1, const routerinfo_t *r2)
+{
+ if (r1->tap_onion_pkey_len != r2->tap_onion_pkey_len)
+ return 0;
+
+ if ((r1->tap_onion_pkey == NULL) && (r2->tap_onion_pkey == NULL)) {
+ return 1;
+ } else if ((r1->tap_onion_pkey != NULL) && (r2->tap_onion_pkey != NULL)) {
+ return tor_memeq(r1->tap_onion_pkey, r2->tap_onion_pkey,
+ r1->tap_onion_pkey_len);
+ } else {
+ /* One is NULL; one is not. */
+ return 0;
+ }
+}
+
/** Return true iff the only differences between r1 and r2 are such that
* would not cause a recent (post 0.1.1.6) dirserver to republish.
*/
@@ -2982,8 +3000,7 @@ router_differences_are_cosmetic(const routerinfo_t *r1, const routerinfo_t *r2)
r1->ipv6_orport != r2->ipv6_orport ||
r1->ipv4_dirport != r2->ipv4_dirport ||
r1->purpose != r2->purpose ||
- r1->onion_pkey_len != r2->onion_pkey_len ||
- !tor_memeq(r1->onion_pkey, r2->onion_pkey, r1->onion_pkey_len) ||
+ !router_tap_onion_keys_eq(r1,r2) ||
!crypto_pk_eq_keys(r1->identity_pkey, r2->identity_pkey) ||
strcasecmp(r1->platform, r2->platform) ||
(r1->contact_info && !r2->contact_info) || /* contact_info is optional */
diff --git a/src/feature/relay/circuitbuild_relay.c b/src/feature/relay/circuitbuild_relay.c
index ce6cbe6df4..5ece5b4adc 100644
--- a/src/feature/relay/circuitbuild_relay.c
+++ b/src/feature/relay/circuitbuild_relay.c
@@ -389,7 +389,6 @@ circuit_open_connection_for_extend(const struct extend_cell_t *ec,
circ->n_hop = extend_info_new(NULL /*nickname*/,
(const char*)ec->node_id,
&ec->ed_pubkey,
- NULL, /*onion_key*/
NULL, /*curve25519_key*/
&chosen_ap->addr,
chosen_ap->port,
@@ -443,6 +442,12 @@ circuit_extend(struct cell_t *cell, struct circuit_t *circ)
relay_header_unpack(&rh, cell->payload);
+ /* We no longer accept EXTEND messages; only EXTEND2. */
+ if (rh.command == RELAY_COMMAND_EXTEND) {
+ /* TODO: Should we log this? */
+ return -1;
+ }
+
if (extend_cell_parse(&ec, rh.command,
cell->payload+RELAY_HEADER_SIZE,
rh.length) < 0) {
diff --git a/src/feature/relay/dns.c b/src/feature/relay/dns.c
index f6a020d061..eb31678189 100644
--- a/src/feature/relay/dns.c
+++ b/src/feature/relay/dns.c
@@ -563,6 +563,12 @@ send_resolved_cell,(edge_connection_t *conn, uint8_t answer_type,
connection_edge_send_command(conn, RELAY_COMMAND_RESOLVED, buf, buflen);
}
+void
+dns_send_resolved_error_cell(edge_connection_t *conn, uint8_t answer_type)
+{
+ send_resolved_cell(conn, answer_type, NULL);
+}
+
/** Send a response to the RESOLVE request of a connection for an in-addr.arpa
* address on connection <b>conn</b> which yielded the result <b>hostname</b>.
* The answer type will be RESOLVED_HOSTNAME.
@@ -1178,8 +1184,8 @@ dns_found_answer(const char *address, uint8_t query_type,
* resolution.
*
* Do this by sending a RELAY_RESOLVED cell (if the pending stream had sent us
- * RELAY_RESOLVE cell), or by launching an exit connection (if the pending
- * stream had send us a RELAY_BEGIN cell).
+ * a RELAY_RESOLVE cell), or by launching an exit connection (if the pending
+ * stream had sent us a RELAY_BEGIN cell).
*/
static void
inform_pending_connections(cached_resolve_t *resolve)
diff --git a/src/feature/relay/dns.h b/src/feature/relay/dns.h
index 3f8519bd97..5de70039d4 100644
--- a/src/feature/relay/dns.h
+++ b/src/feature/relay/dns.h
@@ -20,6 +20,8 @@ int dns_reset(void);
void connection_dns_remove(edge_connection_t *conn);
void assert_connection_edge_not_dns_pending(edge_connection_t *conn);
int dns_resolve(edge_connection_t *exitconn);
+void dns_send_resolved_error_cell(edge_connection_t *conn,
+ uint8_t answer_type);
int dns_seems_to_be_broken(void);
int dns_seems_to_be_broken_for_ipv6(void);
void dns_reset_correctness_checks(void);
@@ -36,6 +38,8 @@ void dns_launch_correctness_checks(void);
#else /* !defined(HAVE_MODULE_RELAY) */
#define dns_init() (0)
+#define dns_send_resolved_error_cell(conn, answer_type) \
+ ((void)(conn), (void)(answer_type))
#define dns_seems_to_be_broken() (0)
#define has_dns_init_failed() (0)
#define dns_cache_total_allocation() (0)
diff --git a/src/feature/relay/onion_queue.c b/src/feature/relay/onion_queue.c
index f3f4b169f4..9632b51063 100644
--- a/src/feature/relay/onion_queue.c
+++ b/src/feature/relay/onion_queue.c
@@ -50,10 +50,6 @@
#define ONION_QUEUE_MAX_DELAY_MIN 1
#define ONION_QUEUE_MAX_DELAY_MAX INT32_MAX
-#define NUM_NTORS_PER_TAP_DEFAULT 10
-#define NUM_NTORS_PER_TAP_MIN 1
-#define NUM_NTORS_PER_TAP_MAX 100000
-
/** Type for a linked list of circuits that are waiting for a free CPU worker
* to process a waiting onion handshake. */
typedef struct onion_queue_t {
@@ -84,17 +80,9 @@ static int ol_entries[MAX_QUEUE_IDX+1];
static void onion_queue_entry_remove(onion_queue_t *victim);
/** Consensus parameters. */
-static int32_t ns_num_ntors_per_tap = NUM_NTORS_PER_TAP_DEFAULT;
static time_t ns_onion_queue_wait_cutoff = ONION_QUEUE_WAIT_CUTOFF_DEFAULT;
static uint32_t ns_onion_queue_max_delay = ONION_QUEUE_MAX_DELAY_DEFAULT;
-/** Return the number of ntors per tap from the cached parameter. */
-static inline int32_t
-get_num_ntors_per_tap(void)
-{
- return ns_num_ntors_per_tap;
-}
-
/** Return the onion queue wait cutoff value from the cached parameter. */
static inline time_t
get_onion_queue_wait_cutoff(void)
@@ -146,8 +134,12 @@ have_room_for_onionskin(uint16_t type)
const or_options_t *options = get_options();
int num_cpus;
uint64_t max_onion_queue_delay;
- uint64_t tap_usec, ntor_usec;
- uint64_t ntor_during_tap_usec, tap_during_ntor_usec;
+ uint64_t ntor_usec;
+
+ /* We never allow TAP. */
+ if (type == ONION_HANDSHAKE_TYPE_TAP) {
+ return 0;
+ }
/* If we've got fewer than 50 entries, we always have room for one more. */
if (ol_entries[type] < 50)
@@ -164,44 +156,15 @@ have_room_for_onionskin(uint16_t type)
/* Compute how many microseconds we'd expect to need to clear all
* onionskins in various combinations of the queues. */
- /* How long would it take to process all the TAP cells in the queue? */
- tap_usec = estimated_usec_for_onionskins(
- ol_entries[ONION_HANDSHAKE_TYPE_TAP],
- ONION_HANDSHAKE_TYPE_TAP) / num_cpus;
-
/* How long would it take to process all the NTor cells in the queue? */
ntor_usec = estimated_usec_for_onionskins(
ol_entries[ONION_HANDSHAKE_TYPE_NTOR],
ONION_HANDSHAKE_TYPE_NTOR) / num_cpus;
- /* How long would it take to process the tap cells that we expect to
- * process while draining the ntor queue? */
- tap_during_ntor_usec = estimated_usec_for_onionskins(
- MIN(ol_entries[ONION_HANDSHAKE_TYPE_TAP],
- ol_entries[ONION_HANDSHAKE_TYPE_NTOR] / get_num_ntors_per_tap()),
- ONION_HANDSHAKE_TYPE_TAP) / num_cpus;
-
- /* How long would it take to process the ntor cells that we expect to
- * process while draining the tap queue? */
- ntor_during_tap_usec = estimated_usec_for_onionskins(
- MIN(ol_entries[ONION_HANDSHAKE_TYPE_NTOR],
- ol_entries[ONION_HANDSHAKE_TYPE_TAP] * get_num_ntors_per_tap()),
- ONION_HANDSHAKE_TYPE_NTOR) / num_cpus;
-
/* See whether that exceeds MaxOnionQueueDelay. If so, we can't queue
* this. */
if (type == ONION_HANDSHAKE_TYPE_NTOR &&
- (ntor_usec + tap_during_ntor_usec) / 1000 > max_onion_queue_delay)
- return 0;
-
- if (type == ONION_HANDSHAKE_TYPE_TAP &&
- (tap_usec + ntor_during_tap_usec) / 1000 > max_onion_queue_delay)
- return 0;
-
- /* If we support the ntor handshake, then don't let TAP handshakes use
- * more than 2/3 of the space on the queue. */
- if (type == ONION_HANDSHAKE_TYPE_TAP &&
- tap_usec / 1000 > max_onion_queue_delay * 2 / 3)
+ (ntor_usec / 1000) > max_onion_queue_delay)
return 0;
return 1;
@@ -292,38 +255,7 @@ onion_pending_add(or_circuit_t *circ, create_cell_t *onionskin)
static uint16_t
decide_next_handshake_type(void)
{
- /* The number of times we've chosen ntor lately when both were available. */
- static int recently_chosen_ntors = 0;
-
- if (!ol_entries[ONION_HANDSHAKE_TYPE_NTOR])
- return ONION_HANDSHAKE_TYPE_TAP; /* no ntors? try tap */
-
- if (!ol_entries[ONION_HANDSHAKE_TYPE_TAP]) {
-
- /* Nick wants us to prioritize new tap requests when there aren't
- * any in the queue and we've processed k ntor cells since the last
- * tap cell. This strategy is maybe a good idea, since it starves tap
- * less in the case where tap is rare, or maybe a poor idea, since it
- * makes the new tap cell unfairly jump in front of ntor cells that
- * got here first. In any case this edge case will only become relevant
- * once tap is rare. We should reevaluate whether we like this decision
- * once tap gets more rare. */
- if (ol_entries[ONION_HANDSHAKE_TYPE_NTOR] &&
- recently_chosen_ntors <= get_num_ntors_per_tap())
- ++recently_chosen_ntors;
-
- return ONION_HANDSHAKE_TYPE_NTOR; /* no taps? try ntor */
- }
-
- /* They both have something queued. Pick ntor if we haven't done that
- * too much lately. */
- if (++recently_chosen_ntors <= get_num_ntors_per_tap()) {
- return ONION_HANDSHAKE_TYPE_NTOR;
- }
-
- /* Else, it's time to let tap have its turn. */
- recently_chosen_ntors = 0;
- return ONION_HANDSHAKE_TYPE_TAP;
+ return ONION_HANDSHAKE_TYPE_NTOR;
}
/** Remove the highest priority item from ol_list[] and return it, or
@@ -445,10 +377,4 @@ onion_consensus_has_changed(const networkstatus_t *ns)
ONION_QUEUE_WAIT_CUTOFF_DEFAULT,
ONION_QUEUE_WAIT_CUTOFF_MIN,
ONION_QUEUE_WAIT_CUTOFF_MAX);
-
- ns_num_ntors_per_tap =
- networkstatus_get_param(ns, "NumNTorsPerTAP",
- NUM_NTORS_PER_TAP_DEFAULT,
- NUM_NTORS_PER_TAP_MIN,
- NUM_NTORS_PER_TAP_MAX);
}
diff --git a/src/feature/relay/relay_config.c b/src/feature/relay/relay_config.c
index 0b02461318..320ce8d13a 100644
--- a/src/feature/relay/relay_config.c
+++ b/src/feature/relay/relay_config.c
@@ -1151,8 +1151,8 @@ options_validate_relay_mode(const or_options_t *old_options,
REJECT("BridgeRelay is 1, ORPort is not set. This is an invalid "
"combination.");
- if (options->BridgeRelay == 1 && (options->ExitRelay == 1 ||
- !policy_using_default_exit_options(options))) {
+ if (options->BridgeRelay == 1 && !(options->ExitRelay == 0 ||
+ policy_using_default_exit_options(options))) {
log_warn(LD_CONFIG, "BridgeRelay is 1, but ExitRelay is 1 or an "
"ExitPolicy is configured. Tor will start, but it will not "
"function as an exit relay.");
diff --git a/src/feature/relay/relay_metrics.c b/src/feature/relay/relay_metrics.c
index 8f3b82bd96..492a5945b8 100644
--- a/src/feature/relay/relay_metrics.c
+++ b/src/feature/relay/relay_metrics.c
@@ -13,6 +13,7 @@
#include "core/or/or.h"
#include "core/mainloop/connection.h"
#include "core/mainloop/mainloop.h"
+#include "core/or/command.h"
#include "core/or/congestion_control_common.h"
#include "core/or/congestion_control_vegas.h"
#include "core/or/congestion_control_flow.h"
@@ -54,6 +55,9 @@ static void fill_socket_values(void);
static void fill_onionskins_values(void);
static void fill_oom_values(void);
static void fill_streams_values(void);
+static void fill_relay_circ_proto_violation(void);
+static void fill_relay_destroy_cell(void);
+static void fill_relay_drop_cell(void);
static void fill_relay_flags(void);
static void fill_tcp_exhaustion_values(void);
static void fill_traffic_values(void);
@@ -217,6 +221,27 @@ static const relay_metrics_entry_t base_metrics[] =
.help = "Total number of REND1 cells we received",
.fill_fn = fill_rend1_cells,
},
+ {
+ .key = RELAY_METRICS_CIRC_DESTROY_CELL,
+ .type = METRICS_TYPE_COUNTER,
+ .name = METRICS_NAME(relay_destroy_cell_total),
+ .help = "Total number of DESTROY cell we received",
+ .fill_fn = fill_relay_destroy_cell,
+ },
+ {
+ .key = RELAY_METRICS_CIRC_PROTO_VIOLATION,
+ .type = METRICS_TYPE_COUNTER,
+ .name = METRICS_NAME(relay_circ_proto_violation_total),
+ .help = "Total number of circuit protocol violation",
+ .fill_fn = fill_relay_circ_proto_violation,
+ },
+ {
+ .key = RELAY_METRICS_CIRC_DROP_CELL,
+ .type = METRICS_TYPE_COUNTER,
+ .name = METRICS_NAME(relay_drop_cell_total),
+ .help = "Total number of DROP cell we received",
+ .fill_fn = fill_relay_drop_cell,
+ },
};
static const size_t num_base_metrics = ARRAY_LENGTH(base_metrics);
@@ -433,6 +458,12 @@ fill_dos_values(void)
metrics_store_entry_add_label(sentry,
metrics_format_label("type", "introduce2_rejected"));
metrics_store_entry_update(sentry, hs_dos_get_intro2_rejected_count());
+
+ sentry = metrics_store_add(the_store, rentry->type, rentry->name,
+ rentry->help, 0, NULL);
+ metrics_store_entry_add_label(sentry,
+ metrics_format_label("type", "stream_rejected"));
+ metrics_store_entry_update(sentry, dos_get_num_stream_rejected());
}
/** Fill function for the RELAY_METRICS_CC_COUNTERS metric. */
@@ -1200,6 +1231,46 @@ fill_rend1_cells(void)
}
}
+/** Fill the metrics store for the RELAY_METRICS_CIRC_DESTROY_CELL counter. */
+static void
+fill_relay_destroy_cell(void)
+{
+ metrics_store_entry_t *sentry;
+ const relay_metrics_entry_t *rentry =
+ &base_metrics[RELAY_METRICS_CIRC_DESTROY_CELL];
+
+ sentry = metrics_store_add(the_store, rentry->type, rentry->name,
+ rentry->help, 0, NULL);
+ metrics_store_entry_update(sentry,
+ (int64_t) stats_n_destroy_cells_processed);
+}
+
+/** Fill the metrics store for the RELAY_METRICS_CIRC_DROP_CELL counter. */
+static void
+fill_relay_drop_cell(void)
+{
+ metrics_store_entry_t *sentry;
+ const relay_metrics_entry_t *rentry =
+ &base_metrics[RELAY_METRICS_CIRC_DROP_CELL];
+
+ sentry = metrics_store_add(the_store, rentry->type, rentry->name,
+ rentry->help, 0, NULL);
+ metrics_store_entry_update(sentry, rep_hist_get_drop_cell_received_count());
+}
+
+/** Fill the metrics store for the RELAY_METRICS_CIRC_PROTO_VIOLATION. */
+static void
+fill_relay_circ_proto_violation(void)
+{
+ metrics_store_entry_t *sentry;
+ const relay_metrics_entry_t *rentry =
+ &base_metrics[RELAY_METRICS_CIRC_PROTO_VIOLATION];
+
+ sentry = metrics_store_add(the_store, rentry->type, rentry->name,
+ rentry->help, 0, NULL);
+ metrics_store_entry_update(sentry, circ_n_proto_violation);
+}
+
/** Reset the global store and fill it with all the metrics from base_metrics
* and their associated values.
*
diff --git a/src/feature/relay/relay_metrics.h b/src/feature/relay/relay_metrics.h
index cf9dddf955..e7b5b660fa 100644
--- a/src/feature/relay/relay_metrics.h
+++ b/src/feature/relay/relay_metrics.h
@@ -57,6 +57,12 @@ typedef enum {
RELAY_METRICS_NUM_INTRO1_CELLS,
/** Number of times we received a REND1 cell */
RELAY_METRICS_NUM_REND1_CELLS,
+ /** Number of circuit closed by receiving a DESTROY cell. */
+ RELAY_METRICS_CIRC_DESTROY_CELL,
+ /** Number of circuits closed due to protocol violation. */
+ RELAY_METRICS_CIRC_PROTO_VIOLATION,
+ /** Number of drop cell seen. */
+ RELAY_METRICS_CIRC_DROP_CELL,
} relay_metrics_key_t;
/** The metadata of a relay metric. */
diff --git a/src/feature/relay/router.c b/src/feature/relay/router.c
index 1ed9630e09..ab5fe697bc 100644
--- a/src/feature/relay/router.c
+++ b/src/feature/relay/router.c
@@ -211,8 +211,13 @@ set_onion_key(crypto_pk_t *k)
mark_my_descriptor_dirty("set onion key");
}
-/** Return the current onion key. Requires that the onion key has been
- * loaded or generated. */
+/** Return the current TAP onion key. Requires that the onion key has been
+ * loaded or generated.
+ *
+ * Note that this key is no longer used for anything; we only keep it around
+ * because (as of June 2024) other Tor instances all expect to find it in
+ * our routerdescs.
+ **/
MOCK_IMPL(crypto_pk_t *,
get_onion_key,(void))
{
@@ -220,6 +225,25 @@ get_onion_key,(void))
return onionkey;
}
+/**
+ * Return true iff we should include our TAP onion key in our router
+ * descriptor.
+ */
+static int
+should_publish_tap_onion_key(void)
+{
+#define SHOULD_PUBLISH_TAP_MIN 0
+#define SHOULD_PUBLISH_TAP_MAX 1
+ /* Note that we err on the side of publishing. */
+#define SHOULD_PUBLISH_TAP_DFLT 1
+
+ return networkstatus_get_param(NULL,
+ "publish-dummy-tap-key",
+ SHOULD_PUBLISH_TAP_DFLT,
+ SHOULD_PUBLISH_TAP_MIN,
+ SHOULD_PUBLISH_TAP_MAX);
+}
+
/** Store a full copy of the current onion key into *<b>key</b>, and a full
* copy of the most recent onion key into *<b>last</b>. Store NULL into
* a pointer if the corresponding key does not exist.
@@ -2138,9 +2162,12 @@ router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out))
ri->supports_tunnelled_dir_requests =
directory_permits_begindir_requests(options);
ri->cache_info.published_on = time(NULL);
- /* get_onion_key() must invoke from main thread */
- router_set_rsa_onion_pkey(get_onion_key(), &ri->onion_pkey,
- &ri->onion_pkey_len);
+
+ if (should_publish_tap_onion_key()) {
+ /* get_onion_key() must invoke from main thread */
+ router_set_rsa_onion_pkey(get_onion_key(), &ri->tap_onion_pkey,
+ &ri->tap_onion_pkey_len);
+ }
ri->onion_curve25519_pkey =
tor_memdup(&get_current_curve25519_keypair()->pubkey,
@@ -2777,7 +2804,7 @@ router_dump_router_to_string(routerinfo_t *router,
char published[ISO_TIME_LEN+1];
char fingerprint[FINGERPRINT_LEN+1];
char *extra_info_line = NULL;
- size_t onion_pkeylen, identity_pkeylen;
+ size_t onion_pkeylen=0, identity_pkeylen;
char *family_line = NULL;
char *extra_or_address = NULL;
const or_options_t *options = get_options();
@@ -2835,12 +2862,14 @@ router_dump_router_to_string(routerinfo_t *router,
}
/* PEM-encode the onion key */
- rsa_pubkey = router_get_rsa_onion_pkey(router->onion_pkey,
- router->onion_pkey_len);
- if (crypto_pk_write_public_key_to_string(rsa_pubkey,
- &onion_pkey,&onion_pkeylen)<0) {
- log_warn(LD_BUG,"write onion_pkey to string failed!");
- goto err;
+ rsa_pubkey = router_get_rsa_onion_pkey(router->tap_onion_pkey,
+ router->tap_onion_pkey_len);
+ if (rsa_pubkey) {
+ if (crypto_pk_write_public_key_to_string(rsa_pubkey,
+ &onion_pkey,&onion_pkeylen)<0) {
+ log_warn(LD_BUG,"write onion_pkey to string failed!");
+ goto err;
+ }
}
/* PEM-encode the identity key */
@@ -2851,7 +2880,7 @@ router_dump_router_to_string(routerinfo_t *router,
}
/* Cross-certify with RSA key */
- if (tap_key && router->cache_info.signing_key_cert &&
+ if (tap_key && rsa_pubkey && router->cache_info.signing_key_cert &&
router->cache_info.signing_key_cert->signing_key_included) {
char buf[256];
int tap_cc_len = 0;
@@ -2976,7 +3005,7 @@ router_dump_router_to_string(routerinfo_t *router,
"uptime %ld\n"
"bandwidth %d %d %d\n"
"%s%s"
- "onion-key\n%s"
+ "%s%s"
"signing-key\n%s"
"%s%s"
"%s%s%s",
@@ -2997,7 +3026,8 @@ router_dump_router_to_string(routerinfo_t *router,
extra_info_line ? extra_info_line : "",
(options->DownloadExtraInfo || options->V3AuthoritativeDir) ?
"caches-extra-info\n" : "",
- onion_pkey, identity_pkey,
+ onion_pkey?"onion-key\n":"", onion_pkey?onion_pkey:"",
+ identity_pkey,
rsa_tap_cc_line ? rsa_tap_cc_line : "",
ntor_cc_line ? ntor_cc_line : "",
family_line,
diff --git a/src/feature/relay/selftest.c b/src/feature/relay/selftest.c
index 399b6bca6e..0a80a5d47e 100644
--- a/src/feature/relay/selftest.c
+++ b/src/feature/relay/selftest.c
@@ -201,7 +201,6 @@ have_orport_for_family(int family)
static extend_info_t *
extend_info_from_router(const routerinfo_t *r, int family)
{
- crypto_pk_t *rsa_pubkey;
extend_info_t *info;
tor_addr_port_t ap;
@@ -224,15 +223,14 @@ extend_info_from_router(const routerinfo_t *r, int family)
/* We don't have an ORPort for the requested family. */
return NULL;
}
- rsa_pubkey = router_get_rsa_onion_pkey(r->onion_pkey, r->onion_pkey_len);
info = extend_info_new(r->nickname, r->cache_info.identity_digest,
ed_id_key,
- rsa_pubkey, r->onion_curve25519_pkey,
+ r->onion_curve25519_pkey,
&ap.addr, ap.port,
/* TODO-324: Should self-test circuits use
* congestion control? */
NULL, false);
- crypto_pk_free(rsa_pubkey);
+
return info;
}
diff --git a/src/feature/stats/rephist.c b/src/feature/stats/rephist.c
index 8f4f33151a..055081fc7c 100644
--- a/src/feature/stats/rephist.c
+++ b/src/feature/stats/rephist.c
@@ -280,6 +280,9 @@ static dns_stats_t dns_AAAA_stats;
/** DNS query statistics store. It covers all type of queries. */
static dns_stats_t dns_all_stats;
+/** Counter of the total number of DROP cell received. */
+static uint64_t relay_circ_n_drop_cell_received = 0;
+
/** Return the point to the DNS statistics store. Ignore the type for now
* because of a libevent problem. */
static inline dns_stats_t *
@@ -2290,19 +2293,14 @@ typedef struct {
/** Keep track of the onionskin requests for an assessment period. */
static overload_onionskin_assessment_t overload_onionskin_assessment;
-/**
- * We combine ntorv3 and ntor into the same stat, so we must
- * use this function to convert the cell type to a stat index.
+/** This function ensures that we clamp the maximum value of the given input
+ * <b>type</b> to NTOR in case the input is out of range.
*/
static inline uint16_t
onionskin_type_to_stat(uint16_t type)
{
- if (type == ONION_HANDSHAKE_TYPE_NTOR_V3) {
- return ONION_HANDSHAKE_TYPE_NTOR;
- }
-
if (BUG(type > MAX_ONION_STAT_TYPE)) {
- return MAX_ONION_STAT_TYPE; // use ntor if out of range
+ return MAX_ONION_STAT_TYPE; // use ntor_v3 if out of range
}
return type;
@@ -2371,7 +2369,8 @@ rep_hist_note_circuit_handshake_requested(uint16_t type)
onion_handshakes_requested[stat]++;
/* Only relays get to record requested onionskins. */
- if (stat == ONION_HANDSHAKE_TYPE_NTOR) {
+ if (stat == ONION_HANDSHAKE_TYPE_NTOR ||
+ stat == ONION_HANDSHAKE_TYPE_NTOR_V3) {
/* Assess if we've reached the overload general signal. */
overload_general_onionskin_assessment();
@@ -2398,7 +2397,8 @@ rep_hist_note_circuit_handshake_dropped(uint16_t type)
stats_n_onionskin_dropped[stat]++;
/* Only relays get to record requested onionskins. */
- if (stat == ONION_HANDSHAKE_TYPE_NTOR) {
+ if (stat == ONION_HANDSHAKE_TYPE_NTOR ||
+ stat == ONION_HANDSHAKE_TYPE_NTOR_V3) {
/* Note the dropped ntor in the overload assessment object. */
overload_onionskin_assessment.n_ntor_dropped++;
}
@@ -2438,11 +2438,13 @@ rep_hist_log_circuit_handshake_stats(time_t now)
{
(void)now;
log_notice(LD_HEARTBEAT, "Circuit handshake stats since last time: "
- "%d/%d TAP, %d/%d NTor.",
+ "%d/%d TAP, %d/%d NTor, %d/%d NTor (v3).",
onion_handshakes_assigned[ONION_HANDSHAKE_TYPE_TAP],
onion_handshakes_requested[ONION_HANDSHAKE_TYPE_TAP],
onion_handshakes_assigned[ONION_HANDSHAKE_TYPE_NTOR],
- onion_handshakes_requested[ONION_HANDSHAKE_TYPE_NTOR]);
+ onion_handshakes_requested[ONION_HANDSHAKE_TYPE_NTOR],
+ onion_handshakes_assigned[ONION_HANDSHAKE_TYPE_NTOR_V3],
+ onion_handshakes_requested[ONION_HANDSHAKE_TYPE_NTOR_V3]);
memset(onion_handshakes_assigned, 0, sizeof(onion_handshakes_assigned));
memset(onion_handshakes_requested, 0, sizeof(onion_handshakes_requested));
}
@@ -2816,6 +2818,8 @@ rep_hist_padding_count_write(padding_type_t type)
switch (type) {
case PADDING_TYPE_DROP:
padding_current.write_drop_cell_count++;
+ /* Padding stats get reset thus why we have two counters. */
+ relay_circ_n_drop_cell_received++;
break;
case PADDING_TYPE_CELL:
padding_current.write_pad_cell_count++;
@@ -3023,6 +3027,13 @@ rep_hist_consensus_has_changed(const networkstatus_t *ns)
OVERLOAD_ONIONSKIN_NTOR_PERIOD_SECS_MAX);
}
+/** Relay Only: return the total number of DROP cell received. */
+uint64_t
+rep_hist_get_drop_cell_received_count(void)
+{
+ return relay_circ_n_drop_cell_received;
+}
+
#ifdef TOR_UNIT_TESTS
/* only exists for unit tests: get HSv2 stats object */
const hs_v2_stats_t *
diff --git a/src/feature/stats/rephist.h b/src/feature/stats/rephist.h
index fbfab4c451..f595459580 100644
--- a/src/feature/stats/rephist.h
+++ b/src/feature/stats/rephist.h
@@ -102,8 +102,8 @@ void rep_hist_note_dns_error(int type, uint8_t error);
void rep_hist_consensus_has_changed(const networkstatus_t *ns);
/** We combine ntor and ntorv3 stats, so we have 3 stat types:
- * tap, fast, and ntor. The max type is ntor (2) */
-#define MAX_ONION_STAT_TYPE ONION_HANDSHAKE_TYPE_NTOR
+ * tap, fast, and ntor. The max type is ntor_v3 (3) */
+#define MAX_ONION_STAT_TYPE MAX_ONION_HANDSHAKE_TYPE
extern uint64_t rephist_total_alloc;
extern uint32_t rephist_total_num;
@@ -192,6 +192,8 @@ uint64_t rep_hist_get_n_tcp_exhaustion(void);
uint64_t rep_hist_get_n_read_limit_reached(void);
uint64_t rep_hist_get_n_write_limit_reached(void);
+uint64_t rep_hist_get_drop_cell_received_count(void);
+
#ifdef TOR_UNIT_TESTS
struct hs_v2_stats_t;
const struct hs_v2_stats_t *rep_hist_get_hs_v2_stats(void);
diff --git a/src/lib/crypt_ops/crypto_openssl_mgt.c b/src/lib/crypt_ops/crypto_openssl_mgt.c
index 6c01cb6aa8..ca12a82518 100644
--- a/src/lib/crypt_ops/crypto_openssl_mgt.c
+++ b/src/lib/crypt_ops/crypto_openssl_mgt.c
@@ -40,6 +40,11 @@ ENABLE_GCC_WARNING("-Wredundant-decls")
#include <string.h>
+#ifdef OPENSSL_NO_ENGINE
+/* Android's OpenSSL seems to have removed all of its Engine support. */
+#define DISABLE_ENGINES
+#endif
+
#ifndef NEW_THREAD_API
/** A number of preallocated mutexes for use by OpenSSL. */
static tor_mutex_t **openssl_mutexes_ = NULL;
diff --git a/src/lib/crypt_ops/crypto_openssl_mgt.h b/src/lib/crypt_ops/crypto_openssl_mgt.h
index 96a37721dd..eac0ec1977 100644
--- a/src/lib/crypt_ops/crypto_openssl_mgt.h
+++ b/src/lib/crypt_ops/crypto_openssl_mgt.h
@@ -49,11 +49,6 @@
#define OPENSSL_V_SERIES(a,b,c) \
OPENSSL_VER((a),(b),(c),0,0)
-#ifdef OPENSSL_NO_ENGINE
-/* Android's OpenSSL seems to have removed all of its Engine support. */
-#define DISABLE_ENGINES
-#endif
-
#if OPENSSL_VERSION_NUMBER >= OPENSSL_VER(1,1,0,0,5)
/* OpenSSL as of 1.1.0pre4 has an "new" thread API, which doesn't require
* setting up various callbacks.
diff --git a/src/lib/fs/files.c b/src/lib/fs/files.c
index 55f20dd49e..914a8b8e72 100644
--- a/src/lib/fs/files.c
+++ b/src/lib/fs/files.c
@@ -85,7 +85,8 @@ tor_open_cloexec(const char *path, int flags, unsigned mode)
FILE *
tor_fopen_cloexec(const char *path, const char *mode)
{
- FILE *result = fopen(path, mode);
+ const char *p = sandbox_intern_string(path);
+ FILE *result = fopen(p, mode);
#ifdef FD_CLOEXEC
if (result != NULL) {
if (fcntl(fileno(result), F_SETFD, FD_CLOEXEC) == -1) {
@@ -572,9 +573,10 @@ write_bytes_to_new_file(const char *fname, const char *str, size_t len,
/**
* Read the contents of the open file <b>fd</b> presuming it is a FIFO
* (or similar) file descriptor for which the size of the file isn't
- * known ahead of time. Return NULL on failure, and a NUL-terminated
- * string on success. On success, set <b>sz_out</b> to the number of
- * bytes read.
+ * known ahead of time.
+ * Return NULL on failure, and a NUL-terminated string on success.
+ * On success, set <b>sz_out</b> to the number of bytes read (not including
+ * the final NULL, which wasn't read from <b>fd</fd>).
*/
char *
read_file_to_str_until_eof(int fd, size_t max_bytes_to_read, size_t *sz_out)
diff --git a/src/lib/log/.may_include b/src/lib/log/.may_include
index 54d96324db..09e2b90282 100644
--- a/src/lib/log/.may_include
+++ b/src/lib/log/.may_include
@@ -9,8 +9,10 @@ lib/intmath/*.h
lib/lock/*.h
lib/log/*.h
lib/malloc/*.h
+lib/metrics/*.h
lib/string/*.h
lib/subsys/*.h
lib/testsupport/*.h
+lib/thread/threads.h
lib/version/*.h
lib/wallclock/*.h
diff --git a/src/lib/log/log.c b/src/lib/log/log.c
index db57ee61a2..aecd838c5d 100644
--- a/src/lib/log/log.c
+++ b/src/lib/log/log.c
@@ -33,6 +33,7 @@
#define LOG_PRIVATE
#include "lib/log/log.h"
#include "lib/log/log_sys.h"
+#include "lib/log/util_bug.h"
#include "lib/version/git_revision.h"
#include "lib/log/ratelim.h"
#include "lib/lock/compat_mutex.h"
@@ -706,6 +707,8 @@ log_fn_(int severity, log_domain_mask_t domain, const char *fn,
const char *format, ...)
{
va_list ap;
+ if (domain & LD_BUG)
+ tor_bug_increment_count_();
if (severity > log_global_min_severity_)
return;
va_start(ap,format);
@@ -718,6 +721,8 @@ log_fn_ratelim_(ratelim_t *ratelim, int severity, log_domain_mask_t domain,
{
va_list ap;
char *m;
+ if (domain & LD_BUG)
+ tor_bug_increment_count_();
if (severity > log_global_min_severity_)
return;
m = rate_limit_log(ratelim, approx_time());
@@ -912,6 +917,7 @@ init_logging(int disable_startup_queue)
{
if (!log_mutex_initialized) {
tor_mutex_init(&log_mutex);
+ tor_bug_init_counter();
log_mutex_initialized = 1;
}
#ifdef __GNUC__
diff --git a/src/lib/log/log_sys.c b/src/lib/log/log_sys.c
index 33609f5288..ac76d9bdbb 100644
--- a/src/lib/log/log_sys.c
+++ b/src/lib/log/log_sys.c
@@ -11,11 +11,16 @@
#include "lib/log/escape.h"
#include "lib/log/log.h"
#include "lib/log/log_sys.h"
+#include "lib/log/util_bug.h"
+#include "lib/metrics/metrics_store.h"
+
+static metrics_store_t *the_store;
static int
subsys_logging_initialize(void)
{
init_logging(0);
+ the_store = metrics_store_new();
return 0;
}
@@ -26,6 +31,29 @@ subsys_logging_shutdown(void)
escaped(NULL);
}
+static const smartlist_t *
+logging_metrics_get_stores(void)
+{
+ static smartlist_t *stores_list = NULL;
+
+ metrics_store_reset(the_store);
+
+ metrics_store_entry_t *sentry = metrics_store_add(
+ the_store,
+ METRICS_TYPE_COUNTER,
+ METRICS_NAME(bug_reached_count),
+ "Total number of BUG() and similar assertion reached",
+ 0, NULL);
+ metrics_store_entry_update(sentry, tor_bug_get_count());
+
+ if (!stores_list) {
+ stores_list = smartlist_new();
+ smartlist_add(stores_list, the_store);
+ }
+
+ return stores_list;
+}
+
const subsys_fns_t sys_logging = {
.name = "log",
SUBSYS_DECLARE_LOCATION(),
@@ -35,4 +63,5 @@ const subsys_fns_t sys_logging = {
.level = -90,
.initialize = subsys_logging_initialize,
.shutdown = subsys_logging_shutdown,
+ .get_metrics = logging_metrics_get_stores,
};
diff --git a/src/lib/log/util_bug.c b/src/lib/log/util_bug.c
index 34b41324af..d2dbb0a7a5 100644
--- a/src/lib/log/util_bug.c
+++ b/src/lib/log/util_bug.c
@@ -18,6 +18,7 @@
#endif
#include "lib/malloc/malloc.h"
#include "lib/string/printf.h"
+#include "lib/thread/threads.h"
#include <string.h>
#include <stdlib.h>
@@ -101,6 +102,27 @@ tor_assertion_failed_(const char *fname, unsigned int line,
tor_free(buf);
}
+static atomic_counter_t total_bug_reached;
+
+void
+tor_bug_init_counter(void)
+{
+ atomic_counter_init(&total_bug_reached);
+}
+
+/** Helper to update BUG count in metrics. */
+void
+tor_bug_increment_count_(void)
+{
+ atomic_counter_add(&total_bug_reached, 1);
+}
+
+size_t
+tor_bug_get_count(void)
+{
+ return atomic_counter_get(&total_bug_reached);
+}
+
/** Helper for tor_assert_nonfatal: report the assertion failure. */
void
tor_bug_occurred_(const char *fname, unsigned int line,
@@ -110,6 +132,11 @@ tor_bug_occurred_(const char *fname, unsigned int line,
char *buf = NULL;
const char *once_str = once ?
" (Future instances of this warning will be silenced.)": "";
+ if (! once) {
+ // _once assertions count from the macro directly so we count them as many
+ // time as they are reached, and not just once.
+ tor_bug_increment_count_();
+ }
if (! expr) {
if (capturing_bugs()) {
add_captured_bug("This line should not have been reached.");
diff --git a/src/lib/log/util_bug.h b/src/lib/log/util_bug.h
index dd82981e08..5ea198f7ff 100644
--- a/src/lib/log/util_bug.h
+++ b/src/lib/log/util_bug.h
@@ -39,6 +39,7 @@
#include "orconfig.h"
#include "lib/cc/compat_compiler.h"
#include "lib/log/log.h"
+#include "lib/smartlist_core/smartlist_core.h"
#include "lib/testsupport/testsupport.h"
/* Replace assert() with a variant that sends failures to the log before
@@ -191,6 +192,7 @@
STMT_END
#define tor_assert_nonfatal_unreached_once() STMT_BEGIN \
static int warning_logged__ = 0; \
+ tor_bug_increment_count_(); \
if (!warning_logged__) { \
warning_logged__ = 1; \
tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, NULL, 1, NULL); \
@@ -198,10 +200,12 @@
STMT_END
#define tor_assert_nonfatal_once(cond) STMT_BEGIN \
static int warning_logged__ = 0; \
- if (ASSERT_PREDICT_LIKELY_(cond)) { \
- } else if (!warning_logged__) { \
- warning_logged__ = 1; \
- tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, #cond, 1, NULL);\
+ if (!ASSERT_PREDICT_LIKELY_(cond)) { \
+ tor_bug_increment_count_(); \
+ if (!warning_logged__) { \
+ warning_logged__ = 1; \
+ tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, #cond, 1, NULL);\
+ } \
} \
STMT_END
#define BUG(cond) \
@@ -215,18 +219,22 @@
if (( { \
static int var = 0; \
int bool_result = !!(cond); \
- if (bool_result && !var) { \
- var = 1; \
- tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, \
- ("!("#cond")"), 1, NULL); \
+ if (bool_result) { \
+ tor_bug_increment_count_(); \
+ if (!var) { \
+ var = 1; \
+ tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, \
+ ("!("#cond")"), 1, NULL); \
+ } \
} \
bool_result; } ))
#else /* !defined(__GNUC__) */
#define IF_BUG_ONCE__(cond,var) \
static int var = 0; \
if ((cond) ? \
- (var ? 1 : \
+ (var ? (tor_bug_increment_count_(), 1) : \
(var=1, \
+ tor_bug_increment_count_(), \
tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, \
("!("#cond")"), 1, NULL), \
1)) \
@@ -273,12 +281,15 @@ void tor_assertion_failed_(const char *fname, unsigned int line,
const char *func, const char *expr,
const char *fmt, ...)
CHECK_PRINTF(5,6);
+void tor_bug_increment_count_(void);
+size_t tor_bug_get_count(void);
void tor_bug_occurred_(const char *fname, unsigned int line,
const char *func, const char *expr,
int once, const char *fmt, ...)
CHECK_PRINTF(6,7);
void tor_abort_(void) ATTR_NORETURN;
+void tor_bug_init_counter(void);
#ifdef _WIN32
#define SHORT_FILE__ (tor_fix_source_file(__FILE__))
diff --git a/src/lib/sandbox/sandbox.c b/src/lib/sandbox/sandbox.c
index 8ac07abfc9..08322e17d4 100644
--- a/src/lib/sandbox/sandbox.c
+++ b/src/lib/sandbox/sandbox.c
@@ -125,6 +125,15 @@
#define SYSCALL_NAME_DEBUGGING
#endif
+/**
+ * On newer architectures Linux provides a standardized, generic set of system
+ * calls (defined in Linux's include/uapi/asm-generic/unistd.h), which omits a
+ * number of legacy calls used by glibc on other platforms.
+ */
+#if defined(__aarch64__) || defined(__riscv)
+#define ARCH_USES_GENERIC_SYSCALLS
+#endif
+
/**Determines if at least one sandbox is active.*/
static int sandbox_active = 0;
/** Holds the parameter list configuration for the sandbox.*/
@@ -263,8 +272,9 @@ static int filter_nopar_gen[] = {
#ifdef __NR_sigreturn
SCMP_SYS(sigreturn),
#endif
+#if defined(__NR_stat)
SCMP_SYS(stat),
-#if defined(__i386__) && defined(__NR_statx)
+#elif defined(__i386__) && defined(__NR_statx)
SCMP_SYS(statx),
#endif
SCMP_SYS(uname),
@@ -335,6 +345,8 @@ static int filter_nopar_gen[] = {
seccomp_rule_add((ctx),(act),(call),3,(f1),(f2),(f3))
#define seccomp_rule_add_4(ctx,act,call,f1,f2,f3,f4) \
seccomp_rule_add((ctx),(act),(call),4,(f1),(f2),(f3),(f4))
+#define seccomp_rule_add_5(ctx,act,call,f1,f2,f3,f4,f5) \
+ seccomp_rule_add((ctx),(act),(call),4,(f1),(f2),(f3),(f4),(f5))
static const char *sandbox_get_interned_string(const char *str);
@@ -516,18 +528,33 @@ is_libc_at_least(int major, int minor)
static int
libc_uses_openat_for_open(void)
{
+#ifdef __NR_open
return is_libc_at_least(2, 26);
+#else
+ return 1;
+#endif /* defined(__NR_open) */
}
+/* Calls to opendir() cannot be filtered by the sandbox when built with fragile
+ * hardening for an architecture that uses Linux's generic syscall interface,
+ * so prevent a compiler warning by omitting this function along with
+ * sb_opendir(). */
+#if !(defined(ENABLE_FRAGILE_HARDENING) && defined(ARCH_USES_GENERIC_SYSCALLS))
/* Return true if we think we're running with a libc that uses openat for the
* opendir function on linux. */
static int
libc_uses_openat_for_opendir(void)
{
+#ifdef __NR_open
// libc 2.27 and above or between 2.15 (inclusive) and 2.22 (exclusive)
return is_libc_at_least(2, 27) ||
(is_libc_at_least(2, 15) && !is_libc_at_least(2, 22));
+#else
+ return 1;
+#endif /* defined(__NR_open) */
}
+#endif /* !(defined(ENABLE_FRAGILE_HARDENING) &&
+ defined(ARCH_USES_GENERIC_SYSCALLS)) */
/** Allow a single file to be opened. If <b>use_openat</b> is true,
* we're using a libc that remaps all the opens into openats. */
@@ -557,10 +584,25 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
int use_openat = libc_uses_openat_for_open();
#ifdef ENABLE_FRAGILE_HARDENING
- /* AddressSanitizer uses the "open" syscall to access information about the
- * running process via the filesystem, so that call must be allowed without
+ /* AddressSanitizer uses either the "open" or the "openat" syscall (depending
+ * on the architecture) to access information about the running process via
+ * the filesystem, so the appropriate call must be allowed without
* restriction or the sanitizer will be unable to execute normally when the
* process terminates. */
+#ifdef ARCH_USES_GENERIC_SYSCALLS
+ rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat),
+ SCMP_CMP_LOWER32_EQ(0, AT_FDCWD));
+ if (rc != 0) {
+ log_err(LD_BUG,"(Sandbox) failed to add openat syscall, received "
+ "libseccomp error %d", rc);
+ return rc;
+ }
+
+ /* The "open" syscall is not defined on this architecture, so any other
+ * requests to open files will necessarily use "openat" as well and there is
+ * no need to consider any additional rules. */
+ return 0;
+#else
rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open));
if (rc != 0) {
log_err(LD_BUG,"(Sandbox) failed to add open syscall, received "
@@ -572,7 +614,8 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
* there is no need to consider any additional rules. */
if (!use_openat)
return 0;
-#endif
+#endif /* defined(ARCH_USES_GENERIC_SYSCALLS) */
+#endif /* defined(ENABLE_FRAGILE_HARDENING) */
// for each dynamic parameter filters
for (elem = filter; elem != NULL; elem = elem->next) {
@@ -592,6 +635,33 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
return 0;
}
+#ifdef ARCH_USES_GENERIC_SYSCALLS
+static int
+sb_fchmodat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
+{
+ int rc;
+ sandbox_cfg_t *elem = NULL;
+
+ // for each dynamic parameter filters
+ for (elem = filter; elem != NULL; elem = elem->next) {
+ smp_param_t *param = elem->param;
+
+ if (param != NULL && param->prot == 1 && param->syscall
+ == SCMP_SYS(fchmodat)) {
+ rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fchmodat),
+ SCMP_CMP_LOWER32_EQ(0, AT_FDCWD),
+ SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value));
+ if (rc != 0) {
+ log_err(LD_BUG,"(Sandbox) failed to add fchmodat syscall, received "
+ "libseccomp error %d", rc);
+ return rc;
+ }
+ }
+ }
+
+ return 0;
+}
+#else
static int
sb_chmod(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
{
@@ -616,9 +686,11 @@ sb_chmod(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
return 0;
}
+#endif /* defined(ARCH_USES_GENERIC_SYSCALLS) */
+#if defined(ARCH_USES_GENERIC_SYSCALLS)
static int
-sb_fchmodat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
+sb_fchownat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
{
int rc;
sandbox_cfg_t *elem = NULL;
@@ -628,12 +700,12 @@ sb_fchmodat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
smp_param_t *param = elem->param;
if (param != NULL && param->prot == 1 && param->syscall
- == SCMP_SYS(fchmodat)) {
- rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fchmodat),
+ == SCMP_SYS(fchownat)) {
+ rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fchownat),
SCMP_CMP_LOWER32_EQ(0, AT_FDCWD),
SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value));
if (rc != 0) {
- log_err(LD_BUG,"(Sandbox) failed to add fchmodat syscall, received "
+ log_err(LD_BUG,"(Sandbox) failed to add fchownat syscall, received "
"libseccomp error %d", rc);
return rc;
}
@@ -642,8 +714,7 @@ sb_fchmodat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
return 0;
}
-
-#ifdef __i386__
+#elif defined(__i386__)
static int
sb_chown32(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
{
@@ -693,10 +764,15 @@ sb_chown(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
return 0;
}
-#endif /* defined(__i386__) */
+#endif /* defined(ARCH_USES_GENERIC_SYSCALLS) || defined(__i386__) */
+#if defined(__NR_rename)
+/**
+ * Function responsible for setting up the rename syscall for
+ * the seccomp filter sandbox.
+ */
static int
-sb_fchownat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
+sb_rename(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
{
int rc;
sandbox_cfg_t *elem = NULL;
@@ -705,13 +781,14 @@ sb_fchownat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
for (elem = filter; elem != NULL; elem = elem->next) {
smp_param_t *param = elem->param;
- if (param != NULL && param->prot == 1 && param->syscall
- == SCMP_SYS(fchownat)) {
- rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fchownat),
- SCMP_CMP_LOWER32_EQ(0, AT_FDCWD),
- SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value));
+ if (param != NULL && param->prot == 1 &&
+ param->syscall == SCMP_SYS(rename)) {
+
+ rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rename),
+ SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value),
+ SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value2));
if (rc != 0) {
- log_err(LD_BUG,"(Sandbox) failed to add fchownat syscall, received "
+ log_err(LD_BUG,"(Sandbox) failed to add rename syscall, received "
"libseccomp error %d", rc);
return rc;
}
@@ -720,13 +797,13 @@ sb_fchownat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
return 0;
}
-
+#elif defined(__NR_renameat)
/**
- * Function responsible for setting up the rename syscall for
+ * Function responsible for setting up the renameat syscall for
* the seccomp filter sandbox.
*/
static int
-sb_rename(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
+sb_renameat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
{
int rc;
sandbox_cfg_t *elem = NULL;
@@ -736,13 +813,15 @@ sb_rename(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
smp_param_t *param = elem->param;
if (param != NULL && param->prot == 1 &&
- param->syscall == SCMP_SYS(rename)) {
+ param->syscall == SCMP_SYS(renameat)) {
- rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rename),
- SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value),
- SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value2));
+ rc = seccomp_rule_add_4(ctx, SCMP_ACT_ALLOW, SCMP_SYS(renameat),
+ SCMP_CMP_LOWER32_EQ(0, AT_FDCWD),
+ SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value),
+ SCMP_CMP_LOWER32_EQ(2, AT_FDCWD),
+ SCMP_CMP_STR(3, SCMP_CMP_EQ, param->value2));
if (rc != 0) {
- log_err(LD_BUG,"(Sandbox) failed to add rename syscall, received "
+ log_err(LD_BUG,"(Sandbox) failed to add renameat syscall, received "
"libseccomp error %d", rc);
return rc;
}
@@ -751,13 +830,13 @@ sb_rename(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
return 0;
}
-
+#else
/**
- * Function responsible for setting up the renameat syscall for
+ * Function responsible for setting up the renameat2 syscall for
* the seccomp filter sandbox.
*/
static int
-sb_renameat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
+sb_renameat2(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
{
int rc;
sandbox_cfg_t *elem = NULL;
@@ -767,15 +846,16 @@ sb_renameat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
smp_param_t *param = elem->param;
if (param != NULL && param->prot == 1 &&
- param->syscall == SCMP_SYS(renameat)) {
+ param->syscall == SCMP_SYS(renameat2)) {
- rc = seccomp_rule_add_4(ctx, SCMP_ACT_ALLOW, SCMP_SYS(renameat),
+ rc = seccomp_rule_add_5(ctx, SCMP_ACT_ALLOW, SCMP_SYS(renameat2),
SCMP_CMP_LOWER32_EQ(0, AT_FDCWD),
SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value),
SCMP_CMP_LOWER32_EQ(2, AT_FDCWD),
- SCMP_CMP_STR(3, SCMP_CMP_EQ, param->value2));
+ SCMP_CMP_STR(3, SCMP_CMP_EQ, param->value2),
+ SCMP_CMP(4, SCMP_CMP_EQ, 0));
if (rc != 0) {
- log_err(LD_BUG,"(Sandbox) failed to add renameat syscall, received "
+ log_err(LD_BUG,"(Sandbox) failed to add renameat2 syscall, received "
"libseccomp error %d", rc);
return rc;
}
@@ -784,7 +864,19 @@ sb_renameat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
return 0;
}
+#endif /* defined(__NR_rename) || defined(__NR_renameat) */
+/* If Tor is built with fragile hardening for an architecture that uses Linux's
+ * generic syscall interface a rule allowing the "openat" syscall without
+ * restriction will have already been added by sb_open(), so there is no need
+ * to consider adding additional, more restrictive rules here as they will
+ * simply be ignored.
+ *
+ * Also, since the "open" syscall is not defined on these architectures, glibc
+ * will necessarily use "openat" for its implementation of opendir() as well.
+ * This means neither of the following two functions will have any effect and
+ * both can be omitted. */
+#if !(defined(ENABLE_FRAGILE_HARDENING) && defined(ARCH_USES_GENERIC_SYSCALLS))
/**
* Function responsible for setting up the openat syscall for
* the seccomp filter sandbox.
@@ -840,6 +932,8 @@ sb_opendir(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
return 0;
}
+#endif /* !(defined(ENABLE_FRAGILE_HARDENING) &&
+ defined(ARCH_USES_GENERIC_SYSCALLS)) */
#ifdef ENABLE_FRAGILE_HARDENING
/**
@@ -859,9 +953,17 @@ sb_ptrace(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
if (rc)
return rc;
+ /* AddressSanitizer uses "PTRACE_GETREGSET" on AArch64 (ARM64) and
+ * System/390, "PTRACE_GETREGS" everywhere else. */
+#if defined(__aarch64__) || defined(__s390__)
+ rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ptrace),
+ SCMP_CMP(0, SCMP_CMP_EQ, PTRACE_GETREGSET),
+ SCMP_CMP(1, SCMP_CMP_EQ, pid));
+#else
rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ptrace),
SCMP_CMP(0, SCMP_CMP_EQ, PTRACE_GETREGS),
SCMP_CMP(1, SCMP_CMP_EQ, pid));
+#endif /* defined(__aarch64__) || defined(__s390__) */
if (rc)
return rc;
@@ -1351,6 +1453,40 @@ sb_mremap(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
return 0;
}
+#ifdef ARCH_USES_GENERIC_SYSCALLS
+/**
+ * Function responsible for setting up the newfstatat syscall for
+ * the seccomp filter sandbox.
+ */
+static int
+sb_newfstatat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
+{
+ int rc = 0;
+
+ sandbox_cfg_t *elem = NULL;
+
+ // for each dynamic parameter filters
+ for (elem = filter; elem != NULL; elem = elem->next) {
+ smp_param_t *param = elem->param;
+
+ if (param != NULL && param->prot == 1 && (param->syscall == SCMP_SYS(open)
+ || param->syscall == PHONY_OPENDIR_SYSCALL
+ || param->syscall == SCMP_SYS(newfstatat))) {
+ rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(newfstatat),
+ SCMP_CMP_LOWER32_EQ(0, AT_FDCWD),
+ SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value));
+ if (rc != 0) {
+ log_err(LD_BUG,"(Sandbox) failed to add newfstatat syscall, received "
+ "libseccomp error %d", rc);
+ return rc;
+ }
+ }
+ }
+
+ return 0;
+}
+#endif /* defined(ARCH_USES_GENERIC_SYSCALLS) */
+
#ifdef __NR_stat64
/**
* Function responsible for setting up the stat64 syscall for
@@ -1409,22 +1545,33 @@ static sandbox_filter_func_t filter_func[] = {
#ifdef __NR_mmap2
sb_mmap2,
#endif
-#ifdef __i386__
+#if defined(ARCH_USES_GENERIC_SYSCALLS)
+ sb_fchownat,
+#elif defined(__i386__)
sb_chown32,
#else
sb_chown,
#endif
- sb_fchownat,
- sb_chmod,
+#if defined(ARCH_USES_GENERIC_SYSCALLS)
sb_fchmodat,
+#else
+ sb_chmod,
+#endif
sb_open,
+#if !(defined(ENABLE_FRAGILE_HARDENING) && defined(ARCH_USES_GENERIC_SYSCALLS))
sb_openat,
sb_opendir,
+#endif
#ifdef ENABLE_FRAGILE_HARDENING
sb_ptrace,
#endif
+#if defined(__NR_rename)
sb_rename,
+#elif defined(__NR_renameat)
sb_renameat,
+#else
+ sb_renameat2,
+#endif
#ifdef __NR_fcntl64
sb_fcntl64,
#endif
@@ -1434,7 +1581,9 @@ static sandbox_filter_func_t filter_func[] = {
sb_flock,
sb_futex,
sb_mremap,
-#ifdef __NR_stat64
+#if defined(ARCH_USES_GENERIC_SYSCALLS)
+ sb_newfstatat,
+#elif defined(__NR_stat64)
sb_stat64,
#endif
@@ -1690,27 +1839,31 @@ new_element(int syscall, char *value)
return new_element2(syscall, value, NULL);
}
-#ifdef __i386__
-#define SCMP_chown SCMP_SYS(chown32)
-#elif defined(__aarch64__) && defined(__LP64__)
+#if defined(ARCH_USES_GENERIC_SYSCALLS)
#define SCMP_chown SCMP_SYS(fchownat)
+#elif defined(__i386__)
+#define SCMP_chown SCMP_SYS(chown32)
#else
#define SCMP_chown SCMP_SYS(chown)
#endif
-#if defined(__aarch64__) && defined(__LP64__)
+#if defined(ARCH_USES_GENERIC_SYSCALLS)
#define SCMP_chmod SCMP_SYS(fchmodat)
#else
#define SCMP_chmod SCMP_SYS(chmod)
#endif
-#if defined(__aarch64__) && defined(__LP64__)
+#if defined(__NR_rename)
+#define SCMP_rename SCMP_SYS(rename)
+#elif defined(__NR_renameat)
#define SCMP_rename SCMP_SYS(renameat)
#else
-#define SCMP_rename SCMP_SYS(rename)
+#define SCMP_rename SCMP_SYS(renameat2)
#endif
-#ifdef __NR_stat64
+#if defined(ARCH_USES_GENERIC_SYSCALLS)
+#define SCMP_stat SCMP_SYS(newfstatat)
+#elif defined(__NR_stat64)
#define SCMP_stat SCMP_SYS(stat64)
#else
#define SCMP_stat SCMP_SYS(stat)
diff --git a/src/lib/string/util_string.c b/src/lib/string/util_string.c
index b1c0a11439..60b5933e4d 100644
--- a/src/lib/string/util_string.c
+++ b/src/lib/string/util_string.c
@@ -31,6 +31,8 @@ tor_memmem(const void *_haystack, size_t hlen,
{
#if defined(HAVE_MEMMEM) && (!defined(__GNUC__) || __GNUC__ >= 2)
raw_assert(nlen);
+ if (nlen > hlen)
+ return NULL;
return memmem(_haystack, hlen, _needle, nlen);
#else
/* This isn't as fast as the GLIBC implementation, but it doesn't need to
diff --git a/src/test/bench.c b/src/test/bench.c
index a76e600cfa..044351b4be 100644
--- a/src/test/bench.c
+++ b/src/test/bench.c
@@ -11,7 +11,6 @@
#include "orconfig.h"
#include "core/or/or.h"
-#include "core/crypto/onion_tap.h"
#include "core/crypto/relay_crypto.h"
#include "lib/intmath/weakrng.h"
@@ -127,75 +126,6 @@ bench_aes(void)
}
static void
-bench_onion_TAP(void)
-{
- const int iters = 1<<9;
- int i;
- crypto_pk_t *key, *key2;
- uint64_t start, end;
- char os[TAP_ONIONSKIN_CHALLENGE_LEN];
- char or[TAP_ONIONSKIN_REPLY_LEN];
- crypto_dh_t *dh_out = NULL;
-
- key = crypto_pk_new();
- key2 = crypto_pk_new();
- if (crypto_pk_generate_key_with_bits(key, 1024) < 0)
- goto done;
- if (crypto_pk_generate_key_with_bits(key2, 1024) < 0)
- goto done;
-
- reset_perftime();
- start = perftime();
- for (i = 0; i < iters; ++i) {
- onion_skin_TAP_create(key, &dh_out, os);
- crypto_dh_free(dh_out);
- }
- end = perftime();
- printf("Client-side, part 1: %f usec.\n", NANOCOUNT(start, end, iters)/1e3);
-
- onion_skin_TAP_create(key, &dh_out, os);
- start = perftime();
- for (i = 0; i < iters; ++i) {
- char key_out[CPATH_KEY_MATERIAL_LEN];
- onion_skin_TAP_server_handshake(os, key, NULL, or,
- key_out, sizeof(key_out));
- }
- end = perftime();
- printf("Server-side, key guessed right: %f usec\n",
- NANOCOUNT(start, end, iters)/1e3);
-
- start = perftime();
- for (i = 0; i < iters; ++i) {
- char key_out[CPATH_KEY_MATERIAL_LEN];
- onion_skin_TAP_server_handshake(os, key2, key, or,
- key_out, sizeof(key_out));
- }
- end = perftime();
- printf("Server-side, key guessed wrong: %f usec.\n",
- NANOCOUNT(start, end, iters)/1e3);
-
- start = perftime();
- for (i = 0; i < iters; ++i) {
- crypto_dh_t *dh;
- char key_out[CPATH_KEY_MATERIAL_LEN];
- int s;
- dh = crypto_dh_dup(dh_out);
- s = onion_skin_TAP_client_handshake(dh, or, key_out, sizeof(key_out),
- NULL);
- crypto_dh_free(dh);
- tor_assert(s == 0);
- }
- end = perftime();
- printf("Client-side, part 2: %f usec.\n",
- NANOCOUNT(start, end, iters)/1e3);
-
- done:
- crypto_dh_free(dh_out);
- crypto_pk_free(key);
- crypto_pk_free(key2);
-}
-
-static void
bench_onion_ntor_impl(void)
{
const int iters = 1<<10;
@@ -754,7 +684,6 @@ static struct benchmark_t benchmarks[] = {
ENT(siphash),
ENT(digest),
ENT(aes),
- ENT(onion_TAP),
ENT(onion_ntor),
ENT(ed25519),
ENT(rand),
diff --git a/src/test/test.c b/src/test/test.c
index 2030a8336e..317b570d8e 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -50,7 +50,6 @@
#include "core/or/onion.h"
#include "core/crypto/onion_ntor.h"
#include "core/crypto/onion_fast.h"
-#include "core/crypto/onion_tap.h"
#include "core/or/policies.h"
#include "lib/sandbox/sandbox.h"
#include "app/config/statefile.h"
@@ -61,150 +60,6 @@
#include "core/or/or_circuit_st.h"
#include "feature/relay/onion_queue.h"
-/** Run unit tests for the onion handshake code. */
-static void
-test_onion_handshake(void *arg)
-{
- /* client-side */
- crypto_dh_t *c_dh = NULL;
- char c_buf[TAP_ONIONSKIN_CHALLENGE_LEN];
- char c_keys[40];
- /* server-side */
- char s_buf[TAP_ONIONSKIN_REPLY_LEN];
- char s_keys[40];
- int i;
- /* shared */
- crypto_pk_t *pk = NULL, *pk2 = NULL;
-
- (void)arg;
- pk = pk_generate(0);
- pk2 = pk_generate(1);
-
- /* client handshake 1. */
- memset(c_buf, 0, TAP_ONIONSKIN_CHALLENGE_LEN);
- tt_assert(! onion_skin_TAP_create(pk, &c_dh, c_buf));
-
- for (i = 1; i <= 3; ++i) {
- crypto_pk_t *k1, *k2;
- if (i==1) {
- /* server handshake: only one key known. */
- k1 = pk; k2 = NULL;
- } else if (i==2) {
- /* server handshake: try the right key first. */
- k1 = pk; k2 = pk2;
- } else {
- /* server handshake: try the right key second. */
- k1 = pk2; k2 = pk;
- }
-
- memset(s_buf, 0, TAP_ONIONSKIN_REPLY_LEN);
- memset(s_keys, 0, 40);
- tt_assert(! onion_skin_TAP_server_handshake(c_buf, k1, k2,
- s_buf, s_keys, 40));
-
- /* client handshake 2 */
- memset(c_keys, 0, 40);
- tt_assert(! onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys,
- 40, NULL));
-
- tt_mem_op(c_keys,OP_EQ, s_keys, 40);
- memset(s_buf, 0, 40);
- tt_mem_op(c_keys,OP_NE, s_buf, 40);
- }
- done:
- crypto_dh_free(c_dh);
- crypto_pk_free(pk);
- crypto_pk_free(pk2);
-}
-
-static void
-test_bad_onion_handshake(void *arg)
-{
- char junk_buf[TAP_ONIONSKIN_CHALLENGE_LEN];
- char junk_buf2[TAP_ONIONSKIN_CHALLENGE_LEN];
- /* client-side */
- crypto_dh_t *c_dh = NULL;
- char c_buf[TAP_ONIONSKIN_CHALLENGE_LEN];
- char c_keys[40];
- /* server-side */
- char s_buf[TAP_ONIONSKIN_REPLY_LEN];
- char s_keys[40];
- /* shared */
- crypto_pk_t *pk = NULL, *pk2 = NULL;
-
- (void)arg;
-
- pk = pk_generate(0);
- pk2 = pk_generate(1);
-
- /* Server: Case 1: the encrypted data is degenerate. */
- memset(junk_buf, 0, sizeof(junk_buf));
- crypto_pk_obsolete_public_hybrid_encrypt(pk,
- junk_buf2, TAP_ONIONSKIN_CHALLENGE_LEN,
- junk_buf, DH1024_KEY_LEN,
- PK_PKCS1_OAEP_PADDING, 1);
- tt_int_op(-1, OP_EQ,
- onion_skin_TAP_server_handshake(junk_buf2, pk, NULL,
- s_buf, s_keys, 40));
-
- /* Server: Case 2: the encrypted data is not long enough. */
- memset(junk_buf, 0, sizeof(junk_buf));
- memset(junk_buf2, 0, sizeof(junk_buf2));
- crypto_pk_public_encrypt(pk, junk_buf2, sizeof(junk_buf2),
- junk_buf, 48, PK_PKCS1_OAEP_PADDING);
- tt_int_op(-1, OP_EQ,
- onion_skin_TAP_server_handshake(junk_buf2, pk, NULL,
- s_buf, s_keys, 40));
-
- /* client handshake 1: do it straight. */
- memset(c_buf, 0, TAP_ONIONSKIN_CHALLENGE_LEN);
- tt_assert(! onion_skin_TAP_create(pk, &c_dh, c_buf));
-
- /* Server: Case 3: we just don't have the right key. */
- tt_int_op(-1, OP_EQ,
- onion_skin_TAP_server_handshake(c_buf, pk2, NULL,
- s_buf, s_keys, 40));
-
- /* Server: Case 4: The RSA-encrypted portion is corrupt. */
- c_buf[64] ^= 33;
- tt_int_op(-1, OP_EQ,
- onion_skin_TAP_server_handshake(c_buf, pk, NULL,
- s_buf, s_keys, 40));
- c_buf[64] ^= 33;
-
- /* (Let the server proceed) */
- tt_int_op(0, OP_EQ,
- onion_skin_TAP_server_handshake(c_buf, pk, NULL,
- s_buf, s_keys, 40));
-
- /* Client: Case 1: The server sent back junk. */
- const char *msg = NULL;
- s_buf[64] ^= 33;
- tt_int_op(-1, OP_EQ,
- onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40, &msg));
- s_buf[64] ^= 33;
- tt_str_op(msg, OP_EQ, "Digest DOES NOT MATCH on onion handshake. "
- "Bug or attack.");
-
- /* Let the client finish; make sure it can. */
- msg = NULL;
- tt_int_op(0, OP_EQ,
- onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40, &msg));
- tt_mem_op(s_keys,OP_EQ, c_keys, 40);
- tt_ptr_op(msg, OP_EQ, NULL);
-
- /* Client: Case 2: The server sent back a degenerate DH. */
- memset(s_buf, 0, sizeof(s_buf));
- tt_int_op(-1, OP_EQ,
- onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40, &msg));
- tt_str_op(msg, OP_EQ, "DH computation failed.");
-
- done:
- crypto_dh_free(c_dh);
- crypto_pk_free(pk);
- crypto_pk_free(pk2);
-}
-
static void
test_ntor_handshake(void *arg)
{
@@ -306,37 +161,35 @@ test_fast_handshake(void *arg)
static void
test_onion_queues(void *arg)
{
- uint8_t buf1[TAP_ONIONSKIN_CHALLENGE_LEN] = {0};
+ uint8_t buf1[NTOR_ONIONSKIN_LEN] = {0};
uint8_t buf2[NTOR_ONIONSKIN_LEN] = {0};
or_circuit_t *circ1 = or_circuit_new(0, NULL);
or_circuit_t *circ2 = or_circuit_new(0, NULL);
- create_cell_t *onionskin = NULL, *create2_ptr;
+ create_cell_t *onionskin = NULL, *create1_ptr;
create_cell_t *create1 = tor_malloc_zero(sizeof(create_cell_t));
create_cell_t *create2 = tor_malloc_zero(sizeof(create_cell_t));
(void)arg;
- create2_ptr = create2; /* remember, but do not free */
+ create1_ptr = create1; /* remember, but do not free */
- create_cell_init(create1, CELL_CREATE, ONION_HANDSHAKE_TYPE_TAP,
- TAP_ONIONSKIN_CHALLENGE_LEN, buf1);
+ create_cell_init(create1, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR,
+ NTOR_ONIONSKIN_LEN, buf1);
create_cell_init(create2, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR,
NTOR_ONIONSKIN_LEN, buf2);
- tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
+ tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
tt_int_op(0,OP_EQ, onion_pending_add(circ1, create1));
create1 = NULL;
- tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
+ tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
- tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
tt_int_op(0,OP_EQ, onion_pending_add(circ2, create2));
create2 = NULL;
- tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
+ tt_int_op(2,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
- tt_ptr_op(circ2,OP_EQ, onion_next_task(&onionskin));
- tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
- tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
- tt_ptr_op(onionskin, OP_EQ, create2_ptr);
+ tt_ptr_op(circ1,OP_EQ, onion_next_task(&onionskin));
+ tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
+ tt_ptr_op(onionskin, OP_EQ, create1_ptr);
clear_pending_onions();
tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
@@ -365,24 +218,19 @@ test_onion_queues(void *arg)
static void
test_onion_queue_order(void *arg)
{
- uint8_t buf_tap[TAP_ONIONSKIN_CHALLENGE_LEN] = {0};
uint8_t buf_ntor[NTOR_ONIONSKIN_LEN] = {0};
uint8_t buf_ntor3[CELL_PAYLOAD_SIZE] = {0};
- or_circuit_t *circ_tap = or_circuit_new(0, NULL);
or_circuit_t *circ_ntor = or_circuit_new(0, NULL);
or_circuit_t *circ_ntor3 = or_circuit_new(0, NULL);
create_cell_t *onionskin = NULL;
- create_cell_t *create_tap1 = tor_malloc_zero(sizeof(create_cell_t));
create_cell_t *create_ntor1 = tor_malloc_zero(sizeof(create_cell_t));
create_cell_t *create_ntor2 = tor_malloc_zero(sizeof(create_cell_t));
create_cell_t *create_v3ntor1 = tor_malloc_zero(sizeof(create_cell_t));
create_cell_t *create_v3ntor2 = tor_malloc_zero(sizeof(create_cell_t));
(void)arg;
- create_cell_init(create_tap1, CELL_CREATE, ONION_HANDSHAKE_TYPE_TAP,
- TAP_ONIONSKIN_CHALLENGE_LEN, buf_tap);
create_cell_init(create_ntor1, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR,
NTOR_ONIONSKIN_LEN, buf_ntor);
create_cell_init(create_ntor2, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR,
@@ -393,78 +241,63 @@ test_onion_queue_order(void *arg)
NTOR_ONIONSKIN_LEN, buf_ntor3);
/* sanity check queue init */
- tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
- tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
- tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3));
-
- /* Add tap first so we can ensure it comes out last */
- tt_int_op(0,OP_EQ, onion_pending_add(circ_tap, create_tap1));
- tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3));
/* Now add interleaving ntor2 and ntor3, to ensure they share
* the same queue and come out in this order */
tt_int_op(0,OP_EQ, onion_pending_add(circ_ntor, create_ntor1));
- tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
+ tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3));
tt_int_op(0,OP_EQ, onion_pending_add(circ_ntor3, create_v3ntor1));
- tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
+ tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
tt_int_op(2,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
tt_int_op(2,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3));
tt_int_op(0,OP_EQ, onion_pending_add(circ_ntor, create_ntor2));
- tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
+ tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
tt_int_op(3,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
tt_int_op(3,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3));
tt_int_op(0,OP_EQ, onion_pending_add(circ_ntor3, create_v3ntor2));
- tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
+ tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
tt_int_op(4,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
tt_int_op(4,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3));
/* Now remove 5 tasks, ensuring order and queue sizes */
tt_ptr_op(circ_ntor, OP_EQ, onion_next_task(&onionskin));
- tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
+ tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
tt_int_op(3,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
tt_int_op(3,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3));
tt_ptr_op(onionskin, OP_EQ, create_ntor1);
tt_ptr_op(circ_ntor3, OP_EQ, onion_next_task(&onionskin));
- tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
+ tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
tt_int_op(2,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
tt_int_op(2,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3));
tt_ptr_op(onionskin, OP_EQ, create_v3ntor1);
tt_ptr_op(circ_ntor, OP_EQ, onion_next_task(&onionskin));
- tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
+ tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3));
tt_ptr_op(onionskin, OP_EQ, create_ntor2);
tt_ptr_op(circ_ntor3, OP_EQ, onion_next_task(&onionskin));
- tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
- tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
- tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3));
- tt_ptr_op(onionskin, OP_EQ, create_v3ntor2);
-
- tt_ptr_op(circ_tap, OP_EQ, onion_next_task(&onionskin));
tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3));
- tt_ptr_op(onionskin, OP_EQ, create_tap1);
+ tt_ptr_op(onionskin, OP_EQ, create_v3ntor2);
clear_pending_onions();
tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
done:
- circuit_free_(TO_CIRCUIT(circ_tap));
circuit_free_(TO_CIRCUIT(circ_ntor));
circuit_free_(TO_CIRCUIT(circ_ntor3));
- tor_free(create_tap1);
tor_free(create_ntor1);
tor_free(create_ntor2);
tor_free(create_v3ntor1);
@@ -740,8 +573,6 @@ test_circuit_timeout(void *arg)
{ #name, test_ ## name , TT_FORK, NULL, NULL }
static struct testcase_t test_array[] = {
- ENT(onion_handshake),
- { "bad_onion_handshake", test_bad_onion_handshake, 0, NULL, NULL },
ENT(onion_queues),
ENT(onion_queue_order),
{ "ntor_handshake", test_ntor_handshake, 0, NULL, NULL },
diff --git a/src/test/test_cell_formats.c b/src/test/test_cell_formats.c
index b7b149cd66..e01a3461fc 100644
--- a/src/test/test_cell_formats.c
+++ b/src/test/test_cell_formats.c
@@ -14,7 +14,6 @@
#include "app/config/config.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "core/or/onion.h"
-#include "core/crypto/onion_tap.h"
#include "core/crypto/onion_fast.h"
#include "core/crypto/onion_ntor.h"
#include "core/or/relay.h"
@@ -399,21 +398,6 @@ test_cfmt_create_cells(void *arg)
/* === Let's try parsing some good cells! */
- /* A valid create cell. */
- memset(&cell, 0, sizeof(cell));
- memset(b, 0, sizeof(b));
- crypto_rand((char*)b, TAP_ONIONSKIN_CHALLENGE_LEN);
- cell.command = CELL_CREATE;
- memcpy(cell.payload, b, TAP_ONIONSKIN_CHALLENGE_LEN);
- tt_int_op(0, OP_EQ, create_cell_parse(&cc, &cell));
- tt_int_op(CELL_CREATE, OP_EQ, cc.cell_type);
- tt_int_op(ONION_HANDSHAKE_TYPE_TAP, OP_EQ, cc.handshake_type);
- tt_int_op(TAP_ONIONSKIN_CHALLENGE_LEN, OP_EQ, cc.handshake_len);
- tt_mem_op(cc.onionskin,OP_EQ, b, TAP_ONIONSKIN_CHALLENGE_LEN + 10);
- tt_int_op(0, OP_EQ, create_cell_format(&cell2, &cc));
- tt_int_op(cell.command, OP_EQ, cell2.command);
- tt_mem_op(cell.payload,OP_EQ, cell2.payload, CELL_PAYLOAD_SIZE);
-
/* A valid create_fast cell. */
memset(&cell, 0, sizeof(cell));
memset(b, 0, sizeof(b));
@@ -429,22 +413,6 @@ test_cfmt_create_cells(void *arg)
tt_int_op(cell.command, OP_EQ, cell2.command);
tt_mem_op(cell.payload,OP_EQ, cell2.payload, CELL_PAYLOAD_SIZE);
- /* A valid create2 cell with a TAP payload */
- memset(&cell, 0, sizeof(cell));
- memset(b, 0, sizeof(b));
- crypto_rand((char*)b, TAP_ONIONSKIN_CHALLENGE_LEN);
- cell.command = CELL_CREATE2;
- memcpy(cell.payload, "\x00\x00\x00\xBA", 4); /* TAP, 186 bytes long */
- memcpy(cell.payload+4, b, TAP_ONIONSKIN_CHALLENGE_LEN);
- tt_int_op(0, OP_EQ, create_cell_parse(&cc, &cell));
- tt_int_op(CELL_CREATE2, OP_EQ, cc.cell_type);
- tt_int_op(ONION_HANDSHAKE_TYPE_TAP, OP_EQ, cc.handshake_type);
- tt_int_op(TAP_ONIONSKIN_CHALLENGE_LEN, OP_EQ, cc.handshake_len);
- tt_mem_op(cc.onionskin,OP_EQ, b, TAP_ONIONSKIN_CHALLENGE_LEN + 10);
- tt_int_op(0, OP_EQ, create_cell_format(&cell2, &cc));
- tt_int_op(cell.command, OP_EQ, cell2.command);
- tt_mem_op(cell.payload,OP_EQ, cell2.payload, CELL_PAYLOAD_SIZE);
-
/* A valid create2 cell with an ntor payload */
memset(&cell, 0, sizeof(cell));
memset(b, 0, sizeof(b));
@@ -461,22 +429,6 @@ test_cfmt_create_cells(void *arg)
tt_int_op(cell.command, OP_EQ, cell2.command);
tt_mem_op(cell.payload,OP_EQ, cell2.payload, CELL_PAYLOAD_SIZE);
- /* A valid create cell with an ntor payload, in legacy format. */
- memset(&cell, 0, sizeof(cell));
- memset(b, 0, sizeof(b));
- crypto_rand((char*)b, NTOR_ONIONSKIN_LEN);
- cell.command = CELL_CREATE;
- memcpy(cell.payload, "ntorNTORntorNTOR", 16);
- memcpy(cell.payload+16, b, NTOR_ONIONSKIN_LEN);
- tt_int_op(0, OP_EQ, create_cell_parse(&cc, &cell));
- tt_int_op(CELL_CREATE, OP_EQ, cc.cell_type);
- tt_int_op(ONION_HANDSHAKE_TYPE_NTOR, OP_EQ, cc.handshake_type);
- tt_int_op(NTOR_ONIONSKIN_LEN, OP_EQ, cc.handshake_len);
- tt_mem_op(cc.onionskin,OP_EQ, b, NTOR_ONIONSKIN_LEN + 10);
- tt_int_op(0, OP_EQ, create_cell_format(&cell2, &cc));
- tt_int_op(cell.command, OP_EQ, cell2.command);
- tt_mem_op(cell.payload,OP_EQ, cell2.payload, CELL_PAYLOAD_SIZE);
-
/* == Okay, now let's try to parse some impossible stuff. */
/* It has to be some kind of a create cell! */
@@ -517,20 +469,6 @@ test_cfmt_created_cells(void *arg)
(void)arg;
- /* A good CREATED cell */
- memset(&cell, 0, sizeof(cell));
- memset(b, 0, sizeof(b));
- crypto_rand((char*)b, TAP_ONIONSKIN_REPLY_LEN);
- cell.command = CELL_CREATED;
- memcpy(cell.payload, b, TAP_ONIONSKIN_REPLY_LEN);
- tt_int_op(0, OP_EQ, created_cell_parse(&cc, &cell));
- tt_int_op(CELL_CREATED, OP_EQ, cc.cell_type);
- tt_int_op(TAP_ONIONSKIN_REPLY_LEN, OP_EQ, cc.handshake_len);
- tt_mem_op(cc.reply,OP_EQ, b, TAP_ONIONSKIN_REPLY_LEN + 10);
- tt_int_op(0, OP_EQ, created_cell_format(&cell2, &cc));
- tt_int_op(cell.command, OP_EQ, cell2.command);
- tt_mem_op(cell.payload,OP_EQ, cell2.payload, CELL_PAYLOAD_SIZE);
-
/* A good CREATED_FAST cell */
memset(&cell, 0, sizeof(cell));
memset(b, 0, sizeof(b));
@@ -606,54 +544,6 @@ test_cfmt_extend_cells(void *arg)
(void) arg;
- /* Let's start with a simple EXTEND cell. */
- memset(p, 0, sizeof(p));
- memset(b, 0, sizeof(b));
- crypto_rand((char*)b, TAP_ONIONSKIN_CHALLENGE_LEN);
- memcpy(p, "\x12\xf4\x00\x01\x01\x02", 6); /* 18 244 0 1 : 258 */
- memcpy(p+6,b,TAP_ONIONSKIN_CHALLENGE_LEN);
- memcpy(p+6+TAP_ONIONSKIN_CHALLENGE_LEN, "electroencephalogram", 20);
- tt_int_op(0, OP_EQ, extend_cell_parse(&ec, RELAY_COMMAND_EXTEND,
- p, 26+TAP_ONIONSKIN_CHALLENGE_LEN));
- tt_int_op(RELAY_COMMAND_EXTEND, OP_EQ, ec.cell_type);
- tt_str_op("18.244.0.1", OP_EQ, fmt_addr(&ec.orport_ipv4.addr));
- tt_int_op(258, OP_EQ, ec.orport_ipv4.port);
- tt_int_op(AF_UNSPEC, OP_EQ, tor_addr_family(&ec.orport_ipv6.addr));
- tt_mem_op(ec.node_id,OP_EQ, "electroencephalogram", 20);
- tt_int_op(cc->cell_type, OP_EQ, CELL_CREATE);
- tt_int_op(cc->handshake_type, OP_EQ, ONION_HANDSHAKE_TYPE_TAP);
- tt_int_op(cc->handshake_len, OP_EQ, TAP_ONIONSKIN_CHALLENGE_LEN);
- tt_mem_op(cc->onionskin,OP_EQ, b, TAP_ONIONSKIN_CHALLENGE_LEN+20);
- tt_int_op(0, OP_EQ, extend_cell_format(&p2_cmd, &p2_len, p2, &ec));
- tt_int_op(p2_cmd, OP_EQ, RELAY_COMMAND_EXTEND);
- tt_int_op(p2_len, OP_EQ, 26+TAP_ONIONSKIN_CHALLENGE_LEN);
- tt_mem_op(p2,OP_EQ, p, RELAY_PAYLOAD_SIZE);
-
- /* Let's do an ntor stuffed in a legacy EXTEND cell */
- memset(p, 0, sizeof(p));
- memset(b, 0, sizeof(b));
- crypto_rand((char*)b, NTOR_ONIONSKIN_LEN);
- memcpy(p, "\x12\xf4\x00\x01\x01\x02", 6); /* 18 244 0 1 : 258 */
- memcpy(p+6,"ntorNTORntorNTOR", 16);
- memcpy(p+22, b, NTOR_ONIONSKIN_LEN);
- memcpy(p+6+TAP_ONIONSKIN_CHALLENGE_LEN, "electroencephalogram", 20);
- tt_int_op(0, OP_EQ, extend_cell_parse(&ec, RELAY_COMMAND_EXTEND,
- p, 26+TAP_ONIONSKIN_CHALLENGE_LEN));
- tt_int_op(RELAY_COMMAND_EXTEND, OP_EQ, ec.cell_type);
- tt_str_op("18.244.0.1", OP_EQ, fmt_addr(&ec.orport_ipv4.addr));
- tt_int_op(258, OP_EQ, ec.orport_ipv4.port);
- tt_int_op(AF_UNSPEC, OP_EQ, tor_addr_family(&ec.orport_ipv6.addr));
- tt_mem_op(ec.node_id,OP_EQ, "electroencephalogram", 20);
- tt_int_op(cc->cell_type, OP_EQ, CELL_CREATE2);
- tt_int_op(cc->handshake_type, OP_EQ, ONION_HANDSHAKE_TYPE_NTOR);
- tt_int_op(cc->handshake_len, OP_EQ, NTOR_ONIONSKIN_LEN);
- tt_mem_op(cc->onionskin,OP_EQ, b, NTOR_ONIONSKIN_LEN+20);
- tt_int_op(0, OP_EQ, extend_cell_format(&p2_cmd, &p2_len, p2, &ec));
- tt_int_op(p2_cmd, OP_EQ, RELAY_COMMAND_EXTEND);
- tt_int_op(p2_len, OP_EQ, 26+TAP_ONIONSKIN_CHALLENGE_LEN);
- tt_mem_op(p2,OP_EQ, p, RELAY_PAYLOAD_SIZE);
- tt_int_op(0, OP_EQ, create_cell_format_relayed(&cell, cc));
-
/* Now let's do a minimal ntor EXTEND2 cell. */
memset(&ec, 0xff, sizeof(ec));
memset(p, 0, sizeof(p));
@@ -896,23 +786,6 @@ test_cfmt_extended_cells(void *arg)
(void) arg;
- /* Try a regular EXTENDED cell. */
- memset(&ec, 0xff, sizeof(ec));
- memset(p, 0, sizeof(p));
- memset(b, 0, sizeof(b));
- crypto_rand((char*)b, TAP_ONIONSKIN_REPLY_LEN);
- memcpy(p,b,TAP_ONIONSKIN_REPLY_LEN);
- tt_int_op(0, OP_EQ, extended_cell_parse(&ec, RELAY_COMMAND_EXTENDED, p,
- TAP_ONIONSKIN_REPLY_LEN));
- tt_int_op(RELAY_COMMAND_EXTENDED, OP_EQ, ec.cell_type);
- tt_int_op(cc->cell_type, OP_EQ, CELL_CREATED);
- tt_int_op(cc->handshake_len, OP_EQ, TAP_ONIONSKIN_REPLY_LEN);
- tt_mem_op(cc->reply,OP_EQ, b, TAP_ONIONSKIN_REPLY_LEN);
- tt_int_op(0, OP_EQ, extended_cell_format(&p2_cmd, &p2_len, p2, &ec));
- tt_int_op(RELAY_COMMAND_EXTENDED, OP_EQ, p2_cmd);
- tt_int_op(TAP_ONIONSKIN_REPLY_LEN, OP_EQ, p2_len);
- tt_mem_op(p2,OP_EQ, p, sizeof(p2));
-
/* Try an EXTENDED2 cell */
memset(&ec, 0xff, sizeof(ec));
memset(p, 0, sizeof(p));
diff --git a/src/test/test_circuitpadding.c b/src/test/test_circuitpadding.c
index 63b7136a11..95401465c1 100644
--- a/src/test/test_circuitpadding.c
+++ b/src/test/test_circuitpadding.c
@@ -1608,7 +1608,7 @@ simulate_single_hop_extend(circuit_t *client, circuit_t *mid_relay,
hop->extend_info = extend_info_new(
padding ? "padding" : "non-padding",
- digest, NULL, NULL, NULL,
+ digest, NULL, NULL,
&addr, padding, NULL, false);
cpath_init_circuit_crypto(hop, whatevs_key, sizeof(whatevs_key), 0, 0);
diff --git a/src/test/test_conflux_pool.c b/src/test/test_conflux_pool.c
index fc30677377..6fe3c8b65b 100644
--- a/src/test/test_conflux_pool.c
+++ b/src/test/test_conflux_pool.c
@@ -349,7 +349,7 @@ simulate_single_hop_extend(origin_circuit_t *client, int exit)
hop->extend_info = extend_info_new(
exit ? "exit" : "non-exit",
- digest, NULL, NULL, NULL,
+ digest, NULL, NULL,
&addr, exit, NULL, exit);
cpath_init_circuit_crypto(hop, whatevs_key, sizeof(whatevs_key), 0, 0);
@@ -396,6 +396,7 @@ test_setup(void)
static void
test_clear_circs(void)
{
+ conflux_notify_shutdown();
SMARTLIST_FOREACH(circ_pairs, circ_pair_t *, circ_pair, {
tor_free(circ_pair);
});
@@ -430,6 +431,9 @@ test_clear_circs(void)
tor_assert(smartlist_len(mock_cell_delivery) == 0);
(void)free_fake_origin_circuit;
+
+ /* Clear shutdown flag so we can resume testing again. */
+ conflux_clear_shutdown();
}
static void
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index d09afcb9e6..b34711dcad 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -217,7 +217,7 @@ basic_routerinfo_new(const char *nickname, uint32_t ipv4_addr,
r1->ipv4_dirport = dir_port;
r1->supports_tunnelled_dir_requests = 1;
- router_set_rsa_onion_pkey(pk1, &r1->onion_pkey, &r1->onion_pkey_len);
+ router_set_rsa_onion_pkey(pk1, &r1->tap_onion_pkey, &r1->tap_onion_pkey_len);
r1->identity_pkey = pk2;
r1->bandwidthrate = bandwidthrate;
@@ -382,8 +382,8 @@ get_new_onion_key_block(const routerinfo_t *r1)
{
char *block = NULL;
tor_assert(r1);
- crypto_pk_t *pk_tmp = router_get_rsa_onion_pkey(r1->onion_pkey,
- r1->onion_pkey_len);
+ crypto_pk_t *pk_tmp = router_get_rsa_onion_pkey(r1->tap_onion_pkey,
+ r1->tap_onion_pkey_len);
block = get_new_rsa_key_block("onion-key", pk_tmp);
crypto_pk_free(pk_tmp);
return block;
@@ -587,8 +587,8 @@ setup_mocks_for_fresh_descriptor(const routerinfo_t *r1,
if (rsa_onion_keypair) {
mocked_onionkey = crypto_pk_dup_key(rsa_onion_keypair);
} else {
- mocked_onionkey = router_get_rsa_onion_pkey(r1->onion_pkey,
- r1->onion_pkey_len);
+ mocked_onionkey = router_get_rsa_onion_pkey(r1->tap_onion_pkey,
+ r1->tap_onion_pkey_len);
}
MOCK(get_onion_key, mock_get_onion_key);
}
@@ -643,10 +643,12 @@ STMT_BEGIN \
tt_int_op(rp1->bandwidthrate,OP_EQ, r1->bandwidthrate); \
tt_int_op(rp1->bandwidthburst,OP_EQ, r1->bandwidthburst); \
tt_int_op(rp1->bandwidthcapacity,OP_EQ, r1->bandwidthcapacity); \
- crypto_pk_t *rp1_onion_pkey = router_get_rsa_onion_pkey(rp1->onion_pkey, \
- rp1->onion_pkey_len); \
- crypto_pk_t *r1_onion_pkey = router_get_rsa_onion_pkey(r1->onion_pkey, \
- r1->onion_pkey_len); \
+ crypto_pk_t *rp1_onion_pkey = router_get_rsa_onion_pkey( \
+ rp1->tap_onion_pkey, \
+ rp1->tap_onion_pkey_len); \
+ crypto_pk_t *r1_onion_pkey = router_get_rsa_onion_pkey( \
+ r1->tap_onion_pkey, \
+ r1->tap_onion_pkey_len); \
tt_int_op(crypto_pk_cmp_keys(rp1_onion_pkey, r1_onion_pkey), OP_EQ, 0); \
crypto_pk_free(rp1_onion_pkey); \
crypto_pk_free(r1_onion_pkey); \
@@ -1303,6 +1305,72 @@ test_dir_parse_router_list(void *arg)
#undef ADD
}
+/* Made with chutney and a patched tor: Has no onion-key or
+ * onion-key-crosscert */
+static const char ROUTERDESC_NO_ONION_KEY[] =
+"router test001a 127.0.0.1 5001 0 7001\n"
+"identity-ed25519\n"
+"-----BEGIN ED25519 CERT-----\n"
+"AQQAB0xWARbCJfDrX0OTtpM0fDxU9cLweMnZeUq/KBfAN1wwWHtMAQAgBADBQJ1o\n"
+"ClrXUenWC90FYEUQDpMSdxdxKlrR83rYy+keGe61WQHYP0ebowJC19UvPnYryLeA\n"
+"Gnhko2WwmbUDGicdnY4j2VSFU15oxBjln65IznZJyiZM4zGE1GkNZzKGmQY=\n"
+"-----END ED25519 CERT-----\n"
+"master-key-ed25519 wUCdaApa11Hp1gvdBWBFEA6TEncXcSpa0fN62MvpHhk\n"
+"or-address [::]:5001\n"
+"platform Tor 0.4.9.0-alpha-dev on Linux\n"
+"proto Conflux=1 Cons=1-2 Desc=1-2 DirCache=2 FlowCtrl=1-2 HSDir=2 "
+ "HSIntro=4-5 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Padding=2 "
+ "Relay=1-4\n"
+"published 2024-06-24 21:34:22\n"
+"fingerprint FD3A 6FA4 E716 C379 3CBA FEC3 39EA 01C8 B49D 7189\n"
+"uptime 0\n"
+"bandwidth 1073741824 1073741824 0\n"
+"extra-info-digest 9946CAC41485EDFFDD83F7DAF1A088C30563126C "
+ "lpAMRlRTy9QR2xVCu1nnnxOHA2I05TTKvCSPPcr1geo\n"
+"caches-extra-info\n"
+"signing-key\n"
+"-----BEGIN RSA PUBLIC KEY-----\n"
+"MIGJAoGBALcIIij7gNpvSZPvaCLDDNyyQZq7fR0aXiHgmiIc5hYVcBl+zF5sTX6a\n"
+"jQF+GQdbSHcRzA1IMWPXnA7+nGOxSNayrQwExuf7ESsBaQHU81/dmV+rgTwtcd3K\n"
+"9lobTQUm+idLvGjVF5P1XJkduPvURIgpIfXT1ZHJUQhwxWSw8MmnAgMBAAE=\n"
+"-----END RSA PUBLIC KEY-----\n"
+"ntor-onion-key-crosscert 1\n"
+"-----BEGIN ED25519 CERT-----\n"
+"AQoAB0wmAcFAnWgKWtdR6dYL3QVgRRAOkxJ3F3EqWtHzetjL6R4ZAFPSCMLyQ82v\n"
+"dvcpZDa7C/qp8TsJn2Z8v77RjRc2QD1KYDzGfg5euwlB1lu8+IR38l3mmC1PXXhe\n"
+"ZB84q4aUdAA=\n"
+"-----END ED25519 CERT-----\n"
+"hidden-service-dir\n"
+"contact auth1@test.test\n"
+"ntor-onion-key m0dedSB2vjtvz08bNu+LCdIApVuspRlzXbsphXZ62zQ\n"
+"reject *:*\n"
+"tunnelled-dir-server\n"
+"router-sig-ed25519 VMwmiN9KhWWFSFSuVZxG1g46mb2QhMhv0UlatvPKyAV+1jPl"
+ "EbDFaO1Qur0335Rn0ToysC6UqB1p78pefX67Aw\n"
+"router-signature\n"
+"-----BEGIN SIGNATURE-----\n"
+"q9Hxy4FJVIK2ks/ByBv8P1p7Pc68ie/TTlDN+tce9opPlijy9+ze9/Gd2SKonRm1\n"
+"J+WBj/kKYKw+YoUExIT0qMfa6QTCOe/ecp1sNmgeW0YfloP4Nv8goi3S0k4yrPk/\n"
+"qw6TIXGYJpvrdR1Qe7+MEl2K1Okqsy5amtOU400lYRA=\n"
+"-----END SIGNATURE-----\n"
+ ;
+
+static void
+test_dir_parse_no_onion_keyrouter_list(void *arg)
+{
+ (void) arg;
+
+ routerinfo_t *ri =
+ router_parse_entry_from_string(ROUTERDESC_NO_ONION_KEY, NULL,
+ 0, 1, 0, NULL);
+
+ tt_assert(ri);
+ tt_assert(ri->tap_onion_pkey == NULL);
+
+ done:
+ routerinfo_free(ri);
+}
+
static download_status_t dls_minimal;
static download_status_t dls_maximal;
static download_status_t dls_bad_fingerprint;
@@ -4079,7 +4147,7 @@ gen_routerstatus_for_umbw(int idx, time_t now)
if (vrs) {
vrs->microdesc = tor_malloc_zero(sizeof(vote_microdesc_hash_t));
tor_asprintf(&vrs->microdesc->microdesc_hash_line,
- "m 25,26,27,28 "
+ "m 32,33 "
"sha256=xyzajkldsdsajdadlsdjaslsdksdjlsdjsdaskdaaa%d\n",
idx);
}
@@ -4103,9 +4171,8 @@ vote_tweaks_for_umbw(networkstatus_t *v, int voter, time_t now)
tt_assert(v->supported_methods);
SMARTLIST_FOREACH(v->supported_methods, char *, c, tor_free(c));
smartlist_clear(v->supported_methods);
- /* Method 17 is MIN_METHOD_TO_CLIP_UNMEASURED_BW_KB */
smartlist_split_string(v->supported_methods,
- "25 26 27 28",
+ "32 33",
NULL, 0, -1);
/* If we're using a non-default clip bandwidth, add it to net_params */
if (alternate_clip_bw > 0) {
@@ -7228,6 +7295,7 @@ struct testcase_t dir_tests[] = {
DIR(routerinfo_parsing, 0),
DIR(extrainfo_parsing, 0),
DIR(parse_router_list, TT_FORK),
+ DIR(parse_no_onion_keyrouter_list, TT_FORK),
DIR(load_routers, TT_FORK),
DIR(load_extrainfo, TT_FORK),
DIR(getinfo_extra, 0),
diff --git a/src/test/test_dirvote.c b/src/test/test_dirvote.c
index 2b53955107..bb7e6fdf10 100644
--- a/src/test/test_dirvote.c
+++ b/src/test/test_dirvote.c
@@ -656,30 +656,6 @@ done:
ROUTER_FREE(pppp);
}
-static void
-test_dirvote_parse_param_buggy(void *arg)
-{
- (void)arg;
-
- /* Tests for behavior with bug emulation to migrate away from bug 19011. */
- tt_i64_op(extract_param_buggy("blah blah", "bwweightscale", 10000),
- OP_EQ, 10000);
- tt_i64_op(extract_param_buggy("bwweightscale=7", "bwweightscale", 10000),
- OP_EQ, 7);
- tt_i64_op(extract_param_buggy("bwweightscale=7 foo=9",
- "bwweightscale", 10000),
- OP_EQ, 10000);
- tt_i64_op(extract_param_buggy("foo=7 bwweightscale=777 bar=9",
- "bwweightscale", 10000),
- OP_EQ, 10000);
- tt_i64_op(extract_param_buggy("foo=7 bwweightscale=1234",
- "bwweightscale", 10000),
- OP_EQ, 1234);
-
- done:
- ;
-}
-
#define NODE(name, flags) \
{ \
#name, test_dirvote_##name, (flags), NULL, NULL \
@@ -692,5 +668,4 @@ struct testcase_t dirvote_tests[] = {
NODE(get_sybil_by_ip_version_ipv4, TT_FORK),
NODE(get_sybil_by_ip_version_ipv6, TT_FORK),
NODE(get_all_possible_sybil, TT_FORK),
- NODE(parse_param_buggy, 0),
END_OF_TESTCASES};
diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c
index 118b66dfa7..7184e49c8c 100644
--- a/src/test/test_entrynodes.c
+++ b/src/test/test_entrynodes.c
@@ -1942,8 +1942,10 @@ test_entry_guard_select_for_circuit_no_confirmed(void *arg)
tt_ptr_op(g2, OP_EQ, g);
/* But if we impose a restriction, we don't get the same guard */
+ get_options_mutable()->EnforceDistinctSubnets = 0;
rst = guard_create_exit_restriction((uint8_t*)g->identity);
g2 = select_entry_guard_for_circuit(gs, GUARD_USAGE_TRAFFIC, rst, &state);
+ tt_assert(g2);
tt_ptr_op(g2, OP_NE, g);
done:
diff --git a/src/test/test_hs_client.c b/src/test/test_hs_client.c
index a02dca1b60..ac6f940cc7 100644
--- a/src/test/test_hs_client.c
+++ b/src/test/test_hs_client.c
@@ -1192,7 +1192,7 @@ test_socks_hs_errors(void *arg)
ocirc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
/* Code path will log this exit so build it. */
ocirc->build_state->chosen_exit = extend_info_new("TestNickname", digest,
- NULL, NULL, NULL, &addr,
+ NULL, NULL, &addr,
4242, NULL, false);
/* Attach socks connection to this rendezvous circuit. */
ocirc->p_streams = ENTRY_TO_EDGE_CONN(socks_conn);
@@ -1287,7 +1287,7 @@ test_close_intro_circuit_failure(void *arg)
ocirc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
/* Code path will log this exit so build it. */
ocirc->build_state->chosen_exit = extend_info_new("TestNickname", digest,
- NULL, NULL, NULL, &addr,
+ NULL, NULL, &addr,
4242, NULL, false);
ed25519_pubkey_copy(&ocirc->hs_ident->intro_auth_pk, &intro_kp.pubkey);
@@ -1314,7 +1314,7 @@ test_close_intro_circuit_failure(void *arg)
ocirc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
/* Code path will log this exit so build it. */
ocirc->build_state->chosen_exit = extend_info_new("TestNickname", digest,
- NULL, NULL, NULL, &addr,
+ NULL, NULL, &addr,
4242, NULL, false);
ed25519_pubkey_copy(&ocirc->hs_ident->intro_auth_pk, &intro_kp.pubkey);
@@ -1337,7 +1337,7 @@ test_close_intro_circuit_failure(void *arg)
ocirc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
/* Code path will log this exit so build it. */
ocirc->build_state->chosen_exit = extend_info_new("TestNickname", digest,
- NULL, NULL, NULL, &addr,
+ NULL, NULL, &addr,
4242, NULL, false);
ed25519_pubkey_copy(&ocirc->hs_ident->intro_auth_pk, &intro_kp.pubkey);
diff --git a/src/test/test_hs_service.c b/src/test/test_hs_service.c
index dc60c7ca29..6f254f16e8 100644
--- a/src/test/test_hs_service.c
+++ b/src/test/test_hs_service.c
@@ -1605,7 +1605,6 @@ test_build_update_descriptors(void *arg)
tt_int_op(ret, OP_EQ, 0);
ri.onion_curve25519_pkey =
tor_malloc_zero(sizeof(curve25519_public_key_t));
- ri.onion_pkey = tor_malloc_zero(140);
curve25519_public_key_generate(ri.onion_curve25519_pkey,
&curve25519_secret_key);
memset(ri.cache_info.identity_digest, 'A', DIGEST_LEN);
@@ -1631,7 +1630,6 @@ test_build_update_descriptors(void *arg)
update_all_descriptors_intro_points(now);
tor_free(node->ri->onion_curve25519_pkey); /* Avoid memleak. */
tor_free(node->ri->cache_info.signing_key_cert);
- tor_free(node->ri->onion_pkey);
expect_log_msg_containing("just picked 1 intro points and wanted 3 for next "
"descriptor. It currently has 0 intro points. "
"Launching ESTABLISH_INTRO circuit shortly.");
diff --git a/src/test/test_microdesc.c b/src/test/test_microdesc.c
index c564805ecf..1209811fb9 100644
--- a/src/test/test_microdesc.c
+++ b/src/test/test_microdesc.c
@@ -366,37 +366,14 @@ static const char test_ri[] =
"iFJkKxxDx7ksxX0zdl7aPT4ORFEuRhCYS6el7YJmoyg=\n"
"-----END SIGNATURE-----\n";
-static const char test_md2_25[] =
+static const char test_md2_withfamily_33[] =
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAMvEJ/JVNK7I38PPWhQMuCgkET/ki4WIas4tj5Kmqfb9kHqxMR+EunRD\n"
"83k4pel1yB7QdV+iTd/4SZOI8RpZP+BO1KnOTWfpztAU1lDGr19/PwdwcHaILpBD\n"
"nNzm6otk4/bKUQ0vqpOfJljtg0DfAm4uMAQ6BMFy6uEAF7+JupuPAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key FChIfm77vrWB7JsxQ+jMbN6VSSp1P0DYbw/2aqey4iA=\n"
- "p accept 1-65535\n"
- "id ed25519 J5lkRqyL6qW+CpN3E4RIlgJZeLgwjtmOOrjZvVhuwLQ\n";
-
-static const char test_md2_withfamily_28[] =
- "onion-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAMvEJ/JVNK7I38PPWhQMuCgkET/ki4WIas4tj5Kmqfb9kHqxMR+EunRD\n"
- "83k4pel1yB7QdV+iTd/4SZOI8RpZP+BO1KnOTWfpztAU1lDGr19/PwdwcHaILpBD\n"
- "nNzm6otk4/bKUQ0vqpOfJljtg0DfAm4uMAQ6BMFy6uEAF7+JupuPAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key FChIfm77vrWB7JsxQ+jMbN6VSSp1P0DYbw/2aqey4iA=\n"
- "family OtherNode !Strange\n"
- "p accept 1-65535\n"
- "id ed25519 J5lkRqyL6qW+CpN3E4RIlgJZeLgwjtmOOrjZvVhuwLQ\n";
-
-static const char test_md2_withfamily_29[] =
- "onion-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAMvEJ/JVNK7I38PPWhQMuCgkET/ki4WIas4tj5Kmqfb9kHqxMR+EunRD\n"
- "83k4pel1yB7QdV+iTd/4SZOI8RpZP+BO1KnOTWfpztAU1lDGr19/PwdwcHaILpBD\n"
- "nNzm6otk4/bKUQ0vqpOfJljtg0DfAm4uMAQ6BMFy6uEAF7+JupuPAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key FChIfm77vrWB7JsxQ+jMbN6VSSp1P0DYbw/2aqey4iA=\n"
+ "ntor-onion-key FChIfm77vrWB7JsxQ+jMbN6VSSp1P0DYbw/2aqey4iA\n"
"family !Strange $D219590AC9513BCDEBBA9AB721007A4CC01BBAE3 othernode\n"
"p accept 1-65535\n"
"id ed25519 J5lkRqyL6qW+CpN3E4RIlgJZeLgwjtmOOrjZvVhuwLQ\n";
@@ -411,21 +388,12 @@ test_md_generate(void *arg)
ri = router_parse_entry_from_string(test_ri, NULL, 0, 0, NULL, NULL);
tt_assert(ri);
- md = dirvote_create_microdescriptor(ri, 25);
- tt_str_op(md->body, OP_EQ, test_md2_25);
- tt_assert(ed25519_pubkey_eq(md->ed25519_identity_pkey,
- &ri->cache_info.signing_key_cert->signing_key));
-
// Try family encoding.
microdesc_free(md);
ri->declared_family = smartlist_new();
smartlist_add_strdup(ri->declared_family, "OtherNode !Strange");
- md = dirvote_create_microdescriptor(ri, 28);
- tt_str_op(md->body, OP_EQ, test_md2_withfamily_28);
-
- microdesc_free(md);
- md = dirvote_create_microdescriptor(ri, 29);
- tt_str_op(md->body, OP_EQ, test_md2_withfamily_29);
+ md = dirvote_create_microdescriptor(ri, 33);
+ tt_str_op(md->body, OP_EQ, test_md2_withfamily_33);
done:
microdesc_free(md);
@@ -792,6 +760,35 @@ test_md_parse_id_ed25519(void *arg)
teardown_capture_of_logs();
}
+static void
+test_md_parse_no_onion_key(void *arg)
+{
+ (void)arg;
+
+ /* A correct MD with no onion key. */
+ const char GOOD_MD[] =
+ "onion-key\n"
+ "ntor-onion-key AppBt6CSeb1kKid/36ototmFA24ddfW5JpjWPLuoJgs=\n"
+ "id ed25519 VGhpcyBpc24ndCBhY3R1YWxseSBhIHB1YmxpYyBrZXk\n";
+
+ smartlist_t *mds = NULL;
+
+ mds = microdescs_parse_from_string(GOOD_MD,
+ NULL, 1, SAVED_NOWHERE, NULL);
+ tt_assert(mds);
+ tt_int_op(smartlist_len(mds), OP_EQ, 1);
+ const microdesc_t *md = smartlist_get(mds, 0);
+ tt_mem_op(md->ed25519_identity_pkey, OP_EQ,
+ "This isn't actually a public key", ED25519_PUBKEY_LEN);
+
+ done:
+ if (mds) {
+ SMARTLIST_FOREACH(mds, microdesc_t *, m, microdesc_free(m));
+ smartlist_free(mds);
+ }
+ teardown_capture_of_logs();
+}
+
static int mock_rgsbd_called = 0;
static routerstatus_t *mock_rgsbd_val_a = NULL;
static routerstatus_t *mock_rgsbd_val_b = NULL;
@@ -926,6 +923,7 @@ struct testcase_t microdesc_tests[] = {
{ "generate", test_md_generate, 0, NULL, NULL },
{ "parse", test_md_parse, 0, NULL, NULL },
{ "parse_id_ed25519", test_md_parse_id_ed25519, 0, NULL, NULL },
+ { "parse_no_onion_key", test_md_parse_no_onion_key, 0, NULL, NULL },
{ "reject_cache", test_md_reject_cache, TT_FORK, NULL, NULL },
{ "corrupt_desc", test_md_corrupt_desc, TT_FORK, NULL, NULL },
END_OF_TESTCASES
diff --git a/src/test/test_protover.c b/src/test/test_protover.c
index 9d14fd678a..9a10cf649f 100644
--- a/src/test/test_protover.c
+++ b/src/test/test_protover.c
@@ -329,7 +329,7 @@ test_protover_supports_version(void *arg)
* headers. */
#define PROTOVER_LINKAUTH_V1 1
#define PROTOVER_LINKAUTH_V2 2
-#define PROTOVER_RELAY_V1 1
+#define PROTOVER_RELAY_V2 2
/* Deprecated HSIntro versions */
#define PROTOVER_HS_INTRO_DEPRECATED_1 1
@@ -397,7 +397,7 @@ test_protover_supported_protocols(void *arg)
/* Relay protovers do not appear anywhere in the code. */
tt_assert(protocol_list_supports_protocol(supported_protocols,
PRT_RELAY,
- PROTOVER_RELAY_V1));
+ PROTOVER_RELAY_V2));
tt_assert(protocol_list_supports_protocol(supported_protocols,
PRT_RELAY,
PROTOVER_RELAY_EXTEND2));
diff --git a/src/test/test_router.c b/src/test/test_router.c
index 47084bba01..64efedfa46 100644
--- a/src/test/test_router.c
+++ b/src/test/test_router.c
@@ -60,8 +60,8 @@ rtr_tests_gen_routerinfo(crypto_pk_t *ident_key, crypto_pk_t *tap_key)
mock_routerinfo->identity_pkey = crypto_pk_dup_key(ident_key);
mock_routerinfo->protocol_list =
tor_strdup("Cons=1-2 Desc=1-2 DirCache=1-2");
- router_set_rsa_onion_pkey(tap_key, &mock_routerinfo->onion_pkey,
- &mock_routerinfo->onion_pkey_len);
+ router_set_rsa_onion_pkey(tap_key, &mock_routerinfo->tap_onion_pkey,
+ &mock_routerinfo->tap_onion_pkey_len);
mock_routerinfo->bandwidthrate = 9001;
mock_routerinfo->bandwidthburst = 9002;
diff --git a/src/test/test_sandbox.c b/src/test/test_sandbox.c
index 64182ecc91..edb5c0c232 100644
--- a/src/test/test_sandbox.c
+++ b/src/test/test_sandbox.c
@@ -364,22 +364,32 @@ test_sandbox_crypto_equix(void *arg)
struct testcase_t sandbox_tests[] = {
SANDBOX_TEST(is_active, TT_FORK),
-/* When Tor is built with fragile compiler-hardening the sandbox is unable to
- * filter requests to open files or directories (on systems where glibc uses
- * the "open" system call to provide this functionality), as doing so would
+/* When Tor is built with fragile compiler-hardening the sandbox is usually
+ * unable to filter requests to open files or directories, as doing so would
* interfere with the address sanitizer as it retrieves information about the
* running process via the filesystem. Skip these tests in that case as the
* corresponding functions are likely to have no effect and this will cause the
* tests to fail. */
#ifdef ENABLE_FRAGILE_HARDENING
SANDBOX_TEST_SKIPPED(open_filename),
+ SANDBOX_TEST_SKIPPED(openat_filename),
SANDBOX_TEST_SKIPPED(opendir_dirname),
#else
SANDBOX_TEST_IN_SANDBOX(open_filename),
- SANDBOX_TEST_IN_SANDBOX(opendir_dirname),
+ SANDBOX_TEST_IN_SANDBOX(openat_filename),
#endif /* defined(ENABLE_FRAGILE_HARDENING) */
- SANDBOX_TEST_IN_SANDBOX(openat_filename),
+ /* Ok why... Quick answer is #40918. This has been failing on Debian SID
+ * making us unable to have nightly packages which is a problem as we have
+ * several relay operators using them and actively reporting us issues with
+ * them. This test fails due to the sandbox denying it.
+ *
+ * We are deprecating C-tor slowly and honestly, the Sandbox feature has
+ * always been a source of pain and unhappiness. Disable this as finding why,
+ * fixing it and hoping it doesn't come back will mostly be a waste of our
+ * time at this point. */
+ SANDBOX_TEST_SKIPPED(opendir_dirname),
+
SANDBOX_TEST_IN_SANDBOX(chmod_filename),
SANDBOX_TEST_IN_SANDBOX(chown_filename),
SANDBOX_TEST_IN_SANDBOX(rename_filename),
diff --git a/src/test/test_socks.c b/src/test/test_socks.c
index 94c772419b..b642d24a8b 100644
--- a/src/test/test_socks.c
+++ b/src/test/test_socks.c
@@ -596,6 +596,70 @@ test_socks_5_authenticate_with_data(void *ptr)
;
}
+/** Perform SOCKS 5 authentication and send data all in one go */
+static void
+test_socks_5_authenticate_with_rpc_objectid(void *ptr)
+{
+ SOCKS_TEST_INIT();
+
+ /* SOCKS 5 Negotiate username/password authentication */
+ ADD_DATA(buf, "\x05\x01\x02");
+ tt_assert(!fetch_from_buf_socks(buf, socks,
+ get_options()->TestSocks,
+ get_options()->SafeSocks));
+ /* SOCKS 5 Send username/password as a RPC ObjectID (see prop351). This
+ * should be invalid as in only the objectID prefix without a version. */
+ ADD_DATA(buf, "\x01\x08<torS0X>\x08password");
+ tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks), OP_EQ, -1);
+
+ buf_clear(buf);
+ socks_request_clear(socks);
+
+ /* SOCKS 5 Negotiate username/password authentication */
+ ADD_DATA(buf, "\x05\x01\x02");
+ tt_assert(!fetch_from_buf_socks(buf, socks,
+ get_options()->TestSocks,
+ get_options()->SafeSocks));
+ /* SOCKS 5 Send username/password as a RPC ObjectID (see prop351). This
+ * should be valid because it is exactly the prefix and version without an
+ * object ID. */
+ ADD_DATA(buf, "\x01\x09<torS0X>0\x08password");
+ tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks), OP_EQ, 0);
+
+ buf_clear(buf);
+ socks_request_clear(socks);
+
+ /* SOCKS 5 Negotiate username/password authentication */
+ ADD_DATA(buf, "\x05\x01\x02");
+ tt_assert(!fetch_from_buf_socks(buf, socks,
+ get_options()->TestSocks,
+ get_options()->SafeSocks));
+ /* SOCKS 5 Send username/password as a RPC ObjectID (see prop351). This
+ * should be invalid as an unknown version per prop351. */
+ ADD_DATA(buf, "\x01\x09<torS0X>1\x08password");
+ tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks), OP_EQ, -1);
+
+ buf_clear(buf);
+ socks_request_clear(socks);
+
+ /* SOCKS 5 Negotiate username/password authentication */
+ ADD_DATA(buf, "\x05\x01\x02");
+ tt_assert(!fetch_from_buf_socks(buf, socks,
+ get_options()->TestSocks,
+ get_options()->SafeSocks));
+ /* SOCKS 5 Send username/password as a RPC ObjectID (see prop351). This
+ * should be invalid because there is an objectID after the prefix. */
+ ADD_DATA(buf, "\x01\x0C<torS0X>0abc\x08password");
+ tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks), OP_EQ, -1);
+
+ done:
+ ;
+}
+
/** Try to negotiate an unsupported authentication type */
static void
test_socks_5_auth_unsupported_type(void *ptr)
@@ -1112,6 +1176,7 @@ struct testcase_t socks_tests[] = {
SOCKSENT(5_authenticate),
SOCKSENT(5_authenticate_empty_user_pass),
SOCKSENT(5_authenticate_with_data),
+ SOCKSENT(5_authenticate_with_rpc_objectid),
SOCKSENT(5_malformed_commands),
SOCKSENT(5_bad_arguments),
diff --git a/src/test/test_status.c b/src/test/test_status.c
index 1d371645ae..4ceb81f3a5 100644
--- a/src/test/test_status.c
+++ b/src/test/test_status.c
@@ -333,10 +333,12 @@ test_status_hb_not_in_consensus(void *arg)
status_hb_not_in_consensus_server_mode);
log_global_min_severity_ = LOG_DEBUG;
- onion_handshakes_requested[ONION_HANDSHAKE_TYPE_TAP] = 1;
onion_handshakes_assigned[ONION_HANDSHAKE_TYPE_TAP] = 1;
- onion_handshakes_requested[ONION_HANDSHAKE_TYPE_NTOR] = 1;
- onion_handshakes_assigned[ONION_HANDSHAKE_TYPE_NTOR] = 1;
+ onion_handshakes_requested[ONION_HANDSHAKE_TYPE_TAP] = 2;
+ onion_handshakes_assigned[ONION_HANDSHAKE_TYPE_NTOR] = 3;
+ onion_handshakes_requested[ONION_HANDSHAKE_TYPE_NTOR] = 4;
+ onion_handshakes_assigned[ONION_HANDSHAKE_TYPE_NTOR_V3] = 5;
+ onion_handshakes_requested[ONION_HANDSHAKE_TYPE_NTOR_V3] = 6;
expected = 0;
setup_capture_of_logs(LOG_INFO);
@@ -352,8 +354,8 @@ test_status_hb_not_in_consensus(void *arg)
"I've made 0 connections with IPv4 and 0 with IPv6.\n");
expect_log_msg("Average packaged cell fullness: 100.000%. "
"TLS write overhead: 0%\n");
- expect_log_msg("Circuit handshake stats since last time: 1/1 TAP, "
- "1/1 NTor.\n");
+ expect_log_msg("Circuit handshake stats since last time: 1/2 TAP, "
+ "3/4 NTor, 5/6 NTor (v3).\n");
expect_log_msg("Since startup we initiated 0 and received 0 v1 "
"connections; initiated 0 and received 0 v2 connections; "
"initiated 0 and received 0 v3 connections; "
@@ -363,6 +365,7 @@ test_status_hb_not_in_consensus(void *arg)
"with too many cells, [DoSCircuitCreationEnabled disabled], "
"[DoSConnectionEnabled disabled], "
"[DoSRefuseSingleHopClientRendezvous disabled], "
+ "[DoSStreamCreationEnabled disabled], "
"0 INTRODUCE2 rejected.\n");
tt_int_op(mock_saved_log_n_entries(), OP_EQ, 6);
diff --git a/src/tools/tor-resolve.c b/src/tools/tor-resolve.c
index ad52fdaa22..33e565dac4 100644
--- a/src/tools/tor-resolve.c
+++ b/src/tools/tor-resolve.c
@@ -385,7 +385,7 @@ do_resolve(const char *hostname,
tor_addr_make_unspec(result_addr);
*result_hostname = NULL;
- s = tor_open_socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
+ s = tor_open_socket(sockshost->family,SOCK_STREAM,IPPROTO_TCP);
if (s<0) {
log_sock_error("creating_socket", -1);
return -1;