summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/app/config/config.c1
-rw-r--r--src/app/config/or_options_st.h7
-rw-r--r--src/core/mainloop/connection.c55
-rw-r--r--src/core/mainloop/connection.h5
-rw-r--r--src/core/or/channel.c2
-rw-r--r--src/core/or/channeltls.c2
-rw-r--r--src/core/or/circuitbuild.c2
-rw-r--r--src/core/or/circuitlist.c2
-rw-r--r--src/core/or/circuitpadding.c9
-rw-r--r--src/core/or/circuituse.c2
-rw-r--r--src/core/or/connection_edge.c6
-rw-r--r--src/core/or/crypt_path.c2
-rw-r--r--src/core/or/dos.c4
-rw-r--r--src/core/or/dos.h3
-rw-r--r--src/core/or/onion.c2
-rw-r--r--src/core/or/policies.c2
-rw-r--r--src/core/or/reasons.c2
-rw-r--r--src/core/or/relay.c2
-rw-r--r--src/core/or/scheduler.c4
-rw-r--r--src/core/or/sendme.c2
-rw-r--r--src/core/proto/proto_socks.c9
-rw-r--r--src/ext/csiphash.c14
-rw-r--r--src/ext/ed25519/donna/ed25519_tor.c4
-rw-r--r--src/ext/ed25519/donna/modm-donna-32bit.h48
-rw-r--r--src/ext/ed25519/donna/modm-donna-64bit.h24
-rw-r--r--src/feature/client/entrynodes.c2
-rw-r--r--src/feature/control/btrack_orconn_cevent.c1
-rw-r--r--src/feature/control/control.c4
-rw-r--r--src/feature/control/control_cmd.c2
-rw-r--r--src/feature/control/control_events.c32
-rw-r--r--src/feature/dirauth/keypin.c2
-rw-r--r--src/feature/dirauth/shared_random_state.c3
-rw-r--r--src/feature/dircache/dircache.c13
-rw-r--r--src/feature/dirclient/dirclient.c2
-rw-r--r--src/feature/dirparse/parsecommon.c11
-rw-r--r--src/feature/hs/hs_client.c17
-rw-r--r--src/feature/hs/hs_service.c6
-rw-r--r--src/feature/nodelist/dirlist.c31
-rw-r--r--src/feature/nodelist/dirlist.h2
-rw-r--r--src/feature/nodelist/nodelist.c43
-rw-r--r--src/feature/nodelist/nodelist.h2
-rw-r--r--src/feature/relay/dns.c4
-rw-r--r--src/feature/rend/rendclient.c2
-rw-r--r--src/lib/cc/compat_compiler.h6
-rw-r--r--src/lib/crypt_ops/crypto_digest_nss.c29
-rw-r--r--src/lib/crypt_ops/crypto_digest_openssl.c10
-rw-r--r--src/lib/crypt_ops/crypto_ed25519.c2
-rw-r--r--src/lib/crypt_ops/crypto_rsa.c27
-rw-r--r--src/lib/crypt_ops/crypto_rsa.h5
-rw-r--r--src/lib/crypt_ops/crypto_rsa_nss.c14
-rw-r--r--src/lib/crypt_ops/crypto_rsa_openssl.c70
-rw-r--r--src/lib/err/torerr.c31
-rw-r--r--src/lib/err/torerr.h1
-rw-r--r--src/lib/err/torerr_sys.c5
-rw-r--r--src/lib/log/log.c36
-rw-r--r--src/lib/log/log.h1
-rw-r--r--src/lib/log/util_bug.c4
-rw-r--r--src/lib/log/util_bug.h2
-rw-r--r--src/lib/net/address.c1
-rw-r--r--src/lib/tls/buffers_tls.c4
-rw-r--r--src/test/test_address_set.c15
-rw-r--r--src/test/test_bwmgt.c209
-rw-r--r--src/test/test_controller_events.c39
-rw-r--r--src/test/test_crypto.c39
-rw-r--r--src/test/test_dos.c24
-rw-r--r--src/test/test_socks.c2
-rw-r--r--src/test/testing_common.c15
-rw-r--r--src/win32/orconfig.h2
68 files changed, 714 insertions, 273 deletions
diff --git a/src/app/config/config.c b/src/app/config/config.c
index 23781b1b0e..8c635ab848 100644
--- a/src/app/config/config.c
+++ b/src/app/config/config.c
@@ -671,6 +671,7 @@ static const config_var_t option_vars_[] = {
OBSOLETE("UseNTorHandshake"),
V(User, STRING, NULL),
OBSOLETE("UserspaceIOCPBuffers"),
+ V(AuthDirRejectRequestsUnderLoad, BOOL, "1"),
V(AuthDirSharedRandomness, BOOL, "1"),
V(AuthDirTestEd25519LinkKeys, BOOL, "1"),
OBSOLETE("V1AuthoritativeDirectory"),
diff --git a/src/app/config/or_options_st.h b/src/app/config/or_options_st.h
index 32dcd9fb18..e6be797017 100644
--- a/src/app/config/or_options_st.h
+++ b/src/app/config/or_options_st.h
@@ -1008,6 +1008,13 @@ struct or_options_t {
*/
uint64_t MaxUnparseableDescSizeToLog;
+ /** Bool (default: 1): Under bandwidth pressure, if set to 1, the authority
+ * will always answer directory requests from relays but will start sending
+ * 503 error code for the other connections. If set to 0, all connections
+ * are considered the same and the authority will try to answer them all
+ * regardless of bandwidth pressure or not. */
+ int AuthDirRejectRequestsUnderLoad;
+
/** Bool (default: 1): Switch for the shared random protocol. Only
* relevant to a directory authority. If off, the authority won't
* participate in the protocol. If on (default), a flag is added to the
diff --git a/src/core/mainloop/connection.c b/src/core/mainloop/connection.c
index 6094f33e4d..50cd3810a4 100644
--- a/src/core/mainloop/connection.c
+++ b/src/core/mainloop/connection.c
@@ -3051,7 +3051,7 @@ connection_mark_all_noncontrol_connections(void)
* uses pluggable transports, since we should then limit it even if it
* comes from an internal IP address. */
static int
-connection_is_rate_limited(connection_t *conn)
+connection_is_rate_limited(const connection_t *conn)
{
const or_options_t *options = get_options();
if (conn->linked)
@@ -3186,14 +3186,14 @@ connection_bucket_write_limit(connection_t *conn, time_t now)
global_bucket_val, conn_bucket);
}
-/** Return 1 if the global write buckets are low enough that we
+/** Return true iff the global write buckets are low enough that we
* shouldn't send <b>attempt</b> bytes of low-priority directory stuff
- * out to <b>conn</b>. Else return 0.
-
- * Priority was 1 for v1 requests (directories and running-routers),
- * and 2 for v2 requests and later (statuses and descriptors).
+ * out to <b>conn</b>.
+ *
+ * If we are a directory authority, always answer dir requests thus true is
+ * always returned.
*
- * There are a lot of parameters we could use here:
+ * Note: There are a lot of parameters we could use here:
* - global_relayed_write_bucket. Low is bad.
* - global_write_bucket. Low is bad.
* - bandwidthrate. Low is bad.
@@ -3205,39 +3205,40 @@ connection_bucket_write_limit(connection_t *conn, time_t now)
* mean is "total directory bytes added to outbufs recently", but
* that's harder to quantify and harder to keep track of.
*/
-int
-global_write_bucket_low(connection_t *conn, size_t attempt, int priority)
+bool
+connection_dir_is_global_write_low(const connection_t *conn, size_t attempt)
{
size_t smaller_bucket =
MIN(token_bucket_rw_get_write(&global_bucket),
token_bucket_rw_get_write(&global_relayed_bucket));
- if (authdir_mode(get_options()) && priority>1)
- return 0; /* there's always room to answer v2 if we're an auth dir */
+
+ /* Special case for authorities (directory only). */
+ if (authdir_mode_v3(get_options())) {
+ /* Are we configured to possibly reject requests under load? */
+ if (!get_options()->AuthDirRejectRequestsUnderLoad) {
+ /* Answer request no matter what. */
+ return false;
+ }
+ /* Always answer requests from a known relay which includes the other
+ * authorities. The following looks up the addresses for relays that we
+ * have their descriptor _and_ any configured trusted directories. */
+ if (nodelist_probably_contains_address(&conn->addr)) {
+ return false;
+ }
+ }
if (!connection_is_rate_limited(conn))
- return 0; /* local conns don't get limited */
+ return false; /* local conns don't get limited */
if (smaller_bucket < attempt)
- return 1; /* not enough space no matter the priority */
+ return true; /* not enough space. */
{
const time_t diff = approx_time() - write_buckets_last_empty_at;
if (diff <= 1)
- return 1; /* we're already hitting our limits, no more please */
+ return true; /* we're already hitting our limits, no more please */
}
-
- if (priority == 1) { /* old-style v1 query */
- /* Could we handle *two* of these requests within the next two seconds? */
- const or_options_t *options = get_options();
- size_t can_write = (size_t) (smaller_bucket
- + 2*(options->RelayBandwidthRate ? options->RelayBandwidthRate :
- options->BandwidthRate));
- if (can_write < 2*attempt)
- return 1;
- } else { /* v2 query */
- /* no further constraints yet */
- }
- return 0;
+ return false;
}
/** When did we last tell the accounting subsystem about transmitted
diff --git a/src/core/mainloop/connection.h b/src/core/mainloop/connection.h
index c93f1ef8e8..668c740042 100644
--- a/src/core/mainloop/connection.h
+++ b/src/core/mainloop/connection.h
@@ -195,8 +195,9 @@ int retry_all_listeners(smartlist_t *new_conns,
void connection_mark_all_noncontrol_listeners(void);
void connection_mark_all_noncontrol_connections(void);
-ssize_t connection_bucket_write_limit(connection_t *conn, time_t now);
-int global_write_bucket_low(connection_t *conn, size_t attempt, int priority);
+ssize_t connection_bucket_write_limit(struct connection_t *conn, time_t now);
+bool connection_dir_is_global_write_low(const struct connection_t *conn,
+ size_t attempt);
void connection_bucket_init(void);
void connection_bucket_adjust(const or_options_t *options);
void connection_bucket_refill_all(time_t now,
diff --git a/src/core/or/channel.c b/src/core/or/channel.c
index 0e190809ba..596932b008 100644
--- a/src/core/or/channel.c
+++ b/src/core/or/channel.c
@@ -1882,7 +1882,7 @@ channel_do_open_actions(channel_t *chan)
tor_free(transport_name);
/* Notify the DoS subsystem of a new client. */
if (tlschan && tlschan->conn) {
- dos_new_client_conn(tlschan->conn);
+ dos_new_client_conn(tlschan->conn, transport_name);
}
}
/* Otherwise the underlying transport can't tell us this, so skip it */
diff --git a/src/core/or/channeltls.c b/src/core/or/channeltls.c
index e9497651ef..d6c9e21631 100644
--- a/src/core/or/channeltls.c
+++ b/src/core/or/channeltls.c
@@ -1237,7 +1237,7 @@ channel_tls_handle_var_cell(var_cell_t *var_cell, or_connection_t *conn)
/* But that should be happening any longer've disabled bufferevents. */
tor_assert_nonfatal_unreached_once();
- /* fall through */
+ FALLTHROUGH;
case OR_CONN_STATE_TLS_SERVER_RENEGOTIATING:
if (!(command_allowed_before_handshake(var_cell->command))) {
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
diff --git a/src/core/or/circuitbuild.c b/src/core/or/circuitbuild.c
index 1daf468715..16bb7e7d79 100644
--- a/src/core/or/circuitbuild.c
+++ b/src/core/or/circuitbuild.c
@@ -2108,7 +2108,7 @@ choose_good_exit_server(origin_circuit_t *circ,
/* For these three, we want to pick the exit like a middle hop,
* since it should be random. */
tor_assert_nonfatal(is_internal);
- /* Falls through */
+ FALLTHROUGH;
case CIRCUIT_PURPOSE_C_GENERAL:
if (is_internal) /* pick it like a middle hop */
return router_choose_random_node(NULL, options->ExcludeNodes, flags);
diff --git a/src/core/or/circuitlist.c b/src/core/or/circuitlist.c
index 9ee9f93c99..61bcfa9039 100644
--- a/src/core/or/circuitlist.c
+++ b/src/core/or/circuitlist.c
@@ -844,7 +844,7 @@ circuit_purpose_to_controller_hs_state_string(uint8_t purpose)
"Unrecognized circuit purpose: %d",
(int)purpose);
tor_fragile_assert();
- /* fall through */
+ FALLTHROUGH;
case CIRCUIT_PURPOSE_OR:
case CIRCUIT_PURPOSE_C_GENERAL:
diff --git a/src/core/or/circuitpadding.c b/src/core/or/circuitpadding.c
index 99c68d5f6b..7f761fed6b 100644
--- a/src/core/or/circuitpadding.c
+++ b/src/core/or/circuitpadding.c
@@ -2444,9 +2444,12 @@ circpad_setup_machine_on_circ(circuit_t *on_circ,
return;
}
- tor_assert_nonfatal(on_circ->padding_machine[machine->machine_index]
- == NULL);
- tor_assert_nonfatal(on_circ->padding_info[machine->machine_index] == NULL);
+ IF_BUG_ONCE(on_circ->padding_machine[machine->machine_index] != NULL) {
+ return;
+ }
+ IF_BUG_ONCE(on_circ->padding_info[machine->machine_index] != NULL) {
+ return;
+ }
/* Log message */
if (CIRCUIT_IS_ORIGIN(on_circ)) {
diff --git a/src/core/or/circuituse.c b/src/core/or/circuituse.c
index 606c5e2dd2..284e315f9c 100644
--- a/src/core/or/circuituse.c
+++ b/src/core/or/circuituse.c
@@ -784,7 +784,7 @@ circuit_expire_building(void)
TO_ORIGIN_CIRCUIT(victim)->build_state->pending_final_cpath ==
NULL)
break;
- /* fallthrough! */
+ FALLTHROUGH;
case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT:
case CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED:
/* If we have reached this line, we want to spare the circ for now. */
diff --git a/src/core/or/connection_edge.c b/src/core/or/connection_edge.c
index 5f1664d286..4f5f038e6c 100644
--- a/src/core/or/connection_edge.c
+++ b/src/core/or/connection_edge.c
@@ -307,7 +307,7 @@ connection_edge_process_inbuf(edge_connection_t *conn, int package_partial)
note_user_activity(approx_time());
}
- /* falls through. */
+ FALLTHROUGH;
case EXIT_CONN_STATE_OPEN:
if (connection_edge_package_raw_inbuf(conn, package_partial, NULL) < 0) {
/* (We already sent an end cell if possible) */
@@ -332,7 +332,7 @@ connection_edge_process_inbuf(edge_connection_t *conn, int package_partial)
}
/* Fall through if the connection is on a circuit without optimistic
* data support. */
- /* Falls through. */
+ FALLTHROUGH;
case EXIT_CONN_STATE_CONNECTING:
case AP_CONN_STATE_RENDDESC_WAIT:
case AP_CONN_STATE_CIRCUIT_WAIT:
@@ -766,7 +766,7 @@ connection_edge_flushed_some(edge_connection_t *conn)
note_user_activity(approx_time());
}
- /* falls through. */
+ FALLTHROUGH;
case EXIT_CONN_STATE_OPEN:
sendme_connection_edge_consider_sending(conn);
break;
diff --git a/src/core/or/crypt_path.c b/src/core/or/crypt_path.c
index 6d5245510f..9b7efc28bf 100644
--- a/src/core/or/crypt_path.c
+++ b/src/core/or/crypt_path.c
@@ -113,7 +113,7 @@ cpath_assert_layer_ok(const crypt_path_t *cp)
{
case CPATH_STATE_OPEN:
relay_crypto_assert_ok(&cp->pvt_crypto);
- /* fall through */
+ FALLTHROUGH;
case CPATH_STATE_CLOSED:
/*XXXX Assert that there's no handshake_state either. */
tor_assert(!cp->rend_dh_handshake_state);
diff --git a/src/core/or/dos.c b/src/core/or/dos.c
index 5f9bbf90ab..d06eaa6d05 100644
--- a/src/core/or/dos.c
+++ b/src/core/or/dos.c
@@ -671,7 +671,7 @@ dos_log_heartbeat(void)
/* Called when a new client connection has been established on the given
* address. */
void
-dos_new_client_conn(or_connection_t *or_conn)
+dos_new_client_conn(or_connection_t *or_conn, const char *transport_name)
{
clientmap_entry_t *entry;
@@ -692,7 +692,7 @@ dos_new_client_conn(or_connection_t *or_conn)
}
/* We are only interested in client connection from the geoip cache. */
- entry = geoip_lookup_client(&or_conn->real_addr, NULL,
+ entry = geoip_lookup_client(&or_conn->real_addr, transport_name,
GEOIP_CLIENT_CONNECT);
if (BUG(entry == NULL)) {
/* Should never happen because we note down the address in the geoip
diff --git a/src/core/or/dos.h b/src/core/or/dos.h
index b5154a7cd2..a46f65d767 100644
--- a/src/core/or/dos.h
+++ b/src/core/or/dos.h
@@ -53,7 +53,8 @@ int dos_enabled(void);
void dos_log_heartbeat(void);
void dos_geoip_entry_about_to_free(const struct clientmap_entry_t *geoip_ent);
-void dos_new_client_conn(or_connection_t *or_conn);
+void dos_new_client_conn(or_connection_t *or_conn,
+ const char *transport_name);
void dos_close_client_conn(const or_connection_t *or_conn);
int dos_should_refuse_single_hop_client(void);
diff --git a/src/core/or/onion.c b/src/core/or/onion.c
index aa77465b96..aeddedd807 100644
--- a/src/core/or/onion.c
+++ b/src/core/or/onion.c
@@ -509,7 +509,7 @@ create_cell_format_impl(cell_t *cell_out, const create_cell_t *cell_in,
p += 16;
space -= 16;
}
- /* Fall through */
+ FALLTHROUGH;
case CELL_CREATE_FAST:
tor_assert(cell_in->handshake_len <= space);
memcpy(p, cell_in->onionskin, cell_in->handshake_len);
diff --git a/src/core/or/policies.c b/src/core/or/policies.c
index 83d9a53fc0..39a0817c85 100644
--- a/src/core/or/policies.c
+++ b/src/core/or/policies.c
@@ -2842,7 +2842,7 @@ parse_short_policy(const char *summary)
switch (*next) {
case ',':
++next;
- /* fall through */
+ FALLTHROUGH;
case '\0':
high = low;
break;
diff --git a/src/core/or/reasons.c b/src/core/or/reasons.c
index a7952279ba..e21bfa670a 100644
--- a/src/core/or/reasons.c
+++ b/src/core/or/reasons.c
@@ -489,7 +489,7 @@ end_reason_to_http_connect_response_line(int endreason)
return "HTTP/1.0 502 Bad Gateway (tor protocol violation)\r\n\r\n";
case END_STREAM_REASON_ENTRYPOLICY:
return "HTTP/1.0 403 Forbidden (entry policy violation)\r\n\r\n";
- case END_STREAM_REASON_NOTDIRECTORY: /* Fall Through */
+ case END_STREAM_REASON_NOTDIRECTORY: FALLTHROUGH;
default:
tor_assert_nonfatal_unreached();
return "HTTP/1.0 500 Internal Server Error (weird end reason)\r\n\r\n";
diff --git a/src/core/or/relay.c b/src/core/or/relay.c
index a437b54792..f83d2365e4 100644
--- a/src/core/or/relay.c
+++ b/src/core/or/relay.c
@@ -940,7 +940,7 @@ connection_ap_process_end_not_open(
break; /* break means it'll close, below */
/* Else fall through: expire this circuit, clear the
* chosen_exit_name field, and try again. */
- /* Falls through. */
+ FALLTHROUGH;
case END_STREAM_REASON_RESOLVEFAILED:
case END_STREAM_REASON_TIMEOUT:
case END_STREAM_REASON_MISC:
diff --git a/src/core/or/scheduler.c b/src/core/or/scheduler.c
index 063342480a..0e3f0fe815 100644
--- a/src/core/or/scheduler.c
+++ b/src/core/or/scheduler.c
@@ -192,7 +192,7 @@ get_scheduler_type_string(scheduler_types_t type)
case SCHEDULER_KIST_LITE:
return "KISTLite";
case SCHEDULER_NONE:
- /* fallthrough */
+ FALLTHROUGH;
default:
tor_assert_unreached();
return "(N/A)";
@@ -288,7 +288,7 @@ select_scheduler(void)
scheduler_kist_set_lite_mode();
goto end;
case SCHEDULER_NONE:
- /* fallthrough */
+ FALLTHROUGH;
default:
/* Our option validation should have caught this. */
tor_assert_unreached();
diff --git a/src/core/or/sendme.c b/src/core/or/sendme.c
index 0757ce3d52..e61cf0c0f8 100644
--- a/src/core/or/sendme.c
+++ b/src/core/or/sendme.c
@@ -293,7 +293,7 @@ send_circuit_level_sendme(circuit_t *circ, crypt_path_t *layer_hint,
log_debug(LD_PROTOCOL, "Emitting SENDME version 1 cell.");
break;
case 0x00:
- /* Fallthrough because default is to use v0. */
+ FALLTHROUGH;
default:
/* Unknown version, fallback to version 0 meaning no payload. */
payload_len = 0;
diff --git a/src/core/proto/proto_socks.c b/src/core/proto/proto_socks.c
index b657a7b758..c06e6b1a41 100644
--- a/src/core/proto/proto_socks.c
+++ b/src/core/proto/proto_socks.c
@@ -856,7 +856,7 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
case SOCKS_RESULT_TRUNCATED:
if (datalen == n_pullup)
return 0;
- /* FALLTHRU */
+ FALLTHROUGH;
case SOCKS_RESULT_MORE_EXPECTED:
res = 0;
break;
@@ -962,7 +962,7 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req,
strlcpy((char*)req->reply, SOCKS_PROXY_IS_NOT_AN_HTTP_PROXY_MSG,
MAX_SOCKS_REPLY_LEN);
req->replylen = strlen((char*)req->reply)+1;
- /* fall through */
+ FALLTHROUGH;
default: /* version is not socks4 or socks5 */
log_warn(LD_APP,
"Socks version %d not recognized. (This port is not an "
@@ -1067,7 +1067,10 @@ parse_socks_client(const uint8_t *data, size_t datalen,
log_info(LD_NET, "SOCKS 5 client: need authentication.");
*drain_out = -1;
return 2;
- /* fall through */
+ default:
+ /* This wasn't supposed to be exhaustive; there are other
+ * authentication methods too. */
+ ;
}
*reason = tor_strdup("server doesn't support any of our available "
diff --git a/src/ext/csiphash.c b/src/ext/csiphash.c
index faa52ae4e1..e0f5b2e5c9 100644
--- a/src/ext/csiphash.c
+++ b/src/ext/csiphash.c
@@ -95,13 +95,13 @@ uint64_t siphash24(const void *src, unsigned long src_sz, const struct sipkey *k
}
#else
switch (src_sz - blocks) {
- case 7: last7 |= (uint64_t)m[i + 6] << 48; /* Falls through. */
- case 6: last7 |= (uint64_t)m[i + 5] << 40; /* Falls through. */
- case 5: last7 |= (uint64_t)m[i + 4] << 32; /* Falls through. */
- case 4: last7 |= (uint64_t)m[i + 3] << 24; /* Falls through. */
- case 3: last7 |= (uint64_t)m[i + 2] << 16; /* Falls through. */
- case 2: last7 |= (uint64_t)m[i + 1] << 8; /* Falls through. */
- case 1: last7 |= (uint64_t)m[i + 0] ; /* Falls through. */
+ case 7: last7 |= (uint64_t)m[i + 6] << 48; FALLTHROUGH;
+ case 6: last7 |= (uint64_t)m[i + 5] << 40; FALLTHROUGH;
+ case 5: last7 |= (uint64_t)m[i + 4] << 32; FALLTHROUGH;
+ case 4: last7 |= (uint64_t)m[i + 3] << 24; FALLTHROUGH;
+ case 3: last7 |= (uint64_t)m[i + 2] << 16; FALLTHROUGH;
+ case 2: last7 |= (uint64_t)m[i + 1] << 8; FALLTHROUGH;
+ case 1: last7 |= (uint64_t)m[i + 0] ; FALLTHROUGH;
case 0:
default:;
}
diff --git a/src/ext/ed25519/donna/ed25519_tor.c b/src/ext/ed25519/donna/ed25519_tor.c
index 7f5ab398d8..a5bb6f4e21 100644
--- a/src/ext/ed25519/donna/ed25519_tor.c
+++ b/src/ext/ed25519/donna/ed25519_tor.c
@@ -35,6 +35,9 @@
#define ED25519_FN(fn) ED25519_FN2(fn,ED25519_SUFFIX)
#include "orconfig.h"
+
+#include "lib/cc/compat_compiler.h"
+
#include "ed25519-donna.h"
#include "ed25519_donna_tor.h"
#include "ed25519-randombytes.h"
@@ -366,4 +369,3 @@ ed25519_donna_scalarmult_with_group_order(unsigned char *out,
}
#include "test-internals.c"
-
diff --git a/src/ext/ed25519/donna/modm-donna-32bit.h b/src/ext/ed25519/donna/modm-donna-32bit.h
index 0ef9e58fa1..5934d9ca9d 100644
--- a/src/ext/ed25519/donna/modm-donna-32bit.h
+++ b/src/ext/ed25519/donna/modm-donna-32bit.h
@@ -385,14 +385,14 @@ sub256_modm_batch(bignum256modm out, const bignum256modm a, const bignum256modm
size_t i = 0;
bignum256modm_element_t carry = 0;
switch (limbsize) {
- case 8: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; /* Falls through. */
- case 7: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; /* Falls through. */
- case 6: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; /* Falls through. */
- case 5: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; /* Falls through. */
- case 4: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; /* Falls through. */
- case 3: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; /* Falls through. */
- case 2: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; /* Falls through. */
- case 1: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; /* Falls through. */
+ case 8: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; FALLTHROUGH;
+ case 7: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; FALLTHROUGH;
+ case 6: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; FALLTHROUGH;
+ case 5: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; FALLTHROUGH;
+ case 4: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; FALLTHROUGH;
+ case 3: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; FALLTHROUGH;
+ case 2: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; FALLTHROUGH;
+ case 1: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; FALLTHROUGH;
case 0:
default: out[i] = (a[i] - b[i]) - carry;
}
@@ -403,14 +403,14 @@ sub256_modm_batch(bignum256modm out, const bignum256modm a, const bignum256modm
static int
lt256_modm_batch(const bignum256modm a, const bignum256modm b, size_t limbsize) {
switch (limbsize) {
- case 8: if (a[8] > b[8]) return 0; if (a[8] < b[8]) return 1; /* Falls through. */
- case 7: if (a[7] > b[7]) return 0; if (a[7] < b[7]) return 1; /* Falls through. */
- case 6: if (a[6] > b[6]) return 0; if (a[6] < b[6]) return 1; /* Falls through. */
- case 5: if (a[5] > b[5]) return 0; if (a[5] < b[5]) return 1; /* Falls through. */
- case 4: if (a[4] > b[4]) return 0; if (a[4] < b[4]) return 1; /* Falls through. */
- case 3: if (a[3] > b[3]) return 0; if (a[3] < b[3]) return 1; /* Falls through. */
- case 2: if (a[2] > b[2]) return 0; if (a[2] < b[2]) return 1; /* Falls through. */
- case 1: if (a[1] > b[1]) return 0; if (a[1] < b[1]) return 1; /* Falls through. */
+ case 8: if (a[8] > b[8]) return 0; if (a[8] < b[8]) return 1; FALLTHROUGH;
+ case 7: if (a[7] > b[7]) return 0; if (a[7] < b[7]) return 1; FALLTHROUGH;
+ case 6: if (a[6] > b[6]) return 0; if (a[6] < b[6]) return 1; FALLTHROUGH;
+ case 5: if (a[5] > b[5]) return 0; if (a[5] < b[5]) return 1; FALLTHROUGH;
+ case 4: if (a[4] > b[4]) return 0; if (a[4] < b[4]) return 1; FALLTHROUGH;
+ case 3: if (a[3] > b[3]) return 0; if (a[3] < b[3]) return 1; FALLTHROUGH;
+ case 2: if (a[2] > b[2]) return 0; if (a[2] < b[2]) return 1; FALLTHROUGH;
+ case 1: if (a[1] > b[1]) return 0; if (a[1] < b[1]) return 1; FALLTHROUGH;
case 0: if (a[0] > b[0]) return 0; if (a[0] < b[0]) return 1;
}
return 0;
@@ -420,14 +420,14 @@ lt256_modm_batch(const bignum256modm a, const bignum256modm b, size_t limbsize)
static int
lte256_modm_batch(const bignum256modm a, const bignum256modm b, size_t limbsize) {
switch (limbsize) {
- case 8: if (a[8] > b[8]) return 0; if (a[8] < b[8]) return 1; /* Falls through. */
- case 7: if (a[7] > b[7]) return 0; if (a[7] < b[7]) return 1; /* Falls through. */
- case 6: if (a[6] > b[6]) return 0; if (a[6] < b[6]) return 1; /* Falls through. */
- case 5: if (a[5] > b[5]) return 0; if (a[5] < b[5]) return 1; /* Falls through. */
- case 4: if (a[4] > b[4]) return 0; if (a[4] < b[4]) return 1; /* Falls through. */
- case 3: if (a[3] > b[3]) return 0; if (a[3] < b[3]) return 1; /* Falls through. */
- case 2: if (a[2] > b[2]) return 0; if (a[2] < b[2]) return 1; /* Falls through. */
- case 1: if (a[1] > b[1]) return 0; if (a[1] < b[1]) return 1; /* Falls through. */
+ case 8: if (a[8] > b[8]) return 0; if (a[8] < b[8]) return 1; FALLTHROUGH;
+ case 7: if (a[7] > b[7]) return 0; if (a[7] < b[7]) return 1; FALLTHROUGH;
+ case 6: if (a[6] > b[6]) return 0; if (a[6] < b[6]) return 1; FALLTHROUGH;
+ case 5: if (a[5] > b[5]) return 0; if (a[5] < b[5]) return 1; FALLTHROUGH;
+ case 4: if (a[4] > b[4]) return 0; if (a[4] < b[4]) return 1; FALLTHROUGH;
+ case 3: if (a[3] > b[3]) return 0; if (a[3] < b[3]) return 1; FALLTHROUGH;
+ case 2: if (a[2] > b[2]) return 0; if (a[2] < b[2]) return 1; FALLTHROUGH;
+ case 1: if (a[1] > b[1]) return 0; if (a[1] < b[1]) return 1; FALLTHROUGH;
case 0: if (a[0] > b[0]) return 0; if (a[0] < b[0]) return 1;
}
return 1;
diff --git a/src/ext/ed25519/donna/modm-donna-64bit.h b/src/ext/ed25519/donna/modm-donna-64bit.h
index 06c98e3039..aa361afdbc 100644
--- a/src/ext/ed25519/donna/modm-donna-64bit.h
+++ b/src/ext/ed25519/donna/modm-donna-64bit.h
@@ -294,10 +294,10 @@ sub256_modm_batch(bignum256modm out, const bignum256modm a, const bignum256modm
size_t i = 0;
bignum256modm_element_t carry = 0;
switch (limbsize) {
- case 4: out[i] = (a[i] - b[i]) ; carry = (out[i] >> 63); out[i] &= 0xffffffffffffff; i++; /* Falls through. */
- case 3: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 63); out[i] &= 0xffffffffffffff; i++; /* Falls through. */
- case 2: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 63); out[i] &= 0xffffffffffffff; i++; /* Falls through. */
- case 1: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 63); out[i] &= 0xffffffffffffff; i++; /* Falls through. */
+ case 4: out[i] = (a[i] - b[i]) ; carry = (out[i] >> 63); out[i] &= 0xffffffffffffff; i++; FALLTHROUGH;
+ case 3: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 63); out[i] &= 0xffffffffffffff; i++; FALLTHROUGH;
+ case 2: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 63); out[i] &= 0xffffffffffffff; i++; FALLTHROUGH;
+ case 1: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 63); out[i] &= 0xffffffffffffff; i++; FALLTHROUGH;
case 0:
default: out[i] = (a[i] - b[i]) - carry;
}
@@ -310,10 +310,10 @@ lt256_modm_batch(const bignum256modm a, const bignum256modm b, size_t limbsize)
size_t i = 0;
bignum256modm_element_t t, carry = 0;
switch (limbsize) {
- case 4: t = (a[i] - b[i]) ; carry = (t >> 63); i++; /* Falls through. */
- case 3: t = (a[i] - b[i]) - carry; carry = (t >> 63); i++; /* Falls through. */
- case 2: t = (a[i] - b[i]) - carry; carry = (t >> 63); i++; /* Falls through. */
- case 1: t = (a[i] - b[i]) - carry; carry = (t >> 63); i++; /* Falls through. */
+ case 4: t = (a[i] - b[i]) ; carry = (t >> 63); i++; FALLTHROUGH;
+ case 3: t = (a[i] - b[i]) - carry; carry = (t >> 63); i++; FALLTHROUGH;
+ case 2: t = (a[i] - b[i]) - carry; carry = (t >> 63); i++; FALLTHROUGH;
+ case 1: t = (a[i] - b[i]) - carry; carry = (t >> 63); i++; FALLTHROUGH;
case 0: t = (a[i] - b[i]) - carry; carry = (t >> 63);
}
return (int)carry;
@@ -325,10 +325,10 @@ lte256_modm_batch(const bignum256modm a, const bignum256modm b, size_t limbsize)
size_t i = 0;
bignum256modm_element_t t, carry = 0;
switch (limbsize) {
- case 4: t = (b[i] - a[i]) ; carry = (t >> 63); i++; /* Falls through. */
- case 3: t = (b[i] - a[i]) - carry; carry = (t >> 63); i++; /* Falls through. */
- case 2: t = (b[i] - a[i]) - carry; carry = (t >> 63); i++; /* Falls through. */
- case 1: t = (b[i] - a[i]) - carry; carry = (t >> 63); i++; /* Falls through. */
+ case 4: t = (b[i] - a[i]) ; carry = (t >> 63); i++; FALLTHROUGH;
+ case 3: t = (b[i] - a[i]) - carry; carry = (t >> 63); i++; FALLTHROUGH;
+ case 2: t = (b[i] - a[i]) - carry; carry = (t >> 63); i++; FALLTHROUGH;
+ case 1: t = (b[i] - a[i]) - carry; carry = (t >> 63); i++; FALLTHROUGH;
case 0: t = (b[i] - a[i]) - carry; carry = (t >> 63);
}
return (int)!carry;
diff --git a/src/feature/client/entrynodes.c b/src/feature/client/entrynodes.c
index 36b575ef20..537ead020b 100644
--- a/src/feature/client/entrynodes.c
+++ b/src/feature/client/entrynodes.c
@@ -2263,7 +2263,7 @@ entry_guards_note_guard_success(guard_selection_t *gs,
break;
default:
tor_assert_nonfatal_unreached();
- /* Fall through. */
+ FALLTHROUGH;
case GUARD_CIRC_STATE_USABLE_IF_NO_BETTER_GUARD:
if (guard->is_primary) {
/* XXXX #20832 -- I don't actually like this logic. It seems to make
diff --git a/src/feature/control/btrack_orconn_cevent.c b/src/feature/control/btrack_orconn_cevent.c
index 535aa8f614..a00eb042d5 100644
--- a/src/feature/control/btrack_orconn_cevent.c
+++ b/src/feature/control/btrack_orconn_cevent.c
@@ -146,6 +146,7 @@ bto_cevent_apconn(const bt_orconn_t *bto)
break;
case OR_CONN_STATE_OPEN:
control_event_bootstrap(BOOTSTRAP_STATUS_AP_HANDSHAKE_DONE, 0);
+ break;
default:
break;
}
diff --git a/src/feature/control/control.c b/src/feature/control/control.c
index d6581808c0..ece5616907 100644
--- a/src/feature/control/control.c
+++ b/src/feature/control/control.c
@@ -158,6 +158,10 @@ control_ports_write_to_file(void)
}
const struct signal_name_t signal_table[] = {
+ /* NOTE: this table is used for handling SIGNAL commands and generating
+ * SIGNAL events. Order is significant: if there are two entries for the
+ * same numeric signal, the first one is the canonical name generated
+ * for the events. */
{ SIGHUP, "RELOAD" },
{ SIGHUP, "HUP" },
{ SIGINT, "SHUTDOWN" },
diff --git a/src/feature/control/control_cmd.c b/src/feature/control/control_cmd.c
index de1bef7e59..68d05abb73 100644
--- a/src/feature/control/control_cmd.c
+++ b/src/feature/control/control_cmd.c
@@ -1887,7 +1887,7 @@ handle_control_add_onion(control_connection_t *conn,
case RSAE_BADAUTH:
control_write_endreply(conn, 512, "Invalid client authorization");
break;
- case RSAE_INTERNAL: /* FALLSTHROUGH */
+ case RSAE_INTERNAL: FALLTHROUGH;
default:
control_write_endreply(conn, 551, "Failed to add Onion Service");
}
diff --git a/src/feature/control/control_events.c b/src/feature/control/control_events.c
index 82ea943999..8cf6d6de0b 100644
--- a/src/feature/control/control_events.c
+++ b/src/feature/control/control_events.c
@@ -1552,29 +1552,17 @@ control_event_signal(uintptr_t signal_num)
if (!control_event_is_interesting(EVENT_GOT_SIGNAL))
return 0;
- switch (signal_num) {
- case SIGHUP:
- signal_string = "RELOAD";
+ for (unsigned i = 0; signal_table[i].signal_name != NULL; ++i) {
+ if ((int)signal_num == signal_table[i].sig) {
+ signal_string = signal_table[i].signal_name;
break;
- case SIGUSR1:
- signal_string = "DUMP";
- break;
- case SIGUSR2:
- signal_string = "DEBUG";
- break;
- case SIGNEWNYM:
- signal_string = "NEWNYM";
- break;
- case SIGCLEARDNSCACHE:
- signal_string = "CLEARDNSCACHE";
- break;
- case SIGHEARTBEAT:
- signal_string = "HEARTBEAT";
- break;
- default:
- log_warn(LD_BUG, "Unrecognized signal %lu in control_event_signal",
- (unsigned long)signal_num);
- return -1;
+ }
+ }
+
+ if (signal_string == NULL) {
+ log_warn(LD_BUG, "Unrecognized signal %lu in control_event_signal",
+ (unsigned long)signal_num);
+ return -1;
}
send_control_event(EVENT_GOT_SIGNAL, "650 SIGNAL %s\r\n",
diff --git a/src/feature/dirauth/keypin.c b/src/feature/dirauth/keypin.c
index 3ca2c3ef91..316b7d6c2f 100644
--- a/src/feature/dirauth/keypin.c
+++ b/src/feature/dirauth/keypin.c
@@ -267,7 +267,7 @@ keypin_add_or_replace_entry_in_map(keypin_ent_t *ent)
}
tor_free(ent2);
r = -1;
- /* Fall through */
+ /* Note lack of return here: we fall through to the next line. */
}
keypin_add_entry_to_map(ent);
diff --git a/src/feature/dirauth/shared_random_state.c b/src/feature/dirauth/shared_random_state.c
index 76befb0f5f..4078d6a24a 100644
--- a/src/feature/dirauth/shared_random_state.c
+++ b/src/feature/dirauth/shared_random_state.c
@@ -1066,8 +1066,9 @@ sr_state_set_valid_after(time_t valid_after)
sr_phase_t
sr_state_get_phase(void)
{
- void *ptr;
+ void *ptr=NULL;
state_query(SR_STATE_ACTION_GET, SR_STATE_OBJ_PHASE, NULL, &ptr);
+ tor_assert(ptr);
return *(sr_phase_t *) ptr;
}
diff --git a/src/feature/dircache/dircache.c b/src/feature/dircache/dircache.c
index d4d0ad9939..59cdcc5e02 100644
--- a/src/feature/dircache/dircache.c
+++ b/src/feature/dircache/dircache.c
@@ -951,7 +951,7 @@ handle_get_current_consensus(dir_connection_t *conn,
goto done;
}
- if (global_write_bucket_low(TO_CONN(conn), size_guess, 2)) {
+ if (connection_dir_is_global_write_low(TO_CONN(conn), size_guess)) {
log_debug(LD_DIRSERV,
"Client asked for network status lists, but we've been "
"writing too many bytes lately. Sending 503 Dir busy.");
@@ -1060,7 +1060,7 @@ handle_get_status_vote(dir_connection_t *conn, const get_handler_args_t *args)
}
});
- if (global_write_bucket_low(TO_CONN(conn), estimated_len, 2)) {
+ if (connection_dir_is_global_write_low(TO_CONN(conn), estimated_len)) {
write_short_http_response(conn, 503, "Directory busy, try again later");
goto vote_done;
}
@@ -1119,7 +1119,7 @@ handle_get_microdesc(dir_connection_t *conn, const get_handler_args_t *args)
write_short_http_response(conn, 404, "Not found");
goto done;
}
- if (global_write_bucket_low(TO_CONN(conn), size_guess, 2)) {
+ if (connection_dir_is_global_write_low(TO_CONN(conn), size_guess)) {
log_info(LD_DIRSERV,
"Client asked for server descriptors, but we've been "
"writing too many bytes lately. Sending 503 Dir busy.");
@@ -1217,7 +1217,7 @@ handle_get_descriptor(dir_connection_t *conn, const get_handler_args_t *args)
msg = "Not found";
write_short_http_response(conn, 404, msg);
} else {
- if (global_write_bucket_low(TO_CONN(conn), size_guess, 2)) {
+ if (connection_dir_is_global_write_low(TO_CONN(conn), size_guess)) {
log_info(LD_DIRSERV,
"Client asked for server descriptors, but we've been "
"writing too many bytes lately. Sending 503 Dir busy.");
@@ -1313,9 +1313,8 @@ handle_get_keys(dir_connection_t *conn, const get_handler_args_t *args)
SMARTLIST_FOREACH(certs, authority_cert_t *, c,
len += c->cache_info.signed_descriptor_len);
- if (global_write_bucket_low(TO_CONN(conn),
- compress_method != NO_METHOD ? len/2 : len,
- 2)) {
+ if (connection_dir_is_global_write_low(TO_CONN(conn),
+ compress_method != NO_METHOD ? len/2 : len)) {
write_short_http_response(conn, 503, "Directory busy, try again later");
goto keys_done;
}
diff --git a/src/feature/dirclient/dirclient.c b/src/feature/dirclient/dirclient.c
index 1ea50fd350..fa82bdc1e7 100644
--- a/src/feature/dirclient/dirclient.c
+++ b/src/feature/dirclient/dirclient.c
@@ -1369,7 +1369,7 @@ directory_initiate_request,(directory_request_t *request))
case 1:
/* start flushing conn */
conn->base_.state = DIR_CONN_STATE_CLIENT_SENDING;
- /* fall through */
+ FALLTHROUGH;
case 0:
/* queue the command on the outbuf */
directory_send_command(conn, 1, request);
diff --git a/src/feature/dirparse/parsecommon.c b/src/feature/dirparse/parsecommon.c
index 036a51689c..c22ed186b8 100644
--- a/src/feature/dirparse/parsecommon.c
+++ b/src/feature/dirparse/parsecommon.c
@@ -222,7 +222,7 @@ token_check_object(memarea_t *area, const char *kwd,
kwd, crypto_pk_num_bits(tok->key));
RET_ERR(ebuf);
}
- /* fall through */
+ FALLTHROUGH;
case NEED_KEY: /* There must be some kind of key. */
if (!tok->key) {
tor_snprintf(ebuf, sizeof(ebuf), "Missing public key for %s", kwd);
@@ -403,12 +403,19 @@ 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) {
+ RET_ERR("Unexpected public key.");
+ }
tok->key = crypto_pk_asn1_decode(tok->object_body, tok->object_size);
if (! tok->key)
RET_ERR("Couldn't parse public key.");
} else if (!strcmp(tok->object_type, "RSA PRIVATE KEY")) { /* private key */
+ if (o_syn != NEED_SKEY_1024 && o_syn != OBJ_OK) {
+ RET_ERR("Unexpected private key.");
+ }
tok->key = crypto_pk_asn1_decode_private(tok->object_body,
- tok->object_size);
+ tok->object_size,
+ 1024);
if (! tok->key)
RET_ERR("Couldn't parse private key.");
}
diff --git a/src/feature/hs/hs_client.c b/src/feature/hs/hs_client.c
index 492e77faff..8b63375939 100644
--- a/src/feature/hs/hs_client.c
+++ b/src/feature/hs/hs_client.c
@@ -606,9 +606,14 @@ send_introduce1(origin_circuit_t *intro_circ,
/* We need to find which intro point in the descriptor we are connected to
* on intro_circ. */
ip = find_desc_intro_point_by_ident(intro_circ->hs_ident, desc);
- if (BUG(ip == NULL)) {
- /* If we can find a descriptor from this introduction circuit ident, we
- * must have a valid intro point object. Permanent error. */
+ if (ip == NULL) {
+ /* The following is possible if the descriptor was changed while we had
+ * this introduction circuit open and waiting for the rendezvous circuit to
+ * be ready. Which results in this situation where we can't find the
+ * corresponding intro point within the descriptor of the service. */
+ log_info(LD_REND, "Unable to find introduction point for service %s "
+ "while trying to send an INTRODUCE1 cell.",
+ safe_str_client(onion_address));
goto perm_err;
}
@@ -1274,7 +1279,7 @@ hs_client_decode_descriptor(const char *desc_str,
uint8_t subcredential[DIGEST256_LEN];
ed25519_public_key_t blinded_pubkey;
hs_client_service_authorization_t *client_auth = NULL;
- curve25519_secret_key_t *client_auht_sk = NULL;
+ curve25519_secret_key_t *client_auth_sk = NULL;
tor_assert(desc_str);
tor_assert(service_identity_pk);
@@ -1283,7 +1288,7 @@ hs_client_decode_descriptor(const char *desc_str,
/* Check if we have a client authorization for this service in the map. */
client_auth = find_client_auth(service_identity_pk);
if (client_auth) {
- client_auht_sk = &client_auth->enc_seckey;
+ client_auth_sk = &client_auth->enc_seckey;
}
/* Create subcredential for this HS so that we can decrypt */
@@ -1296,7 +1301,7 @@ hs_client_decode_descriptor(const char *desc_str,
/* Parse descriptor */
ret = hs_desc_decode_descriptor(desc_str, subcredential,
- client_auht_sk, desc);
+ client_auth_sk, desc);
memwipe(subcredential, 0, sizeof(subcredential));
if (ret < 0) {
goto err;
diff --git a/src/feature/hs/hs_service.c b/src/feature/hs/hs_service.c
index 18c38ebc0a..17ac4fa4a9 100644
--- a/src/feature/hs/hs_service.c
+++ b/src/feature/hs/hs_service.c
@@ -3565,6 +3565,12 @@ hs_service_add_ephemeral(ed25519_secret_key_t *sk, smartlist_t *ports,
goto err;
}
+ if (ed25519_validate_pubkey(&service->keys.identity_pk) < 0) {
+ log_warn(LD_CONFIG, "Bad ed25519 private key was provided");
+ ret = RSAE_BADPRIVKEY;
+ goto err;
+ }
+
/* Make sure we have at least one port. */
if (smartlist_len(service->config.ports) == 0) {
log_warn(LD_CONFIG, "At least one VIRTPORT/TARGET must be specified "
diff --git a/src/feature/nodelist/dirlist.c b/src/feature/nodelist/dirlist.c
index e2a1d6a9fa..ccbb378513 100644
--- a/src/feature/nodelist/dirlist.c
+++ b/src/feature/nodelist/dirlist.c
@@ -49,6 +49,37 @@ static smartlist_t *trusted_dir_servers = NULL;
* and all fallback directory servers. */
static smartlist_t *fallback_dir_servers = NULL;
+/** Helper: From a given trusted directory entry, add the v4 or/and v6 address
+ * to the nodelist address set. */
+static void
+add_trusted_dir_to_nodelist_addr_set(const dir_server_t *dir)
+{
+ tor_assert(dir);
+ tor_assert(dir->is_authority);
+
+ /* Add IPv4 and then IPv6 if applicable. */
+ nodelist_add_addr4_to_address_set(dir->addr);
+ if (!tor_addr_is_null(&dir->ipv6_addr)) {
+ nodelist_add_addr6_to_address_set(&dir->ipv6_addr);
+ }
+}
+
+/** Go over the trusted directory server list and add their address(es) to the
+ * nodelist address set. This is called everytime a new consensus is set. */
+MOCK_IMPL(void,
+dirlist_add_trusted_dir_addresses, (void))
+{
+ if (!trusted_dir_servers) {
+ return;
+ }
+
+ SMARTLIST_FOREACH_BEGIN(trusted_dir_servers, const dir_server_t *, ent) {
+ if (ent->is_authority) {
+ add_trusted_dir_to_nodelist_addr_set(ent);
+ }
+ } SMARTLIST_FOREACH_END(ent);
+}
+
/** Return the number of directory authorities whose type matches some bit set
* in <b>type</b> */
int
diff --git a/src/feature/nodelist/dirlist.h b/src/feature/nodelist/dirlist.h
index b6dda32d85..c49162f1e9 100644
--- a/src/feature/nodelist/dirlist.h
+++ b/src/feature/nodelist/dirlist.h
@@ -44,4 +44,6 @@ void dir_server_add(dir_server_t *ent);
void clear_dir_servers(void);
void dirlist_free_all(void);
+MOCK_DECL(void, dirlist_add_trusted_dir_addresses, (void));
+
#endif /* !defined(TOR_DIRLIST_H) */
diff --git a/src/feature/nodelist/nodelist.c b/src/feature/nodelist/nodelist.c
index bd80fc1b4b..9191173c3b 100644
--- a/src/feature/nodelist/nodelist.c
+++ b/src/feature/nodelist/nodelist.c
@@ -455,22 +455,43 @@ node_add_to_address_set(const node_t *node)
if (node->rs) {
if (node->rs->addr)
- address_set_add_ipv4h(the_nodelist->node_addrs, node->rs->addr);
+ nodelist_add_addr4_to_address_set(node->rs->addr);
if (!tor_addr_is_null(&node->rs->ipv6_addr))
- address_set_add(the_nodelist->node_addrs, &node->rs->ipv6_addr);
+ nodelist_add_addr6_to_address_set(&node->rs->ipv6_addr);
}
if (node->ri) {
if (node->ri->addr)
- address_set_add_ipv4h(the_nodelist->node_addrs, node->ri->addr);
+ nodelist_add_addr4_to_address_set(node->ri->addr);
if (!tor_addr_is_null(&node->ri->ipv6_addr))
- address_set_add(the_nodelist->node_addrs, &node->ri->ipv6_addr);
+ nodelist_add_addr6_to_address_set(&node->ri->ipv6_addr);
}
if (node->md) {
if (!tor_addr_is_null(&node->md->ipv6_addr))
- address_set_add(the_nodelist->node_addrs, &node->md->ipv6_addr);
+ nodelist_add_addr6_to_address_set(&node->md->ipv6_addr);
}
}
+/** Add the given v4 address into the nodelist address set. */
+void
+nodelist_add_addr4_to_address_set(const uint32_t addr)
+{
+ if (!the_nodelist || !the_nodelist->node_addrs || addr == 0) {
+ return;
+ }
+ address_set_add_ipv4h(the_nodelist->node_addrs, addr);
+}
+
+/** Add the given v6 address into the nodelist address set. */
+void
+nodelist_add_addr6_to_address_set(const tor_addr_t *addr)
+{
+ if (BUG(!addr) || tor_addr_is_null(addr) || tor_addr_is_v4(addr) ||
+ !the_nodelist || !the_nodelist->node_addrs) {
+ return;
+ }
+ address_set_add(the_nodelist->node_addrs, addr);
+}
+
/** Return true if <b>addr</b> is the address of some node in the nodelist.
* If not, probably return false. */
int
@@ -612,9 +633,12 @@ nodelist_set_consensus(networkstatus_t *ns)
SMARTLIST_FOREACH(the_nodelist->nodes, node_t *, node,
node->rs = NULL);
- /* Conservatively estimate that every node will have 2 addresses. */
- const int estimated_addresses = smartlist_len(ns->routerstatus_list) *
- get_estimated_address_per_node();
+ /* Conservatively estimate that every node will have 2 addresses (v4 and
+ * v6). Then we add the number of configured trusted authorities we have. */
+ int estimated_addresses = smartlist_len(ns->routerstatus_list) *
+ get_estimated_address_per_node();
+ estimated_addresses += (get_n_authorities(V3_DIRINFO & BRIDGE_DIRINFO) *
+ get_estimated_address_per_node());
address_set_free(the_nodelist->node_addrs);
the_nodelist->node_addrs = address_set_new(estimated_addresses);
@@ -665,6 +689,9 @@ nodelist_set_consensus(networkstatus_t *ns)
SMARTLIST_FOREACH_BEGIN(the_nodelist->nodes, node_t *, node) {
node_add_to_address_set(node);
} SMARTLIST_FOREACH_END(node);
+ /* Then, add all trusted configured directories. Some might not be in the
+ * consensus so make sure we know them. */
+ dirlist_add_trusted_dir_addresses();
if (! authdir) {
SMARTLIST_FOREACH_BEGIN(the_nodelist->nodes, node_t *, node) {
diff --git a/src/feature/nodelist/nodelist.h b/src/feature/nodelist/nodelist.h
index af144c197f..87cfa48e25 100644
--- a/src/feature/nodelist/nodelist.h
+++ b/src/feature/nodelist/nodelist.h
@@ -35,6 +35,8 @@ node_t *nodelist_add_microdesc(microdesc_t *md);
void nodelist_set_consensus(networkstatus_t *ns);
void nodelist_ensure_freshness(networkstatus_t *ns);
int nodelist_probably_contains_address(const tor_addr_t *addr);
+void nodelist_add_addr4_to_address_set(const uint32_t addr);
+void nodelist_add_addr6_to_address_set(const tor_addr_t *addr);
void nodelist_remove_microdesc(const char *identity_digest, microdesc_t *md);
void nodelist_remove_routerinfo(routerinfo_t *ri);
diff --git a/src/feature/relay/dns.c b/src/feature/relay/dns.c
index 05b97e0ae2..d62598d46f 100644
--- a/src/feature/relay/dns.c
+++ b/src/feature/relay/dns.c
@@ -546,9 +546,9 @@ send_resolved_cell,(edge_connection_t *conn, uint8_t answer_type,
break;
} else {
answer_type = RESOLVED_TYPE_ERROR;
- /* fall through. */
+ /* We let this fall through and treat it as an error. */
}
- /* Falls through. */
+ FALLTHROUGH;
case RESOLVED_TYPE_ERROR_TRANSIENT:
case RESOLVED_TYPE_ERROR:
{
diff --git a/src/feature/rend/rendclient.c b/src/feature/rend/rendclient.c
index 2540066dfc..2e119d7c99 100644
--- a/src/feature/rend/rendclient.c
+++ b/src/feature/rend/rendclient.c
@@ -831,7 +831,7 @@ rend_client_report_intro_point_failure(extend_info_t *failed_intro,
log_warn(LD_BUG, "Unknown failure type %u. Removing intro point.",
failure_type);
tor_fragile_assert();
- /* fall through */
+ FALLTHROUGH;
case INTRO_POINT_FAILURE_GENERIC:
rend_cache_intro_failure_note(failure_type,
(uint8_t *)failed_intro->identity_digest,
diff --git a/src/lib/cc/compat_compiler.h b/src/lib/cc/compat_compiler.h
index 3ef866ecce..d9ccabb2b3 100644
--- a/src/lib/cc/compat_compiler.h
+++ b/src/lib/cc/compat_compiler.h
@@ -50,6 +50,12 @@
#define CHECK_SCANF(formatIdx, firstArg)
#endif /* defined(__GNUC__) */
+#if defined(HAVE_ATTR_FALLTHROUGH)
+#define FALLTHROUGH __attribute__((fallthrough))
+#else
+#define FALLTHROUGH
+#endif
+
/* What GCC do we have? */
#ifdef __GNUC__
#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
diff --git a/src/lib/crypt_ops/crypto_digest_nss.c b/src/lib/crypt_ops/crypto_digest_nss.c
index b73f0736fd..afa8f6d5ef 100644
--- a/src/lib/crypt_ops/crypto_digest_nss.c
+++ b/src/lib/crypt_ops/crypto_digest_nss.c
@@ -37,8 +37,8 @@ digest_alg_to_nss_oid(digest_algorithm_t alg)
case DIGEST_SHA1: return SEC_OID_SHA1;
case DIGEST_SHA256: return SEC_OID_SHA256;
case DIGEST_SHA512: return SEC_OID_SHA512;
- case DIGEST_SHA3_256: /* Fall through */
- case DIGEST_SHA3_512: /* Fall through */
+ case DIGEST_SHA3_256: FALLTHROUGH;
+ case DIGEST_SHA3_512: FALLTHROUGH;
default:
return SEC_OID_UNKNOWN;
}
@@ -85,12 +85,12 @@ static bool
library_supports_digest(digest_algorithm_t alg)
{
switch (alg) {
- case DIGEST_SHA1: /* Fall through */
- case DIGEST_SHA256: /* Fall through */
- case DIGEST_SHA512: /* Fall through */
+ case DIGEST_SHA1: FALLTHROUGH;
+ case DIGEST_SHA256: FALLTHROUGH;
+ case DIGEST_SHA512:
return true;
- case DIGEST_SHA3_256: /* Fall through */
- case DIGEST_SHA3_512: /* Fall through */
+ case DIGEST_SHA3_256: FALLTHROUGH;
+ case DIGEST_SHA3_512: FALLTHROUGH;
default:
return false;
}
@@ -197,8 +197,8 @@ crypto_digest_alloc_bytes(digest_algorithm_t alg)
#define END_OF_FIELD(f) (offsetof(crypto_digest_t, f) + \
STRUCT_FIELD_SIZE(crypto_digest_t, f))
switch (alg) {
- case DIGEST_SHA1: /* Fall through */
- case DIGEST_SHA256: /* Fall through */
+ case DIGEST_SHA1: FALLTHROUGH;
+ case DIGEST_SHA256: FALLTHROUGH;
case DIGEST_SHA512:
return END_OF_FIELD(d.ctx);
case DIGEST_SHA3_256:
@@ -224,8 +224,8 @@ crypto_digest_new_internal(digest_algorithm_t algorithm)
switch (algorithm)
{
- case DIGEST_SHA1: /* fall through */
- case DIGEST_SHA256: /* fall through */
+ case DIGEST_SHA1: FALLTHROUGH;
+ case DIGEST_SHA256: FALLTHROUGH;
case DIGEST_SHA512:
r->d.ctx = PK11_CreateDigestContext(digest_alg_to_nss_oid(algorithm));
if (BUG(!r->d.ctx)) {
@@ -312,8 +312,8 @@ crypto_digest_add_bytes(crypto_digest_t *digest, const char *data,
* just doing it ourselves. Hashes are fast.
*/
switch (digest->algorithm) {
- case DIGEST_SHA1: /* fall through */
- case DIGEST_SHA256: /* fall through */
+ case DIGEST_SHA1: FALLTHROUGH;
+ case DIGEST_SHA256: FALLTHROUGH;
case DIGEST_SHA512:
tor_assert(len <= UINT_MAX);
SECStatus s = PK11_DigestOp(digest->d.ctx,
@@ -321,7 +321,7 @@ crypto_digest_add_bytes(crypto_digest_t *digest, const char *data,
(unsigned int)len);
tor_assert(s == SECSuccess);
break;
- case DIGEST_SHA3_256: /* FALLSTHROUGH */
+ case DIGEST_SHA3_256: FALLTHROUGH;
case DIGEST_SHA3_512:
keccak_digest_update(&digest->d.sha3, (const uint8_t *)data, len);
break;
@@ -557,4 +557,3 @@ crypto_hmac_sha256(char *hmac_out,
tor_assert(ok);
}
-
diff --git a/src/lib/crypt_ops/crypto_digest_openssl.c b/src/lib/crypt_ops/crypto_digest_openssl.c
index b0d8b6aee9..50a8ff4d27 100644
--- a/src/lib/crypt_ops/crypto_digest_openssl.c
+++ b/src/lib/crypt_ops/crypto_digest_openssl.c
@@ -160,11 +160,11 @@ crypto_digest_alloc_bytes(digest_algorithm_t alg)
case DIGEST_SHA512:
return END_OF_FIELD(d.sha512);
#ifdef OPENSSL_HAS_SHA3
- case DIGEST_SHA3_256: /* Fall through */
+ case DIGEST_SHA3_256: FALLTHROUGH;
case DIGEST_SHA3_512:
return END_OF_FIELD(d.md);
#else
- case DIGEST_SHA3_256: /* Fall through */
+ case DIGEST_SHA3_256: FALLTHROUGH;
case DIGEST_SHA3_512:
return END_OF_FIELD(d.sha3);
#endif /* defined(OPENSSL_HAS_SHA3) */
@@ -304,14 +304,14 @@ crypto_digest_add_bytes(crypto_digest_t *digest, const char *data,
SHA512_Update(&digest->d.sha512, (void*)data, len);
break;
#ifdef OPENSSL_HAS_SHA3
- case DIGEST_SHA3_256: /* FALLSTHROUGH */
+ case DIGEST_SHA3_256: FALLTHROUGH;
case DIGEST_SHA3_512: {
int r = EVP_DigestUpdate(digest->d.md, data, len);
tor_assert(r);
}
break;
#else /* !defined(OPENSSL_HAS_SHA3) */
- case DIGEST_SHA3_256: /* FALLSTHROUGH */
+ case DIGEST_SHA3_256: FALLTHROUGH;
case DIGEST_SHA3_512:
keccak_digest_update(&digest->d.sha3, (const uint8_t *)data, len);
break;
@@ -377,7 +377,7 @@ crypto_digest_get_digest(crypto_digest_t *digest,
SHA512_Final(r, &tmpenv.d.sha512);
break;
//LCOV_EXCL_START
- case DIGEST_SHA3_256: /* FALLSTHROUGH */
+ case DIGEST_SHA3_256: FALLTHROUGH;
case DIGEST_SHA3_512:
default:
log_warn(LD_BUG, "Handling unexpected algorithm %d", digest->algorithm);
diff --git a/src/lib/crypt_ops/crypto_ed25519.c b/src/lib/crypt_ops/crypto_ed25519.c
index 0581529125..c28111a5a5 100644
--- a/src/lib/crypt_ops/crypto_ed25519.c
+++ b/src/lib/crypt_ops/crypto_ed25519.c
@@ -795,7 +795,7 @@ ed25519_point_is_identity_element(const uint8_t *point)
int
ed25519_validate_pubkey(const ed25519_public_key_t *pubkey)
{
- uint8_t result[32] = {9};
+ uint8_t result[32] = {0};
/* First check that we were not given the identity element */
if (ed25519_point_is_identity_element(pubkey->pubkey)) {
diff --git a/src/lib/crypt_ops/crypto_rsa.c b/src/lib/crypt_ops/crypto_rsa.c
index c39d2e18d1..1289a82e62 100644
--- a/src/lib/crypt_ops/crypto_rsa.c
+++ b/src/lib/crypt_ops/crypto_rsa.c
@@ -490,7 +490,7 @@ crypto_pk_write_private_key_to_string(crypto_pk_t *env,
static int
crypto_pk_read_from_string_generic(crypto_pk_t *env, const char *src,
size_t len, int severity,
- bool private_key)
+ bool private_key, int max_bits)
{
if (len == (size_t)-1) // "-1" indicates "use the length of the string."
len = strlen(src);
@@ -510,7 +510,7 @@ crypto_pk_read_from_string_generic(crypto_pk_t *env, const char *src,
}
crypto_pk_t *pk = private_key
- ? crypto_pk_asn1_decode_private((const char*)buf, n)
+ ? crypto_pk_asn1_decode_private((const char*)buf, n, max_bits)
: crypto_pk_asn1_decode((const char*)buf, n);
if (! pk) {
log_fn(severity, LD_CRYPTO,
@@ -539,7 +539,8 @@ int
crypto_pk_read_public_key_from_string(crypto_pk_t *env,
const char *src, size_t len)
{
- return crypto_pk_read_from_string_generic(env, src, len, LOG_INFO, false);
+ return crypto_pk_read_from_string_generic(env, src, len, LOG_INFO, false,
+ -1);
}
/** Read a PEM-encoded private key from the <b>len</b>-byte string <b>src</b>
@@ -550,7 +551,21 @@ int
crypto_pk_read_private_key_from_string(crypto_pk_t *env,
const char *src, ssize_t len)
{
- return crypto_pk_read_from_string_generic(env, src, len, LOG_INFO, true);
+ return crypto_pk_read_from_string_generic(env, src, len, LOG_INFO, true,
+ -1);
+}
+
+/**
+ * As crypto_pk_read_private_key_from_string(), but reject any key
+ * with a modulus longer than 1024 bits before doing any expensive
+ * validation on it.
+ */
+int
+crypto_pk_read_private_key1024_from_string(crypto_pk_t *env,
+ const char *src, ssize_t len)
+{
+ return crypto_pk_read_from_string_generic(env, src, len, LOG_INFO, true,
+ 1024);
}
/** If a file is longer than this, we won't try to decode its private key */
@@ -578,7 +593,7 @@ crypto_pk_read_private_key_from_filename(crypto_pk_t *env,
}
int rv = crypto_pk_read_from_string_generic(env, buf, (ssize_t)st.st_size,
- LOG_WARN, true);
+ LOG_WARN, true, -1);
if (rv < 0) {
log_warn(LD_CRYPTO, "Unable to decode private key from file %s",
escaped(keyfile));
@@ -662,7 +677,7 @@ crypto_pk_base64_decode_private(const char *str, size_t len)
goto out;
}
- pk = crypto_pk_asn1_decode_private(der, der_len);
+ pk = crypto_pk_asn1_decode_private(der, der_len, -1);
out:
memwipe(der, 0, len+1);
diff --git a/src/lib/crypt_ops/crypto_rsa.h b/src/lib/crypt_ops/crypto_rsa.h
index e9bfec2f85..01e6d10906 100644
--- a/src/lib/crypt_ops/crypto_rsa.h
+++ b/src/lib/crypt_ops/crypto_rsa.h
@@ -61,6 +61,8 @@ int crypto_pk_read_public_key_from_string(crypto_pk_t *env,
const char *src, size_t len);
int crypto_pk_read_private_key_from_string(crypto_pk_t *env,
const char *s, ssize_t len);
+int crypto_pk_read_private_key1024_from_string(crypto_pk_t *env,
+ const char *src, ssize_t len);
int crypto_pk_write_private_key_to_filename(crypto_pk_t *env,
const char *fname);
@@ -95,7 +97,8 @@ int crypto_pk_asn1_encode(const crypto_pk_t *pk, char *dest, size_t dest_len);
crypto_pk_t *crypto_pk_asn1_decode(const char *str, size_t len);
int crypto_pk_asn1_encode_private(const crypto_pk_t *pk,
char *dest, size_t dest_len);
-crypto_pk_t *crypto_pk_asn1_decode_private(const char *str, size_t len);
+crypto_pk_t *crypto_pk_asn1_decode_private(const char *str, size_t len,
+ int max_bits);
int crypto_pk_get_fingerprint(crypto_pk_t *pk, char *fp_out,int add_space);
int crypto_pk_get_hashed_fingerprint(crypto_pk_t *pk, char *fp_out);
void crypto_add_spaces_to_fp(char *out, size_t outlen, const char *in);
diff --git a/src/lib/crypt_ops/crypto_rsa_nss.c b/src/lib/crypt_ops/crypto_rsa_nss.c
index 612b7a0e64..fd8fda486e 100644
--- a/src/lib/crypt_ops/crypto_rsa_nss.c
+++ b/src/lib/crypt_ops/crypto_rsa_nss.c
@@ -679,9 +679,12 @@ crypto_pk_asn1_encode_private(const crypto_pk_t *pk,
/** Given a buffer containing the DER representation of the
* private key <b>str</b>, decode and return the result on success, or NULL
* on failure.
+ *
+ * If <b>max_bits</b> is nonnegative, reject any key longer than max_bits
+ * without performing any expensive validation on it.
*/
crypto_pk_t *
-crypto_pk_asn1_decode_private(const char *str, size_t len)
+crypto_pk_asn1_decode_private(const char *str, size_t len, int max_bits)
{
tor_assert(str);
tor_assert(len < INT_MAX);
@@ -731,6 +734,15 @@ crypto_pk_asn1_decode_private(const char *str, size_t len)
output = NULL;
}
+ if (output) {
+ const int bits = SECKEY_PublicKeyStrengthInBits(output->pubkey);
+ if (max_bits >= 0 && bits > max_bits) {
+ log_info(LD_CRYPTO, "Private key longer than expected.");
+ crypto_pk_free(output);
+ output = NULL;
+ }
+ }
+
if (slot)
PK11_FreeSlot(slot);
diff --git a/src/lib/crypt_ops/crypto_rsa_openssl.c b/src/lib/crypt_ops/crypto_rsa_openssl.c
index 05d7c26b25..41d936d25b 100644
--- a/src/lib/crypt_ops/crypto_rsa_openssl.c
+++ b/src/lib/crypt_ops/crypto_rsa_openssl.c
@@ -33,6 +33,7 @@ ENABLE_GCC_WARNING(redundant-decls)
#include "lib/encoding/binascii.h"
#include <string.h>
+#include <stdbool.h>
/** Declaration for crypto_pk_t structure. */
struct crypto_pk_t
@@ -564,11 +565,71 @@ crypto_pk_asn1_encode_private(const crypto_pk_t *pk, char *dest,
return len;
}
+/** Check whether any component of a private key is too large in a way that
+ * seems likely to make verification too expensive. Return true if it's too
+ * long, and false otherwise. */
+static bool
+rsa_private_key_too_long(RSA *rsa, int max_bits)
+{
+ const BIGNUM *n, *e, *p, *q, *d, *dmp1, *dmq1, *iqmp;
+#ifdef OPENSSL_1_1_API
+
+#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,1)
+ n = RSA_get0_n(rsa);
+ e = RSA_get0_e(rsa);
+ p = RSA_get0_p(rsa);
+ q = RSA_get0_q(rsa);
+ d = RSA_get0_d(rsa);
+ dmp1 = RSA_get0_dmp1(rsa);
+ dmq1 = RSA_get0_dmq1(rsa);
+ iqmp = RSA_get0_iqmp(rsa);
+#else
+ /* The accessors above did not exist in openssl 1.1.0. */
+ p = q = dmp1 = dmq1 = iqmp = NULL;
+ RSA_get0_key(rsa, &n, &e, &d);
+#endif
+
+ if (RSA_bits(rsa) > max_bits)
+ return true;
+#else
+ n = rsa->n;
+ e = rsa->e;
+ p = rsa->p;
+ q = rsa->q;
+ d = rsa->d;
+ dmp1 = rsa->dmp1;
+ dmq1 = rsa->dmq1;
+ iqmp = rsa->iqmp;
+#endif
+
+ if (n && BN_num_bits(n) > max_bits)
+ return true;
+ if (e && BN_num_bits(e) > max_bits)
+ return true;
+ if (p && BN_num_bits(p) > max_bits)
+ return true;
+ if (q && BN_num_bits(q) > max_bits)
+ return true;
+ if (d && BN_num_bits(d) > max_bits)
+ return true;
+ if (dmp1 && BN_num_bits(dmp1) > max_bits)
+ return true;
+ if (dmq1 && BN_num_bits(dmq1) > max_bits)
+ return true;
+ if (iqmp && BN_num_bits(iqmp) > max_bits)
+ return true;
+
+ return false;
+}
+
/** Decode an ASN.1-encoded private key from <b>str</b>; return the result on
* success and NULL on failure.
+ *
+ * If <b>max_bits</b> is nonnegative, reject any key longer than max_bits
+ * without performing any expensive validation on it.
*/
crypto_pk_t *
-crypto_pk_asn1_decode_private(const char *str, size_t len)
+crypto_pk_asn1_decode_private(const char *str, size_t len, int max_bits)
{
RSA *rsa;
unsigned char *buf;
@@ -578,7 +639,12 @@ crypto_pk_asn1_decode_private(const char *str, size_t len)
rsa = d2i_RSAPrivateKey(NULL, &cp, len);
tor_free(buf);
if (!rsa) {
- crypto_openssl_log_errors(LOG_WARN,"decoding public key");
+ crypto_openssl_log_errors(LOG_WARN,"decoding private key");
+ return NULL;
+ }
+ if (max_bits >= 0 && rsa_private_key_too_long(rsa, max_bits)) {
+ log_info(LD_CRYPTO, "Private key longer than expected.");
+ RSA_free(rsa);
return NULL;
}
crypto_pk_t *result = crypto_new_pk_from_openssl_rsa_(rsa);
diff --git a/src/lib/err/torerr.c b/src/lib/err/torerr.c
index 0a4ee5d417..a5c00ca389 100644
--- a/src/lib/err/torerr.c
+++ b/src/lib/err/torerr.c
@@ -151,32 +151,6 @@ tor_log_reset_sigsafe_err_fds(void)
}
/**
- * Close the list of fds that get errors from inside a signal handler or
- * other emergency condition. These fds are shared with the logging code:
- * closing them flushes the log buffers, and prevents any further logging.
- *
- * This function closes stderr, so it should only be called immediately before
- * process shutdown.
- */
-void
-tor_log_close_sigsafe_err_fds(void)
-{
- int n_fds, i;
- const int *fds = NULL;
-
- n_fds = tor_log_get_sigsafe_err_fds(&fds);
- for (i = 0; i < n_fds; ++i) {
- /* tor_log_close_sigsafe_err_fds_on_error() is called on error and on
- * shutdown, so we can't log or take any useful action if close()
- * fails. */
- (void)close(fds[i]);
- }
-
- /* Don't even try logging, we've closed all the log fds. */
- tor_log_set_sigsafe_err_fds(NULL, 0);
-}
-
-/**
* Set the granularity (in ms) to use when reporting fatal errors outside
* the logging system.
*/
@@ -217,13 +191,12 @@ tor_raw_assertion_failed_msg_(const char *file, int line, const char *expr,
/**
* Call the abort() function to kill the current process with a fatal
- * error. But first, close the raw error file descriptors, so error messages
- * are written before process termination.
+ * error. This is a separate function, so that log users don't have to include
+ * the header for abort().
**/
void
tor_raw_abort_(void)
{
- tor_log_close_sigsafe_err_fds();
abort();
}
diff --git a/src/lib/err/torerr.h b/src/lib/err/torerr.h
index 0e839cb1ba..a1822d9c9a 100644
--- a/src/lib/err/torerr.h
+++ b/src/lib/err/torerr.h
@@ -40,7 +40,6 @@ void tor_log_err_sigsafe(const char *m, ...);
int tor_log_get_sigsafe_err_fds(const int **out);
void tor_log_set_sigsafe_err_fds(const int *fds, int n);
void tor_log_reset_sigsafe_err_fds(void);
-void tor_log_close_sigsafe_err_fds(void);
void tor_log_sigsafe_err_set_granularity(int ms);
void tor_raw_abort_(void) ATTR_NORETURN;
diff --git a/src/lib/err/torerr_sys.c b/src/lib/err/torerr_sys.c
index eb818004fb..c42e958093 100644
--- a/src/lib/err/torerr_sys.c
+++ b/src/lib/err/torerr_sys.c
@@ -27,11 +27,8 @@ subsys_torerr_initialize(void)
static void
subsys_torerr_shutdown(void)
{
- /* Stop handling signals with backtraces, then close the logs. */
+ /* Stop handling signals with backtraces. */
clean_up_backtrace_handler();
- /* We can't log any log messages after this point: we've closed all the log
- * fds, including stdio. */
- tor_log_close_sigsafe_err_fds();
}
const subsys_fns_t sys_torerr = {
diff --git a/src/lib/log/log.c b/src/lib/log/log.c
index 83f04a3467..c53db46a8c 100644
--- a/src/lib/log/log.c
+++ b/src/lib/log/log.c
@@ -667,12 +667,8 @@ tor_log_update_sigsafe_err_fds(void)
/* log_fds and err_fds contain matching entries: log_fds are the fds used by
* the log module, and err_fds are the fds used by the err module.
- * For stdio logs, the log_fd and err_fd values are identical,
- * and the err module closes the fd on shutdown.
- * For file logs, the err_fd is a dup() of the log_fd,
- * and the log and err modules both close their respective fds on shutdown.
- * (Once all fds representing a file are closed, the underlying file is
- * closed.)
+ * For stdio logs, the log_fd and err_fd values are identical.
+ * For file logs, the err_fd is a dup() of the log_fd.
*/
int log_fds[TOR_SIGSAFE_LOG_MAX_FDS];
int err_fds[TOR_SIGSAFE_LOG_MAX_FDS];
@@ -704,12 +700,10 @@ tor_log_update_sigsafe_err_fds(void)
log_fds[n_fds] = lf->fd;
if (lf->needs_close) {
/* File log fds are duplicated, because close_log() closes the log
- * module's fd, and tor_log_close_sigsafe_err_fds() closes the err
* module's fd. Both refer to the same file. */
err_fds[n_fds] = dup(lf->fd);
} else {
- /* stdio log fds are not closed by the log module.
- * tor_log_close_sigsafe_err_fds() closes stdio logs. */
+ /* stdio log fds are not closed by the log module. */
err_fds[n_fds] = lf->fd;
}
n_fds++;
@@ -841,30 +835,6 @@ logs_free_all(void)
* log mutex. */
}
-/** Close signal-safe log files.
- * Closing the log files makes the process and OS flush log buffers.
- *
- * This function is safe to call from a signal handler. It should only be
- * called when shutting down the log or err modules. It is currenly called
- * by the err module, when terminating the process on an abnormal condition.
- */
-void
-logs_close_sigsafe(void)
-{
- logfile_t *victim, *next;
- /* We can't LOCK_LOGS() in a signal handler, because it may call
- * signal-unsafe functions. And we can't deallocate memory, either. */
- next = logfiles;
- logfiles = NULL;
- while (next) {
- victim = next;
- next = next->next;
- if (victim->needs_close) {
- close_log_sigsafe(victim);
- }
- }
-}
-
/** Remove and free the log entry <b>victim</b> from the linked-list
* logfiles (it is probably present, but it might not be due to thread
* racing issues). After this function is called, the caller shouldn't
diff --git a/src/lib/log/log.h b/src/lib/log/log.h
index 8e36012616..f09c63cdd9 100644
--- a/src/lib/log/log.h
+++ b/src/lib/log/log.h
@@ -184,7 +184,6 @@ void logs_set_domain_logging(int enabled);
int get_min_log_level(void);
void switch_logs_debug(void);
void logs_free_all(void);
-void logs_close_sigsafe(void);
void add_temp_log(int min_severity);
void close_temp_logs(void);
void rollback_log_changes(void);
diff --git a/src/lib/log/util_bug.c b/src/lib/log/util_bug.c
index 72c614a3b2..af1ac40732 100644
--- a/src/lib/log/util_bug.c
+++ b/src/lib/log/util_bug.c
@@ -163,8 +163,7 @@ tor_bug_occurred_(const char *fname, unsigned int line,
/**
* Call the tor_raw_abort_() function to close raw logs, then kill the current
- * process with a fatal error. But first, close the file-based log file
- * descriptors, so error messages are written before process termination.
+ * process with a fatal error.
*
* (This is a separate function so that we declare it in util_bug.h without
* including torerr.h in all the users of util_bug.h)
@@ -172,7 +171,6 @@ tor_bug_occurred_(const char *fname, unsigned int line,
void
tor_abort_(void)
{
- logs_close_sigsafe();
tor_raw_abort_();
}
diff --git a/src/lib/log/util_bug.h b/src/lib/log/util_bug.h
index 030bfa2cc9..7eaa6173c8 100644
--- a/src/lib/log/util_bug.h
+++ b/src/lib/log/util_bug.h
@@ -196,7 +196,7 @@
STMT_END
#define BUG(cond) \
(ASSERT_PREDICT_UNLIKELY_(cond) ? \
- (tor_bug_occurred_(SHORT_FILE__,__LINE__,__func__,"!("#cond")",1,NULL),1) \
+ (tor_bug_occurred_(SHORT_FILE__,__LINE__,__func__,"!("#cond")",0,NULL),1) \
: 0)
#endif /* defined(ALL_BUGS_ARE_FATAL) || ... */
diff --git a/src/lib/net/address.c b/src/lib/net/address.c
index 0a2c84caf2..41017935e1 100644
--- a/src/lib/net/address.c
+++ b/src/lib/net/address.c
@@ -929,6 +929,7 @@ tor_addr_copy_tight(tor_addr_t *dest, const tor_addr_t *src)
break;
case AF_INET6:
memcpy(dest->addr.in6_addr.s6_addr, src->addr.in6_addr.s6_addr, 16);
+ break;
case AF_UNSPEC:
break;
// LCOV_EXCL_START
diff --git a/src/lib/tls/buffers_tls.c b/src/lib/tls/buffers_tls.c
index bf03b61459..ed0f821ce8 100644
--- a/src/lib/tls/buffers_tls.c
+++ b/src/lib/tls/buffers_tls.c
@@ -146,10 +146,10 @@ buf_flush_to_tls(buf_t *buf, tor_tls_t *tls, size_t flushlen,
size_t flushed = 0;
ssize_t sz;
tor_assert(buf_flushlen);
- if (BUG(*buf_flushlen > buf->datalen)) {
+ IF_BUG_ONCE(*buf_flushlen > buf->datalen) {
*buf_flushlen = buf->datalen;
}
- if (BUG(flushlen > *buf_flushlen)) {
+ IF_BUG_ONCE(flushlen > *buf_flushlen) {
flushlen = *buf_flushlen;
}
sz = (ssize_t) flushlen;
diff --git a/src/test/test_address_set.c b/src/test/test_address_set.c
index fb8408b3c3..6e299d779e 100644
--- a/src/test/test_address_set.c
+++ b/src/test/test_address_set.c
@@ -4,6 +4,7 @@
#include "core/or/or.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "core/or/address_set.h"
+#include "feature/nodelist/dirlist.h"
#include "feature/nodelist/microdesc.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/nodelist.h"
@@ -31,6 +32,12 @@ mock_networkstatus_get_latest_consensus_by_flavor(consensus_flavor_t f)
return dummy_ns;
}
+static void
+mock_dirlist_add_trusted_dir_addresses(void)
+{
+ return;
+}
+
/* Number of address a single node_t can have. Default to the production
* value. This is to control the size of the bloom filter. */
static int addr_per_node = 2;
@@ -98,6 +105,8 @@ test_nodelist(void *arg)
mock_networkstatus_get_latest_consensus_by_flavor);
MOCK(get_estimated_address_per_node,
mock_get_estimated_address_per_node);
+ MOCK(dirlist_add_trusted_dir_addresses,
+ mock_dirlist_add_trusted_dir_addresses);
dummy_ns = tor_malloc_zero(sizeof(*dummy_ns));
dummy_ns->flavor = FLAV_MICRODESC;
@@ -113,7 +122,10 @@ test_nodelist(void *arg)
* (the_nodelist->node_addrs) so we will fail the contain test rarely. */
addr_per_node = 1024;
- /* No node no nothing. The lookups should be empty. */
+ /* No node no nothing. The lookups should be empty. We've mocked the
+ * dirlist_add_trusted_dir_addresses in order for _no_ authorities to be
+ * added to the filter else it makes this test to trigger many false
+ * positive. */
nodelist_set_consensus(dummy_ns);
/* The address set should be empty. */
@@ -167,6 +179,7 @@ test_nodelist(void *arg)
UNMOCK(networkstatus_get_latest_consensus);
UNMOCK(networkstatus_get_latest_consensus_by_flavor);
UNMOCK(get_estimated_address_per_node);
+ UNMOCK(dirlist_add_trusted_dir_addresses);
}
struct testcase_t address_set_tests[] = {
diff --git a/src/test/test_bwmgt.c b/src/test/test_bwmgt.c
index 5a013aa268..e6f028ed74 100644
--- a/src/test/test_bwmgt.c
+++ b/src/test/test_bwmgt.c
@@ -6,18 +6,67 @@
* \brief tests for bandwidth management / token bucket functions
*/
+#define CONFIG_PRIVATE
+#define CONNECTION_PRIVATE
#define TOKEN_BUCKET_PRIVATE
#include "core/or/or.h"
-#include "test/test.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "feature/dircommon/directory.h"
+#include "feature/nodelist/microdesc.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "feature/nodelist/routerlist.h"
+#include "lib/crypt_ops/crypto_rand.h"
#include "lib/evloop/token_bucket.h"
+#include "test/test.h"
+#include "test/test_helpers.h"
+
+#include "app/config/or_options_st.h"
+#include "core/or/connection_st.h"
+#include "feature/nodelist/microdesc_st.h"
+#include "feature/nodelist/networkstatus_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "feature/nodelist/routerstatus_st.h"
// an imaginary time, in timestamp units. Chosen so it will roll over.
static const uint32_t START_TS = UINT32_MAX-10;
static const int32_t KB = 1024;
static const uint32_t GB = (UINT64_C(1) << 30);
+static or_options_t mock_options;
+
+static const or_options_t *
+mock_get_options(void)
+{
+ return &mock_options;
+}
+
+static networkstatus_t *dummy_ns = NULL;
+static networkstatus_t *
+mock_networkstatus_get_latest_consensus(void)
+{
+ return dummy_ns;
+}
+
+static networkstatus_t *
+mock_networkstatus_get_latest_consensus_by_flavor(consensus_flavor_t f)
+{
+ tor_assert(f == FLAV_MICRODESC);
+ return dummy_ns;
+}
+
+/* Number of address a single node_t can have. Default to the production
+ * value. This is to control the size of the bloom filter. */
+static int addr_per_node = 2;
+static int
+mock_get_estimated_address_per_node(void)
+{
+ return addr_per_node;
+}
+
static void
test_bwmgt_token_buf_init(void *arg)
{
@@ -220,8 +269,162 @@ test_bwmgt_token_buf_helpers(void *arg)
;
}
+static void
+test_bwmgt_dir_conn_global_write_low(void *arg)
+{
+ bool ret;
+ int addr_family;
+ connection_t *conn = NULL;
+ routerstatus_t *rs = NULL; microdesc_t *md = NULL; routerinfo_t *ri = NULL;
+ tor_addr_t relay_addr;
+
+ (void) arg;
+
+ memset(&mock_options, 0, sizeof(or_options_t));
+ MOCK(networkstatus_get_latest_consensus,
+ mock_networkstatus_get_latest_consensus);
+ MOCK(networkstatus_get_latest_consensus_by_flavor,
+ mock_networkstatus_get_latest_consensus_by_flavor);
+ MOCK(get_estimated_address_per_node,
+ mock_get_estimated_address_per_node);
+
+ /*
+ * The following is rather complex but that is what it takes to add a dummy
+ * consensus with a valid routerlist which will populate our node address
+ * set that we need to lookup to test the known relay code path.
+ *
+ * We MUST do that before we MOCK(get_options) else it is another world of
+ * complexity.
+ */
+
+ /* This will be the address of our relay. */
+ tor_addr_parse(&relay_addr, "1.2.3.4");
+
+ /* We'll now add a relay into our routerlist and see if we let it. */
+ dummy_ns = tor_malloc_zero(sizeof(*dummy_ns));
+ dummy_ns->flavor = FLAV_MICRODESC;
+ dummy_ns->routerstatus_list = smartlist_new();
+
+ md = tor_malloc_zero(sizeof(*md));
+ ri = tor_malloc_zero(sizeof(*ri));
+ rs = tor_malloc_zero(sizeof(*rs));
+ crypto_rand(rs->identity_digest, sizeof(rs->identity_digest));
+ crypto_rand(md->digest, sizeof(md->digest));
+ memcpy(rs->descriptor_digest, md->digest, DIGEST256_LEN);
+
+ /* Set IP address. */
+ rs->addr = tor_addr_to_ipv4h(&relay_addr);
+ ri->addr = rs->addr;
+ /* Add the rs to the consensus becoming a node_t. */
+ smartlist_add(dummy_ns->routerstatus_list, rs);
+
+ /* Add all configured authorities (hardcoded) before we set the consensus so
+ * the address set exists. */
+ ret = consider_adding_dir_servers(&mock_options, &mock_options);
+ tt_int_op(ret, OP_EQ, 0);
+
+ /* This will make the nodelist bloom filter very large
+ * (the_nodelist->node_addrs) so we will fail the contain test rarely. */
+ addr_per_node = 1024;
+
+ nodelist_set_consensus(dummy_ns);
+
+ /* Ok, now time to control which options we use. */
+ MOCK(get_options, mock_get_options);
+
+ /* Set ourselves as an authoritative dir. */
+ mock_options.AuthoritativeDir = 1;
+ mock_options.V3AuthoritativeDir = 1;
+ mock_options.UseDefaultFallbackDirs = 0;
+
+ /* This will set our global bucket to 1 byte and thus we will hit the
+ * banwdith limit in our test. */
+ mock_options.BandwidthRate = 1;
+ mock_options.BandwidthBurst = 1;
+
+ /* Else an IPv4 address screams. */
+ mock_options.ClientUseIPv4 = 1;
+ mock_options.ClientUseIPv6 = 1;
+
+ /* Initialize the global buckets. */
+ connection_bucket_init();
+
+ /* The address "127.0.0.1" is set with this helper. */
+ conn = test_conn_get_connection(DIR_CONN_STATE_MIN_, CONN_TYPE_DIR,
+ DIR_PURPOSE_MIN_);
+ tt_assert(conn);
+
+ /* First try a non authority non relay IP thus a client but we are not
+ * configured to reject requests under load so we should get a false value
+ * that our limit is _not_ low. */
+ addr_family = tor_addr_parse(&conn->addr, "1.1.1.1");
+ tt_int_op(addr_family, OP_EQ, AF_INET);
+ ret = connection_dir_is_global_write_low(conn, INT_MAX);
+ tt_int_op(ret, OP_EQ, 0);
+
+ /* Now, we will reject requests under load so try again a non authority non
+ * relay IP thus a client. We should get a warning that our limit is too
+ * low. */
+ mock_options.AuthDirRejectRequestsUnderLoad = 1;
+
+ addr_family = tor_addr_parse(&conn->addr, "1.1.1.1");
+ tt_int_op(addr_family, OP_EQ, AF_INET);
+ ret = connection_dir_is_global_write_low(conn, INT_MAX);
+ tt_int_op(ret, OP_EQ, 1);
+
+ /* Now, lets try with a connection address from moria1. It should always
+ * pass even though our limit is too low. */
+ addr_family = tor_addr_parse(&conn->addr, "128.31.0.39");
+ tt_int_op(addr_family, OP_EQ, AF_INET);
+ ret = connection_dir_is_global_write_low(conn, INT_MAX);
+ tt_int_op(ret, OP_EQ, 0);
+
+ /* IPv6 testing of gabelmoo. */
+ addr_family = tor_addr_parse(&conn->addr, "[2001:638:a000:4140::ffff:189]");
+ tt_int_op(addr_family, OP_EQ, AF_INET6);
+ ret = connection_dir_is_global_write_low(conn, INT_MAX);
+ tt_int_op(ret, OP_EQ, 0);
+
+ /* Lets retry with a known relay address. It should pass. Possible due to
+ * our consensus setting above. */
+ memcpy(&conn->addr, &relay_addr, sizeof(tor_addr_t));
+ ret = connection_dir_is_global_write_low(conn, INT_MAX);
+ tt_int_op(ret, OP_EQ, 0);
+
+ /* Lets retry with a random IP that is not an authority nor a relay. */
+ addr_family = tor_addr_parse(&conn->addr, "1.2.3.4");
+ tt_int_op(addr_family, OP_EQ, AF_INET);
+ ret = connection_dir_is_global_write_low(conn, INT_MAX);
+ tt_int_op(ret, OP_EQ, 0);
+
+ /* Finally, just make sure it still denies an IP if we are _not_ a v3
+ * directory authority. */
+ mock_options.V3AuthoritativeDir = 0;
+ addr_family = tor_addr_parse(&conn->addr, "1.2.3.4");
+ tt_int_op(addr_family, OP_EQ, AF_INET);
+ ret = connection_dir_is_global_write_low(conn, INT_MAX);
+ tt_int_op(ret, OP_EQ, 1);
+
+ /* Random IPv6 should not be allowed. */
+ addr_family = tor_addr_parse(&conn->addr, "[CAFE::ACAB]");
+ tt_int_op(addr_family, OP_EQ, AF_INET6);
+ ret = connection_dir_is_global_write_low(conn, INT_MAX);
+ tt_int_op(ret, OP_EQ, 1);
+
+ done:
+ connection_free_minimal(conn);
+ routerstatus_free(rs); routerinfo_free(ri); microdesc_free(md);
+ smartlist_clear(dummy_ns->routerstatus_list);
+ networkstatus_vote_free(dummy_ns);
+
+ UNMOCK(get_estimated_address_per_node);
+ UNMOCK(networkstatus_get_latest_consensus);
+ UNMOCK(networkstatus_get_latest_consensus_by_flavor);
+ UNMOCK(get_options);
+}
+
#define BWMGT(name) \
- { #name, test_bwmgt_ ## name , 0, NULL, NULL }
+ { #name, test_bwmgt_ ## name , TT_FORK, NULL, NULL }
struct testcase_t bwmgt_tests[] = {
BWMGT(token_buf_init),
@@ -229,5 +432,7 @@ struct testcase_t bwmgt_tests[] = {
BWMGT(token_buf_dec),
BWMGT(token_buf_refill),
BWMGT(token_buf_helpers),
+
+ BWMGT(dir_conn_global_write_low),
END_OF_TESTCASES
};
diff --git a/src/test/test_controller_events.c b/src/test/test_controller_events.c
index 9fb2bc7256..0d276ef8a6 100644
--- a/src/test/test_controller_events.c
+++ b/src/test/test_controller_events.c
@@ -18,6 +18,7 @@
#include "feature/control/control_events.h"
#include "test/test.h"
#include "test/test_helpers.h"
+#include "test/log_test_helpers.h"
#include "core/or/or_circuit_st.h"
#include "core/or/origin_circuit_st.h"
@@ -396,6 +397,43 @@ test_cntev_dirboot_defer_orconn(void *arg)
}
static void
+test_cntev_signal(void *arg)
+{
+ (void)arg;
+ int rv;
+
+ MOCK(queue_control_event_string, mock_queue_control_event_string);
+
+ /* Nothing is listening for signals, so no event should be queued. */
+ rv = control_event_signal(SIGHUP);
+ tt_int_op(0, OP_EQ, rv);
+ tt_ptr_op(saved_event_str, OP_EQ, NULL);
+
+ /* Now try with signals included in the event mask. */
+ control_testing_set_global_event_mask(EVENT_MASK_(EVENT_GOT_SIGNAL));
+ rv = control_event_signal(SIGHUP);
+ tt_int_op(0, OP_EQ, rv);
+ tt_str_op(saved_event_str, OP_EQ, "650 SIGNAL RELOAD\r\n");
+
+ rv = control_event_signal(SIGACTIVE);
+ tt_int_op(0, OP_EQ, rv);
+ tt_str_op(saved_event_str, OP_EQ, "650 SIGNAL ACTIVE\r\n");
+
+ /* Try a signal that doesn't exist. */
+ setup_full_capture_of_logs(LOG_WARN);
+ tor_free(saved_event_str);
+ rv = control_event_signal(99999);
+ tt_int_op(-1, OP_EQ, rv);
+ tt_ptr_op(saved_event_str, OP_EQ, NULL);
+ expect_single_log_msg_containing("Unrecognized signal 99999");
+
+ done:
+ tor_free(saved_event_str);
+ teardown_capture_of_logs();
+ UNMOCK(queue_control_event_string);
+}
+
+static void
setup_orconn_state(orconn_state_msg_t *msg, uint64_t gid, uint64_t chan,
int proxy_type)
{
@@ -550,6 +588,7 @@ struct testcase_t controller_event_tests[] = {
TEST(event_mask, TT_FORK),
T_PUBSUB(dirboot_defer_desc, TT_FORK),
T_PUBSUB(dirboot_defer_orconn, TT_FORK),
+ T_PUBSUB(signal, TT_FORK),
T_PUBSUB(orconn_state, TT_FORK),
T_PUBSUB(orconn_state_pt, TT_FORK),
T_PUBSUB(orconn_state_proxy, TT_FORK),
diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c
index 67940aeac5..ed39f41560 100644
--- a/src/test/test_crypto.c
+++ b/src/test/test_crypto.c
@@ -1336,6 +1336,44 @@ test_crypto_pk_pem_encrypted(void *arg)
}
static void
+test_crypto_pk_bad_size(void *arg)
+{
+ (void)arg;
+ crypto_pk_t *pk1 = pk_generate(0);
+ crypto_pk_t *pk2 = NULL;
+ char buf[2048];
+ int n = crypto_pk_asn1_encode_private(pk1, buf, sizeof(buf));
+ tt_int_op(n, OP_GT, 0);
+
+ /* Set the max bit count smaller: we should refuse to decode the key.*/
+ pk2 = crypto_pk_asn1_decode_private(buf, n, 1020);
+ tt_assert(! pk2);
+
+ /* Set the max bit count one bit smaller: we should refuse to decode the
+ key.*/
+ pk2 = crypto_pk_asn1_decode_private(buf, n, 1023);
+ tt_assert(! pk2);
+
+ /* Correct size: should work. */
+ pk2 = crypto_pk_asn1_decode_private(buf, n, 1024);
+ tt_assert(pk2);
+ crypto_pk_free(pk2);
+
+ /* One bit larger: should work. */
+ pk2 = crypto_pk_asn1_decode_private(buf, n, 1025);
+ tt_assert(pk2);
+ crypto_pk_free(pk2);
+
+ /* Set the max bit count larger: it should decode fine. */
+ pk2 = crypto_pk_asn1_decode_private(buf, n, 2048);
+ tt_assert(pk2);
+
+ done:
+ crypto_pk_free(pk1);
+ crypto_pk_free(pk2);
+}
+
+static void
test_crypto_pk_invalid_private_key(void *arg)
{
(void)arg;
@@ -2998,6 +3036,7 @@ struct testcase_t crypto_tests[] = {
{ "pk_fingerprints", test_crypto_pk_fingerprints, TT_FORK, NULL, NULL },
{ "pk_base64", test_crypto_pk_base64, TT_FORK, NULL, NULL },
{ "pk_pem_encrypted", test_crypto_pk_pem_encrypted, TT_FORK, NULL, NULL },
+ { "pk_bad_size", test_crypto_pk_bad_size, 0, NULL, NULL },
{ "pk_invalid_private_key", test_crypto_pk_invalid_private_key, 0,
NULL, NULL },
CRYPTO_LEGACY(digests),
diff --git a/src/test/test_dos.c b/src/test/test_dos.c
index bda9908e6c..c17cfedbf6 100644
--- a/src/test/test_dos.c
+++ b/src/test/test_dos.c
@@ -79,7 +79,7 @@ test_dos_conn_creation(void *arg)
{ /* Register many conns from this client but not enough to get it blocked */
unsigned int i;
for (i = 0; i < max_concurrent_conns; i++) {
- dos_new_client_conn(&or_conn);
+ dos_new_client_conn(&or_conn, NULL);
}
}
@@ -88,7 +88,7 @@ test_dos_conn_creation(void *arg)
dos_conn_addr_get_defense_type(addr));
/* Register another conn and check that new conns are not allowed anymore */
- dos_new_client_conn(&or_conn);
+ dos_new_client_conn(&or_conn, NULL);
tt_int_op(DOS_CONN_DEFENSE_CLOSE, OP_EQ,
dos_conn_addr_get_defense_type(addr));
@@ -98,7 +98,7 @@ test_dos_conn_creation(void *arg)
dos_conn_addr_get_defense_type(addr));
/* Register another conn and see that defense measures get reactivated */
- dos_new_client_conn(&or_conn);
+ dos_new_client_conn(&or_conn, NULL);
tt_int_op(DOS_CONN_DEFENSE_CLOSE, OP_EQ,
dos_conn_addr_get_defense_type(addr));
@@ -153,7 +153,7 @@ test_dos_circuit_creation(void *arg)
* circuit counting subsystem */
geoip_note_client_seen(GEOIP_CLIENT_CONNECT, addr, NULL, now);
for (i = 0; i < min_conc_conns_for_cc ; i++) {
- dos_new_client_conn(&or_conn);
+ dos_new_client_conn(&or_conn, NULL);
}
/* Register new circuits for this client and conn, but not enough to get
@@ -217,7 +217,7 @@ test_dos_bucket_refill(void *arg)
/* Register this client */
geoip_note_client_seen(GEOIP_CLIENT_CONNECT, addr, NULL, now);
- dos_new_client_conn(&or_conn);
+ dos_new_client_conn(&or_conn, NULL);
/* Fetch this client from the geoip cache and get its DoS structs */
clientmap_entry_t *entry = geoip_lookup_client(addr, NULL,
@@ -460,11 +460,11 @@ test_known_relay(void *arg)
geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &or_conn.real_addr, NULL, 0);
/* Suppose we have 5 connections in rapid succession, the counter should
* always be 0 because we should ignore this. */
- dos_new_client_conn(&or_conn);
- dos_new_client_conn(&or_conn);
- dos_new_client_conn(&or_conn);
- dos_new_client_conn(&or_conn);
- dos_new_client_conn(&or_conn);
+ dos_new_client_conn(&or_conn, NULL);
+ dos_new_client_conn(&or_conn, NULL);
+ dos_new_client_conn(&or_conn, NULL);
+ dos_new_client_conn(&or_conn, NULL);
+ dos_new_client_conn(&or_conn, NULL);
entry = geoip_lookup_client(&or_conn.real_addr, NULL, GEOIP_CLIENT_CONNECT);
tt_assert(entry);
/* We should have a count of 0. */
@@ -474,8 +474,8 @@ test_known_relay(void *arg)
* connection and see if we do get it. */
tor_addr_parse(&or_conn.real_addr, "42.42.42.43");
geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &or_conn.real_addr, NULL, 0);
- dos_new_client_conn(&or_conn);
- dos_new_client_conn(&or_conn);
+ dos_new_client_conn(&or_conn, NULL);
+ dos_new_client_conn(&or_conn, NULL);
entry = geoip_lookup_client(&or_conn.real_addr, NULL, GEOIP_CLIENT_CONNECT);
tt_assert(entry);
/* We should have a count of 2. */
diff --git a/src/test/test_socks.c b/src/test/test_socks.c
index a4a768ce84..6d3ebd2320 100644
--- a/src/test/test_socks.c
+++ b/src/test/test_socks.c
@@ -778,7 +778,7 @@ test_socks_truncated(void *ptr)
for (i = 0; i < ARRAY_LENGTH(commands); ++i) {
for (j = 0; j < commands[i].len; ++j) {
switch (commands[i].setup) {
- default: /* Falls through */
+ default: FALLTHROUGH;
case NONE:
/* This test calls for no setup on the socks state. */
break;
diff --git a/src/test/testing_common.c b/src/test/testing_common.c
index ff6028ddb4..06a6f312ad 100644
--- a/src/test/testing_common.c
+++ b/src/test/testing_common.c
@@ -343,6 +343,21 @@ main(int c, const char **v)
atexit(remove_directory);
+ /* Look for TOR_SKIP_TESTCASES: a space-separated list of tests to skip. */
+ const char *skip_tests = getenv("TOR_SKIP_TESTCASES");
+ if (skip_tests) {
+ smartlist_t *skip = smartlist_new();
+ smartlist_split_string(skip, skip_tests, NULL,
+ SPLIT_IGNORE_BLANK, -1);
+ int n = 0;
+ SMARTLIST_FOREACH_BEGIN(skip, char *, cp) {
+ n += tinytest_skip(testgroups, cp);
+ tor_free(cp);
+ } SMARTLIST_FOREACH_END(cp);
+ printf("Skipping %d testcases.\n", n);
+ smartlist_free(skip);
+ }
+
int have_failed = (tinytest_main(c, v, testgroups) != 0);
free_pregenerated_keys();
diff --git a/src/win32/orconfig.h b/src/win32/orconfig.h
index 556c8b8056..f5f7046751 100644
--- a/src/win32/orconfig.h
+++ b/src/win32/orconfig.h
@@ -218,7 +218,7 @@
#define USING_TWOS_COMPLEMENT
/* Version number of package */
-#define VERSION "0.4.2.6-dev"
+#define VERSION "0.4.2.7-dev"