aboutsummaryrefslogtreecommitdiff
path: root/src/core/or/channeltls.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/or/channeltls.c')
-rw-r--r--src/core/or/channeltls.c156
1 files changed, 99 insertions, 57 deletions
diff --git a/src/core/or/channeltls.c b/src/core/or/channeltls.c
index 18025ff73a..f9eb67c399 100644
--- a/src/core/or/channeltls.c
+++ b/src/core/or/channeltls.c
@@ -1,4 +1,4 @@
-/* * Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* * Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -34,7 +34,7 @@
* Define this so channel.h gives us things only channel_t subclasses
* should touch.
*/
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#define CHANNELTLS_PRIVATE
@@ -45,8 +45,10 @@
#include "core/or/circuitmux_ewma.h"
#include "core/or/command.h"
#include "app/config/config.h"
+#include "app/config/resolve_addr.h"
#include "core/mainloop/connection.h"
#include "core/or/connection_or.h"
+#include "feature/relay/relay_handshake.h"
#include "feature/control/control.h"
#include "feature/client/entrynodes.h"
#include "trunnel/link_handshake.h"
@@ -59,6 +61,7 @@
#include "feature/nodelist/torcert.h"
#include "feature/nodelist/networkstatus.h"
#include "trunnel/channelpadding_negotiation.h"
+#include "trunnel/netinfo.h"
#include "core/or/channelpadding.h"
#include "core/or/cell_st.h"
@@ -562,9 +565,7 @@ channel_tls_get_transport_name_method(channel_t *chan, char **transport_out)
static const char *
channel_tls_get_remote_descr_method(channel_t *chan, int flags)
{
-#define MAX_DESCR_LEN 32
-
- static char buf[MAX_DESCR_LEN + 1];
+ static char buf[TOR_ADDRPORT_BUF_LEN];
channel_tls_t *tlschan = BASE_CHAN_TO_TLS(chan);
connection_t *conn;
const char *answer = NULL;
@@ -577,15 +578,14 @@ channel_tls_get_remote_descr_method(channel_t *chan, int flags)
switch (flags) {
case 0:
/* Canonical address with port*/
- tor_snprintf(buf, MAX_DESCR_LEN + 1,
+ tor_snprintf(buf, TOR_ADDRPORT_BUF_LEN,
"%s:%u", conn->address, conn->port);
answer = buf;
break;
case GRD_FLAG_ORIGINAL:
/* Actual address with port */
addr_str = tor_addr_to_str_dup(&(tlschan->conn->real_addr));
- tor_snprintf(buf, MAX_DESCR_LEN + 1,
- "%s:%u", addr_str, conn->port);
+ tor_snprintf(buf, TOR_ADDRPORT_BUF_LEN, "%s:%u", addr_str, conn->port);
tor_free(addr_str);
answer = buf;
break;
@@ -724,10 +724,13 @@ channel_tls_matches_target_method(channel_t *chan,
* base_.addr is updated by connection_or_init_conn_from_address()
* to be the address in the descriptor. It may be tempting to
* allow either address to be allowed, but if we did so, it would
- * enable someone who steals a relay's keys to impersonate/MITM it
+ * enable someone who steals a relay's keys to covertly impersonate/MITM it
* from anywhere on the Internet! (Because they could make long-lived
* TLS connections from anywhere to all relays, and wait for them to
* be used for extends).
+ *
+ * An adversary who has stolen a relay's keys could also post a fake relay
+ * descriptor, but that attack is easier to detect.
*/
return tor_addr_eq(&(tlschan->conn->real_addr), target);
}
@@ -937,7 +940,6 @@ channel_tls_listener_describe_transport_method(channel_listener_t *chan_l)
void
channel_tls_handle_state_change_on_orconn(channel_tls_t *chan,
or_connection_t *conn,
- uint8_t old_state,
uint8_t state)
{
channel_t *base_chan;
@@ -946,8 +948,6 @@ channel_tls_handle_state_change_on_orconn(channel_tls_t *chan,
tor_assert(conn);
tor_assert(conn->chan == chan);
tor_assert(chan->conn == conn);
- /* Shut the compiler up without triggering -Wtautological-compare */
- (void)old_state;
base_chan = TLS_CHAN_TO_BASE(chan);
@@ -1017,6 +1017,16 @@ channel_tls_time_process_cell(cell_t *cell, channel_tls_t *chan, int *time,
}
#endif /* defined(KEEP_TIMING_STATS) */
+#ifdef KEEP_TIMING_STATS
+#define PROCESS_CELL(tp, cl, cn) STMT_BEGIN { \
+ ++num ## tp; \
+ channel_tls_time_process_cell(cl, cn, & tp ## time , \
+ channel_tls_process_ ## tp ## _cell); \
+ } STMT_END
+#else /* !defined(KEEP_TIMING_STATS) */
+#define PROCESS_CELL(tp, cl, cn) channel_tls_process_ ## tp ## _cell(cl, cn)
+#endif /* defined(KEEP_TIMING_STATS) */
+
/**
* Handle an incoming cell on a channel_tls_t.
*
@@ -1036,16 +1046,6 @@ channel_tls_handle_cell(cell_t *cell, or_connection_t *conn)
channel_tls_t *chan;
int handshaking;
-#ifdef KEEP_TIMING_STATS
-#define PROCESS_CELL(tp, cl, cn) STMT_BEGIN { \
- ++num ## tp; \
- channel_tls_time_process_cell(cl, cn, & tp ## time , \
- channel_tls_process_ ## tp ## _cell); \
- } STMT_END
-#else /* !(defined(KEEP_TIMING_STATS)) */
-#define PROCESS_CELL(tp, cl, cn) channel_tls_process_ ## tp ## _cell(cl, cn)
-#endif /* defined(KEEP_TIMING_STATS) */
-
tor_assert(cell);
tor_assert(conn);
@@ -1063,7 +1063,8 @@ channel_tls_handle_cell(cell_t *cell, or_connection_t *conn)
return;
/* Reject all but VERSIONS and NETINFO when handshaking. */
- /* (VERSIONS should actually be impossible; it's variable-length.) */
+ /* (VERSIONS actually indicates a protocol warning: it's variable-length,
+ * so if it reaches this function, we're on a v1 connection.) */
if (handshaking && cell->command != CELL_VERSIONS &&
cell->command != CELL_NETINFO) {
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
@@ -1084,13 +1085,13 @@ channel_tls_handle_cell(cell_t *cell, or_connection_t *conn)
entry_guards_note_internet_connectivity(get_guard_selection_info());
rep_hist_padding_count_read(PADDING_TYPE_TOTAL);
- if (TLS_CHAN_TO_BASE(chan)->currently_padding)
+ if (TLS_CHAN_TO_BASE(chan)->padding_enabled)
rep_hist_padding_count_read(PADDING_TYPE_ENABLED_TOTAL);
switch (cell->command) {
case CELL_PADDING:
rep_hist_padding_count_read(PADDING_TYPE_CELL);
- if (TLS_CHAN_TO_BASE(chan)->currently_padding)
+ if (TLS_CHAN_TO_BASE(chan)->padding_enabled)
rep_hist_padding_count_read(PADDING_TYPE_ENABLED_CELL);
++stats_n_padding_cells_processed;
/* do nothing */
@@ -1317,6 +1318,8 @@ channel_tls_handle_var_cell(var_cell_t *var_cell, or_connection_t *conn)
}
}
+#undef PROCESS_CELL
+
/**
* Update channel marks after connection_or.c has changed an address.
*
@@ -1632,6 +1635,35 @@ channel_tls_process_padding_negotiate_cell(cell_t *cell, channel_tls_t *chan)
}
/**
+ * Convert <b>netinfo_addr</b> into corresponding <b>tor_addr</b>.
+ * Return 0 on success; on failure, return -1 and log a warning.
+ */
+static int
+tor_addr_from_netinfo_addr(tor_addr_t *tor_addr,
+ const netinfo_addr_t *netinfo_addr) {
+ tor_assert(tor_addr);
+ tor_assert(netinfo_addr);
+
+ uint8_t type = netinfo_addr_get_addr_type(netinfo_addr);
+ uint8_t len = netinfo_addr_get_len(netinfo_addr);
+
+ if (type == NETINFO_ADDR_TYPE_IPV4 && len == 4) {
+ uint32_t ipv4 = netinfo_addr_get_addr_ipv4(netinfo_addr);
+ tor_addr_from_ipv4h(tor_addr, ipv4);
+ } else if (type == NETINFO_ADDR_TYPE_IPV6 && len == 16) {
+ const uint8_t *ipv6_bytes = netinfo_addr_getconstarray_addr_ipv6(
+ netinfo_addr);
+ tor_addr_from_ipv6_bytes(tor_addr, ipv6_bytes);
+ } else {
+ log_fn(LOG_PROTOCOL_WARN, LD_OR, "Cannot read address from NETINFO "
+ "- wrong type/length.");
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
* Helper: compute the absolute value of a time_t.
*
* (we need this because labs() doesn't always work for time_t, since
@@ -1655,8 +1687,6 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
time_t timestamp;
uint8_t my_addr_type;
uint8_t my_addr_len;
- const uint8_t *my_addr_ptr;
- const uint8_t *cp, *end;
uint8_t n_other_addrs;
time_t now = time(NULL);
const routerinfo_t *me = router_get_my_routerinfo();
@@ -1704,7 +1734,7 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
tor_assert(tor_digest_is_zero(
(const char*)(chan->conn->handshake_state->
authenticated_rsa_peer_id)));
- tor_assert(tor_mem_is_zero(
+ tor_assert(fast_mem_is_zero(
(const char*)(chan->conn->handshake_state->
authenticated_ed25519_peer_id.pubkey), 32));
/* If the client never authenticated, it's a tor client or bridge
@@ -1727,38 +1757,48 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
}
/* Decode the cell. */
- timestamp = ntohl(get_uint32(cell->payload));
- const time_t sent_versions_at =
- chan->conn->handshake_state->sent_versions_at;
- if (now > sent_versions_at && (now - sent_versions_at) < 180) {
- /* If we have gotten the NETINFO cell reasonably soon after having
- * sent our VERSIONS cell, maybe we can learn skew information from it. */
- apparent_skew = now - timestamp;
+ netinfo_cell_t *netinfo_cell = NULL;
+
+ ssize_t parsed = netinfo_cell_parse(&netinfo_cell, cell->payload,
+ CELL_PAYLOAD_SIZE);
+
+ if (parsed < 0) {
+ log_fn(LOG_PROTOCOL_WARN, LD_OR,
+ "Failed to parse NETINFO cell - closing connection.");
+ connection_or_close_for_error(chan->conn, 0);
+ return;
}
- my_addr_type = (uint8_t) cell->payload[4];
- my_addr_len = (uint8_t) cell->payload[5];
- my_addr_ptr = (uint8_t*) cell->payload + 6;
- end = cell->payload + CELL_PAYLOAD_SIZE;
- cp = cell->payload + 6 + my_addr_len;
+ timestamp = netinfo_cell_get_timestamp(netinfo_cell);
+ const netinfo_addr_t *my_addr =
+ netinfo_cell_getconst_other_addr(netinfo_cell);
+
+ my_addr_type = netinfo_addr_get_addr_type(my_addr);
+ my_addr_len = netinfo_addr_get_len(my_addr);
+
+ if ((now - chan->conn->handshake_state->sent_versions_at) < 180) {
+ apparent_skew = now - timestamp;
+ }
/* We used to check:
* if (my_addr_len >= CELL_PAYLOAD_SIZE - 6) {
*
* This is actually never going to happen, since my_addr_len is at most 255,
* and CELL_PAYLOAD_LEN - 6 is 503. So we know that cp is < end. */
- if (my_addr_type == RESOLVED_TYPE_IPV4 && my_addr_len == 4) {
- tor_addr_from_ipv4n(&my_apparent_addr, get_uint32(my_addr_ptr));
+ if (tor_addr_from_netinfo_addr(&my_apparent_addr, my_addr) == -1) {
+ connection_or_close_for_error(chan->conn, 0);
+ netinfo_cell_free(netinfo_cell);
+ return;
+ }
+ if (my_addr_type == NETINFO_ADDR_TYPE_IPV4 && my_addr_len == 4) {
if (!get_options()->BridgeRelay && me &&
- get_uint32(my_addr_ptr) == htonl(me->addr)) {
+ tor_addr_eq_ipv4h(&my_apparent_addr, me->addr)) {
TLS_CHAN_TO_BASE(chan)->is_canonical_to_peer = 1;
}
-
- } else if (my_addr_type == RESOLVED_TYPE_IPV6 && my_addr_len == 16) {
- tor_addr_from_ipv6_bytes(&my_apparent_addr, (const char *) my_addr_ptr);
-
+ } else if (my_addr_type == NETINFO_ADDR_TYPE_IPV6 &&
+ my_addr_len == 16) {
if (!get_options()->BridgeRelay && me &&
!tor_addr_is_null(&me->ipv6_addr) &&
tor_addr_eq(&my_apparent_addr, &me->ipv6_addr)) {
@@ -1766,18 +1806,20 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
}
}
- n_other_addrs = (uint8_t) *cp++;
- while (n_other_addrs && cp < end-2) {
+ n_other_addrs = netinfo_cell_get_n_my_addrs(netinfo_cell);
+ for (uint8_t i = 0; i < n_other_addrs; i++) {
/* Consider all the other addresses; if any matches, this connection is
* "canonical." */
+
+ const netinfo_addr_t *netinfo_addr =
+ netinfo_cell_getconst_my_addrs(netinfo_cell, i);
+
tor_addr_t addr;
- const uint8_t *next =
- decode_address_from_payload(&addr, cp, (int)(end-cp));
- if (next == NULL) {
+
+ if (tor_addr_from_netinfo_addr(&addr, netinfo_addr) == -1) {
log_fn(LOG_PROTOCOL_WARN, LD_OR,
- "Bad address in netinfo cell; closing connection.");
- connection_or_close_for_error(chan->conn, 0);
- return;
+ "Bad address in netinfo cell; Skipping.");
+ continue;
}
/* A relay can connect from anywhere and be canonical, so
* long as it tells you from where it came. This may sound a bit
@@ -1790,10 +1832,10 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
connection_or_set_canonical(chan->conn, 1);
break;
}
- cp = next;
- --n_other_addrs;
}
+ netinfo_cell_free(netinfo_cell);
+
if (me && !TLS_CHAN_TO_BASE(chan)->is_canonical_to_peer &&
channel_is_canonical(TLS_CHAN_TO_BASE(chan))) {
const char *descr =