summaryrefslogtreecommitdiff
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.c543
1 files changed, 331 insertions, 212 deletions
diff --git a/src/core/or/channeltls.c b/src/core/or/channeltls.c
index 18025ff73a..dd5e42c47f 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,16 +61,18 @@
#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/extendinfo.h"
#include "core/or/cell_st.h"
#include "core/or/cell_queue_st.h"
-#include "core/or/extend_info_st.h"
#include "core/or/or_connection_st.h"
#include "core/or/or_handshake_certs_st.h"
#include "core/or/or_handshake_state_st.h"
#include "feature/nodelist/routerinfo_st.h"
#include "core/or/var_cell_st.h"
+#include "src/feature/relay/relay_find_addr.h"
#include "lib/tls/tortls.h"
#include "lib/tls/x509.h"
@@ -99,12 +103,11 @@ static void channel_tls_close_method(channel_t *chan);
static const char * channel_tls_describe_transport_method(channel_t *chan);
static void channel_tls_free_method(channel_t *chan);
static double channel_tls_get_overhead_estimate_method(channel_t *chan);
-static int
-channel_tls_get_remote_addr_method(channel_t *chan, tor_addr_t *addr_out);
+static int channel_tls_get_remote_addr_method(const channel_t *chan,
+ tor_addr_t *addr_out);
static int
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);
+static const char *channel_tls_describe_peer_method(const channel_t *chan);
static int channel_tls_has_queued_writes_method(channel_t *chan);
static int channel_tls_is_canonical_method(channel_t *chan);
static int
@@ -160,7 +163,7 @@ channel_tls_common_init(channel_tls_t *tlschan)
chan->free_fn = channel_tls_free_method;
chan->get_overhead_estimate = channel_tls_get_overhead_estimate_method;
chan->get_remote_addr = channel_tls_get_remote_addr_method;
- chan->get_remote_descr = channel_tls_get_remote_descr_method;
+ chan->describe_peer = channel_tls_describe_peer_method;
chan->get_transport_name = channel_tls_get_transport_name_method;
chan->has_queued_writes = channel_tls_has_queued_writes_method;
chan->is_canonical = channel_tls_is_canonical_method;
@@ -200,7 +203,7 @@ channel_tls_connect(const tor_addr_t *addr, uint16_t port,
tlschan,
(chan->global_identifier));
- if (is_local_addr(addr)) {
+ if (is_local_to_resolve_addr(addr)) {
log_debug(LD_CHANNEL,
"Marking new outgoing channel %"PRIu64 " at %p as local",
(chan->global_identifier), chan);
@@ -337,7 +340,7 @@ channel_tls_handle_incoming(or_connection_t *orconn)
tlschan->conn = orconn;
orconn->chan = tlschan;
- if (is_local_addr(&(TO_CONN(orconn)->addr))) {
+ if (is_local_to_resolve_addr(&(TO_CONN(orconn)->addr))) {
log_debug(LD_CHANNEL,
"Marking new incoming channel %"PRIu64 " at %p as local",
(chan->global_identifier), chan);
@@ -357,6 +360,31 @@ channel_tls_handle_incoming(or_connection_t *orconn)
return chan;
}
+/**
+ * Set the `potentially_used_for_bootstrapping` flag on the or_connection_t
+ * corresponding to the provided channel.
+ *
+ * This flag indicates that if the connection fails, it might be interesting
+ * to the bootstrapping subsystem. (The bootstrapping system only cares about
+ * channels that we have tried to use for our own circuits. Other channels
+ * may have been launched in response to EXTEND cells from somebody else, and
+ * if they fail, it won't necessarily indicate a bootstrapping problem.)
+ **/
+void
+channel_mark_as_used_for_origin_circuit(channel_t *chan)
+{
+ if (BUG(!chan))
+ return;
+ if (chan->magic != TLS_CHAN_MAGIC)
+ return;
+ channel_tls_t *tlschan = channel_tls_from_base(chan);
+ if (BUG(!tlschan))
+ return;
+
+ if (tlschan->conn)
+ tlschan->conn->potentially_used_for_bootstrapping = 1;
+}
+
/*********
* Casts *
********/
@@ -386,6 +414,25 @@ channel_tls_from_base(channel_t *chan)
return (channel_tls_t *)(chan);
}
+/**
+ * Cast a const channel_tls_t to a const channel_t.
+ */
+const channel_t *
+channel_tls_to_base_const(const channel_tls_t *tlschan)
+{
+ return channel_tls_to_base((channel_tls_t*) tlschan);
+}
+
+/**
+ * Cast a const channel_t to a const channel_tls_t, with appropriate
+ * type-checking asserts.
+ */
+const channel_tls_t *
+channel_tls_from_base_const(const channel_t *chan)
+{
+ return channel_tls_from_base((channel_t *)chan);
+}
+
/********************************************
* Method implementations for channel_tls_t *
*******************************************/
@@ -507,24 +554,29 @@ channel_tls_get_overhead_estimate_method(channel_t *chan)
* Get the remote address of a channel_tls_t.
*
* This implements the get_remote_addr method for channel_tls_t; copy the
- * remote endpoint of the channel to addr_out and return 1 (always
- * succeeds for this transport).
+ * remote endpoint of the channel to addr_out and return 1. (Always
+ * succeeds if this channel is attached to an OR connection.)
+ *
+ * Always returns the real address of the peer, not the canonical address.
*/
static int
-channel_tls_get_remote_addr_method(channel_t *chan, tor_addr_t *addr_out)
+channel_tls_get_remote_addr_method(const channel_t *chan,
+ tor_addr_t *addr_out)
{
- int rv = 0;
- channel_tls_t *tlschan = BASE_CHAN_TO_TLS(chan);
+ const channel_tls_t *tlschan = CONST_BASE_CHAN_TO_TLS(chan);
tor_assert(tlschan);
tor_assert(addr_out);
- if (tlschan->conn) {
- tor_addr_copy(addr_out, &(tlschan->conn->real_addr));
- rv = 1;
- } else tor_addr_make_unspec(addr_out);
+ if (tlschan->conn == NULL) {
+ tor_addr_make_unspec(addr_out);
+ return 0;
+ }
- return rv;
+ /* They want the real address, so give it to them. */
+ tor_addr_copy(addr_out, &TO_CONN(tlschan->conn)->addr);
+
+ return 1;
}
/**
@@ -552,65 +604,22 @@ channel_tls_get_transport_name_method(channel_t *chan, char **transport_out)
}
/**
- * Get endpoint description of a channel_tls_t.
+ * Get a human-readable endpoint description of a channel_tls_t.
*
- * This implements the get_remote_descr method for channel_tls_t; it returns
- * a text description of the remote endpoint of the channel suitable for use
- * in log messages. The req parameter is 0 for the canonical address or 1 for
- * the actual address seen.
+ * This format is intended for logging, and may change in the future;
+ * nothing should parse or rely on its particular details.
*/
static const char *
-channel_tls_get_remote_descr_method(channel_t *chan, int flags)
+channel_tls_describe_peer_method(const channel_t *chan)
{
-#define MAX_DESCR_LEN 32
-
- static char buf[MAX_DESCR_LEN + 1];
- channel_tls_t *tlschan = BASE_CHAN_TO_TLS(chan);
- connection_t *conn;
- const char *answer = NULL;
- char *addr_str;
-
+ const channel_tls_t *tlschan = CONST_BASE_CHAN_TO_TLS(chan);
tor_assert(tlschan);
if (tlschan->conn) {
- conn = TO_CONN(tlschan->conn);
- switch (flags) {
- case 0:
- /* Canonical address with port*/
- tor_snprintf(buf, MAX_DESCR_LEN + 1,
- "%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_free(addr_str);
- answer = buf;
- break;
- case GRD_FLAG_ADDR_ONLY:
- /* Canonical address, no port */
- strlcpy(buf, conn->address, sizeof(buf));
- answer = buf;
- break;
- case GRD_FLAG_ORIGINAL|GRD_FLAG_ADDR_ONLY:
- /* Actual address, no port */
- addr_str = tor_addr_to_str_dup(&(tlschan->conn->real_addr));
- strlcpy(buf, addr_str, sizeof(buf));
- tor_free(addr_str);
- answer = buf;
- break;
- default:
- /* Something's broken in channel.c */
- tor_assert_nonfatal_unreached_once();
- }
+ return connection_describe_peer(TO_CONN(tlschan->conn));
} else {
- strlcpy(buf, "(No connection)", sizeof(buf));
- answer = buf;
+ return "(No connection)";
}
-
- return answer;
}
/**
@@ -671,6 +680,9 @@ channel_tls_is_canonical_method(channel_t *chan)
*
* This implements the matches_extend_info method for channel_tls_t; the upper
* layer wants to know if this channel matches an extend_info_t.
+ *
+ * NOTE that this function only checks for an address/port match, and should
+ * be used only when no identify is available.
*/
static int
channel_tls_matches_extend_info_method(channel_t *chan,
@@ -690,9 +702,19 @@ channel_tls_matches_extend_info_method(channel_t *chan,
return 0;
}
- return (tor_addr_eq(&(extend_info->addr),
- &(TO_CONN(tlschan->conn)->addr)) &&
- (extend_info->port == TO_CONN(tlschan->conn)->port));
+ const tor_addr_port_t *orport = &tlschan->conn->canonical_orport;
+ // If the canonical address is set, then we'll allow matches based on that.
+ if (! tor_addr_is_unspec(&orport->addr)) {
+ if (extend_info_has_orport(extend_info, &orport->addr, orport->port)) {
+ return 1;
+ }
+ }
+
+ // We also want to match if the true address and port are listed in the
+ // extend info.
+ return extend_info_has_orport(extend_info,
+ &TO_CONN(tlschan->conn)->addr,
+ TO_CONN(tlschan->conn)->port);
}
/**
@@ -720,16 +742,19 @@ channel_tls_matches_target_method(channel_t *chan,
return 0;
}
- /* real_addr is the address this connection came from.
- * base_.addr is updated by connection_or_init_conn_from_address()
+ /* addr is the address this connection came from.
+ * canonical_orport 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);
+ return tor_addr_eq(&TO_CONN(tlschan->conn)->addr, target);
}
/**
@@ -937,7 +962,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 +970,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 +1039,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 +1068,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 +1085,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 +1107,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 +1340,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.
*
@@ -1337,7 +1362,7 @@ channel_tls_update_marks(or_connection_t *conn)
chan = TLS_CHAN_TO_BASE(conn->chan);
- if (is_local_addr(&(TO_CONN(conn)->addr))) {
+ if (is_local_to_resolve_addr(&(TO_CONN(conn)->addr))) {
if (!channel_is_local(chan)) {
log_debug(LD_CHANNEL,
"Marking channel %"PRIu64 " at %p as local",
@@ -1402,7 +1427,7 @@ enter_v3_handshake_with_cell(var_cell_t *cell, channel_tls_t *chan)
"OR_HANDSHAKING_V3, on a connection we originated.");
}
connection_or_block_renegotiation(chan->conn);
- chan->conn->base_.state = OR_CONN_STATE_OR_HANDSHAKING_V3;
+ connection_or_change_state(chan->conn, OR_CONN_STATE_OR_HANDSHAKING_V3);
if (connection_init_or_handshake_state(chan->conn, started_here) < 0) {
connection_or_close_for_error(chan->conn, 0);
return -1;
@@ -1501,7 +1526,7 @@ channel_tls_process_versions_cell(var_cell_t *cell, channel_tls_t *chan)
log_fn(LOG_WARN, LD_OR,
"Negotiated link with non-2 protocol after doing a v2 TLS "
"handshake with %s. Closing connection.",
- fmt_addr(&chan->conn->base_.addr));
+ connection_describe_peer(TO_CONN(chan->conn)));
connection_or_close_for_error(chan->conn, 0);
return;
}
@@ -1513,10 +1538,9 @@ channel_tls_process_versions_cell(var_cell_t *cell, channel_tls_t *chan)
if (chan->conn->link_proto == 2) {
log_info(LD_OR,
- "Negotiated version %d with %s:%d; sending NETINFO.",
+ "Negotiated version %d on %s; sending NETINFO.",
highest_supported_version,
- safe_str_client(chan->conn->base_.address),
- chan->conn->base_.port);
+ connection_describe(TO_CONN(chan->conn)));
if (connection_or_send_netinfo(chan->conn) < 0) {
connection_or_close_for_error(chan->conn, 0);
@@ -1536,10 +1560,9 @@ channel_tls_process_versions_cell(var_cell_t *cell, channel_tls_t *chan)
tor_assert(chan->conn->link_proto >= 3);
log_info(LD_OR,
- "Negotiated version %d with %s:%d; %s%s%s%s%s",
+ "Negotiated version %d with on %s; %s%s%s%s%s",
highest_supported_version,
- safe_str_client(chan->conn->base_.address),
- chan->conn->base_.port,
+ connection_describe(TO_CONN(chan->conn)),
send_any ? "Sending cells:" : "Waiting for CERTS cell",
send_versions ? " VERSIONS" : "",
send_certs ? " CERTS" : "",
@@ -1632,6 +1655,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
@@ -1643,6 +1695,85 @@ time_abs(time_t val)
return (val < 0) ? -val : val;
}
+/** Return true iff the channel can process a NETINFO cell. For this to return
+ * true, these channel conditions apply:
+ *
+ * 1. Link protocol is version 2 or higher (tor-spec.txt, NETINFO cells
+ * section).
+ *
+ * 2. Underlying OR connection of the channel is either in v2 or v3
+ * handshaking state.
+ */
+static bool
+can_process_netinfo_cell(const channel_tls_t *chan)
+{
+ /* NETINFO cells can only be negotiated on link protocol 2 or higher. */
+ if (chan->conn->link_proto < 2) {
+ log_fn(LOG_PROTOCOL_WARN, LD_OR,
+ "Received a NETINFO cell on %s connection; dropping.",
+ chan->conn->link_proto == 0 ? "non-versioned" : "a v1");
+ return false;
+ }
+
+ /* Can't process a NETINFO cell if the connection is not handshaking. */
+ if (chan->conn->base_.state != OR_CONN_STATE_OR_HANDSHAKING_V2 &&
+ chan->conn->base_.state != OR_CONN_STATE_OR_HANDSHAKING_V3) {
+ log_fn(LOG_PROTOCOL_WARN, LD_OR,
+ "Received a NETINFO cell on non-handshaking connection; dropping.");
+ return false;
+ }
+
+ /* Make sure we do have handshake state. */
+ tor_assert(chan->conn->handshake_state);
+ tor_assert(chan->conn->handshake_state->received_versions);
+
+ return true;
+}
+
+/** Mark the given channel endpoint as a client (which means either a tor
+ * client or a tor bridge).
+ *
+ * This MUST be done on an _unauthenticated_ channel. It is a mistake to mark
+ * an authenticated channel as a client.
+ *
+ * The following is done on the channel:
+ *
+ * 1. Marked as a client.
+ * 2. Type of circuit ID type is set.
+ * 3. The underlying OR connection is initialized with the address of the
+ * endpoint.
+ */
+static void
+mark_channel_tls_endpoint_as_client(channel_tls_t *chan)
+{
+ /* Ending up here for an authenticated link is a mistake. */
+ if (BUG(chan->conn->handshake_state->authenticated)) {
+ return;
+ }
+
+ tor_assert(tor_digest_is_zero(
+ (const char*)(chan->conn->handshake_state->
+ authenticated_rsa_peer_id)));
+ 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
+ * relay, and we must not use it for EXTEND requests (nor could we, as
+ * there are no authenticated peer IDs) */
+ channel_mark_client(TLS_CHAN_TO_BASE(chan));
+ channel_set_circid_type(TLS_CHAN_TO_BASE(chan), NULL,
+ chan->conn->link_proto < MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS);
+
+ connection_or_init_conn_from_address(chan->conn,
+ &(chan->conn->base_.addr),
+ chan->conn->base_.port,
+ /* zero, checked above */
+ (const char*)(chan->conn->handshake_state->
+ authenticated_rsa_peer_id),
+ NULL, /* Ed25519 ID: Also checked as zero */
+ 0);
+}
+
/**
* Process a 'netinfo' cell
*
@@ -1655,8 +1786,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();
@@ -1670,20 +1799,12 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
tor_assert(chan);
tor_assert(chan->conn);
- if (chan->conn->link_proto < 2) {
- log_fn(LOG_PROTOCOL_WARN, LD_OR,
- "Received a NETINFO cell on %s connection; dropping.",
- chan->conn->link_proto == 0 ? "non-versioned" : "a v1");
+ /* Make sure we can process a NETINFO cell. Link protocol and state
+ * validation is done to make sure of it. */
+ if (!can_process_netinfo_cell(chan)) {
return;
}
- if (chan->conn->base_.state != OR_CONN_STATE_OR_HANDSHAKING_V2 &&
- chan->conn->base_.state != OR_CONN_STATE_OR_HANDSHAKING_V3) {
- log_fn(LOG_PROTOCOL_WARN, LD_OR,
- "Received a NETINFO cell on non-handshaking connection; dropping.");
- return;
- }
- tor_assert(chan->conn->handshake_state &&
- chan->conn->handshake_state->received_versions);
+
started_here = connection_or_nonopen_was_started_here(chan->conn);
identity_digest = chan->conn->identity_digest;
@@ -1698,67 +1819,60 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
return;
}
} else {
- /* we're the server. If the client never authenticated, we have
- some housekeeping to do.*/
+ /* We're the server. If the client never authenticated, we have some
+ * housekeeping to do.
+ *
+ * It's a tor client or bridge relay, and we must not use it for EXTEND
+ * requests (nor could we, as there are no authenticated peer IDs) */
if (!(chan->conn->handshake_state->authenticated)) {
- tor_assert(tor_digest_is_zero(
- (const char*)(chan->conn->handshake_state->
- authenticated_rsa_peer_id)));
- tor_assert(tor_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
- * relay, and we must not use it for EXTEND requests (nor could we, as
- * there are no authenticated peer IDs) */
- channel_mark_client(TLS_CHAN_TO_BASE(chan));
- channel_set_circid_type(TLS_CHAN_TO_BASE(chan), NULL,
- chan->conn->link_proto < MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS);
-
- connection_or_init_conn_from_address(chan->conn,
- &(chan->conn->base_.addr),
- chan->conn->base_.port,
- /* zero, checked above */
- (const char*)(chan->conn->handshake_state->
- authenticated_rsa_peer_id),
- NULL, /* Ed25519 ID: Also checked as zero */
- 0);
+ mark_channel_tls_endpoint_as_client(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(&my_apparent_addr, &me->ipv4_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 +1880,27 @@ 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) {
+ if (me) {
+ /* We have a descriptor, so we are a relay: record the address that the
+ * other side said we had. */
+ tor_addr_copy(&TLS_CHAN_TO_BASE(chan)->addr_according_to_peer,
+ &my_apparent_addr);
+ }
+
+ 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
@@ -1786,18 +1909,18 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
* might be doing something funny, but nobody else is doing a MITM
* on the relay's TCP.
*/
- if (tor_addr_eq(&addr, &(chan->conn->real_addr))) {
+ if (tor_addr_eq(&addr, &TO_CONN(chan->conn)->addr)) {
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 =
- TLS_CHAN_TO_BASE(chan)->get_remote_descr(TLS_CHAN_TO_BASE(chan), 0);
+ const char *descr = channel_describe_peer(
+ TLS_CHAN_TO_BASE(chan));
log_info(LD_OR,
"We made a connection to a relay at %s (fp=%s) but we think "
"they will not consider this connection canonical. They "
@@ -1806,7 +1929,7 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
safe_str(hex_str(identity_digest, DIGEST_LEN)),
safe_str(tor_addr_is_null(&my_apparent_addr) ?
"<none>" : fmt_and_decorate_addr(&my_apparent_addr)),
- safe_str(fmt_addr32(me->addr)));
+ safe_str(fmt_addr(&me->ipv4_addr)));
}
/* Act on apparent skew. */
@@ -1820,8 +1943,12 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
"NETINFO cell", "OR");
}
- /* XXX maybe act on my_apparent_addr, if the source is sufficiently
- * trustworthy. */
+ /* Consider our apparent address as a possible suggestion for our address if
+ * we were unable to resolve it previously. The endpoint address is passed
+ * in order to make sure to never consider an address that is the same as
+ * our endpoint. */
+ relay_address_new_suggestion(&my_apparent_addr, &TO_CONN(chan->conn)->addr,
+ identity_digest);
if (! chan->conn->handshake_state->sent_netinfo) {
/* If we were prepared to authenticate, but we never got an AUTH_CHALLENGE
@@ -1835,18 +1962,16 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
if (connection_or_set_state_open(chan->conn) < 0) {
log_fn(LOG_PROTOCOL_WARN, LD_OR,
- "Got good NETINFO cell from %s:%d; but "
+ "Got good NETINFO cell on %s; but "
"was unable to make the OR connection become open.",
- safe_str_client(chan->conn->base_.address),
- chan->conn->base_.port);
+ connection_describe(TO_CONN(chan->conn)));
connection_or_close_for_error(chan->conn, 0);
} else {
log_info(LD_OR,
- "Got good NETINFO cell from %s:%d; OR connection is now "
+ "Got good NETINFO cell on %s; OR connection is now "
"open, using protocol version %d. Its ID digest is %s. "
"Our address is apparently %s.",
- safe_str_client(chan->conn->base_.address),
- chan->conn->base_.port,
+ connection_describe(TO_CONN(chan->conn)),
(int)(chan->conn->link_proto),
hex_str(identity_digest, DIGEST_LEN),
tor_addr_is_null(&my_apparent_addr) ?
@@ -1931,9 +2056,9 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
#define ERR(s) \
do { \
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \
- "Received a bad CERTS cell from %s:%d: %s", \
- safe_str(chan->conn->base_.address), \
- chan->conn->base_.port, (s)); \
+ "Received a bad CERTS cell on %s: %s", \
+ connection_describe(TO_CONN(chan->conn)), \
+ (s)); \
connection_or_close_for_error(chan->conn, 0); \
goto err; \
} while (0)
@@ -1981,9 +2106,8 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
tor_x509_cert_t *x509_cert = tor_x509_cert_decode(cert_body, cert_len);
if (!x509_cert) {
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
- "Received undecodable certificate in CERTS cell from %s:%d",
- safe_str(chan->conn->base_.address),
- chan->conn->base_.port);
+ "Received undecodable certificate in CERTS cell on %s",
+ connection_describe(TO_CONN(chan->conn)));
} else {
if (x509_certs[cert_type]) {
tor_x509_cert_free(x509_cert);
@@ -1999,9 +2123,8 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
if (!ed_cert) {
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Received undecodable Ed certificate "
- "in CERTS cell from %s:%d",
- safe_str(chan->conn->base_.address),
- chan->conn->base_.port);
+ "in CERTS cell on %s",
+ connection_describe(TO_CONN(chan->conn)));
} else {
if (ed_certs[cert_type]) {
tor_cert_free(ed_cert);
@@ -2111,9 +2234,9 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
ERR("Problem setting or checking peer id");
log_info(LD_HANDSHAKE,
- "Got some good certificates from %s:%d: Authenticated it with "
+ "Got some good certificates on %s: Authenticated it with "
"RSA%s",
- safe_str(chan->conn->base_.address), chan->conn->base_.port,
+ connection_describe(TO_CONN(chan->conn)),
checked_ed_id ? " and Ed25519" : "");
if (!public_server_mode(get_options())) {
@@ -2125,11 +2248,10 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
} else {
/* We can't call it authenticated till we see an AUTHENTICATE cell. */
log_info(LD_OR,
- "Got some good RSA%s certificates from %s:%d. "
+ "Got some good RSA%s certificates on %s. "
"Waiting for AUTHENTICATE.",
checked_ed_id ? " and Ed25519" : "",
- safe_str(chan->conn->base_.address),
- chan->conn->base_.port);
+ connection_describe(TO_CONN(chan->conn)));
/* XXXX check more stuff? */
}
@@ -2178,9 +2300,9 @@ channel_tls_process_auth_challenge_cell(var_cell_t *cell, channel_tls_t *chan)
#define ERR(s) \
do { \
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \
- "Received a bad AUTH_CHALLENGE cell from %s:%d: %s", \
- safe_str(chan->conn->base_.address), \
- chan->conn->base_.port, (s)); \
+ "Received a bad AUTH_CHALLENGE cell on %s: %s", \
+ connection_describe(TO_CONN(chan->conn)), \
+ (s)); \
connection_or_close_for_error(chan->conn, 0); \
goto done; \
} while (0)
@@ -2225,10 +2347,9 @@ channel_tls_process_auth_challenge_cell(var_cell_t *cell, channel_tls_t *chan)
if (use_type >= 0) {
log_info(LD_OR,
- "Got an AUTH_CHALLENGE cell from %s:%d: Sending "
+ "Got an AUTH_CHALLENGE cell on %s: Sending "
"authentication type %d",
- safe_str(chan->conn->base_.address),
- chan->conn->base_.port,
+ connection_describe(TO_CONN(chan->conn)),
use_type);
if (connection_or_send_authenticate_cell(chan->conn, use_type) < 0) {
@@ -2239,10 +2360,9 @@ channel_tls_process_auth_challenge_cell(var_cell_t *cell, channel_tls_t *chan)
}
} else {
log_info(LD_OR,
- "Got an AUTH_CHALLENGE cell from %s:%d, but we don't "
+ "Got an AUTH_CHALLENGE cell on %s, but we don't "
"know any of its authentication types. Not authenticating.",
- safe_str(chan->conn->base_.address),
- chan->conn->base_.port);
+ connection_describe(TO_CONN(chan->conn)));
}
if (connection_or_send_netinfo(chan->conn) < 0) {
@@ -2282,9 +2402,9 @@ channel_tls_process_authenticate_cell(var_cell_t *cell, channel_tls_t *chan)
#define ERR(s) \
do { \
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \
- "Received a bad AUTHENTICATE cell from %s:%d: %s", \
- safe_str(chan->conn->base_.address), \
- chan->conn->base_.port, (s)); \
+ "Received a bad AUTHENTICATE cell on %s: %s", \
+ connection_describe(TO_CONN(chan->conn)), \
+ (s)); \
connection_or_close_for_error(chan->conn, 0); \
var_cell_free(expected_cell); \
return; \
@@ -2445,9 +2565,9 @@ channel_tls_process_authenticate_cell(var_cell_t *cell, channel_tls_t *chan)
crypto_pk_free(identity_rcvd);
log_debug(LD_HANDSHAKE,
- "Calling connection_or_init_conn_from_address for %s "
+ "Calling connection_or_init_conn_from_address on %s "
" from %s, with%s ed25519 id.",
- safe_str(chan->conn->base_.address),
+ connection_describe(TO_CONN(chan->conn)),
__func__,
ed_identity_received ? "" : "out");
@@ -2460,10 +2580,9 @@ channel_tls_process_authenticate_cell(var_cell_t *cell, channel_tls_t *chan)
0);
log_debug(LD_HANDSHAKE,
- "Got an AUTHENTICATE cell from %s:%d, type %d: Looks good.",
- safe_str(chan->conn->base_.address),
- chan->conn->base_.port,
- authtype);
+ "Got an AUTHENTICATE cell on %s, type %d: Looks good.",
+ connection_describe(TO_CONN(chan->conn)),
+ authtype);
}
var_cell_free(expected_cell);