Merge branch 'ticket40042_squashed'

This commit is contained in:
Nick Mathewson 2020-07-17 11:44:27 -04:00
commit 2225c3c369
14 changed files with 128 additions and 119 deletions

7
changes/ticket33898 Normal file
View File

@ -0,0 +1,7 @@
o Minor features (relay address tracking):
- We store relay addresses for OR connections in a more logical way.
Previously we would sometimes overwrite the actual address of a
connection with a "canonical address", and then store the "real
address" elsewhere to remember it. We now track the "canonical address"
elsewhere for the cases where we need it, and leave the connection's
address alone. Closes ticket 33898.

View File

@ -434,14 +434,6 @@ connection_describe_peer_internal(const connection_t *conn,
} else if (conn->type == CONN_TYPE_OR) { } else if (conn->type == CONN_TYPE_OR) {
/* For OR connections, we have a lot to do. */ /* For OR connections, we have a lot to do. */
const or_connection_t *or_conn = CONST_TO_OR_CONN(conn); const or_connection_t *or_conn = CONST_TO_OR_CONN(conn);
/* we report 'real_addr' as the address we're talking with, if it's set.
*
* TODO: Eventually we should have 'addr' always mean the address on the
* internet, and have a separate 'canonical_addr' field.
*/
if (!tor_addr_is_null(&or_conn->real_addr)) {
addr = &or_conn->real_addr;
}
/* We report the IDs we're talking to... */ /* We report the IDs we're talking to... */
if (fast_digest_is_zero(or_conn->identity_digest)) { if (fast_digest_is_zero(or_conn->identity_digest)) {
// This could be a client, so scrub it. No identity to report. // This could be a client, so scrub it. No identity to report.
@ -453,13 +445,17 @@ connection_describe_peer_internal(const connection_t *conn,
tor_snprintf(extra_buf, sizeof(extra_buf), tor_snprintf(extra_buf, sizeof(extra_buf),
" ID=%s", id_buf); " ID=%s", id_buf);
} }
if (! tor_addr_eq(addr, &conn->addr) && !scrub) { if (! scrub && (! tor_addr_eq(addr, &or_conn->canonical_orport.addr) ||
conn->port != or_conn->canonical_orport.port)) {
/* We report canonical address, if it's different */ /* We report canonical address, if it's different */
char canonical_addr_buf[TOR_ADDR_BUF_LEN]; char canonical_addr_buf[TOR_ADDR_BUF_LEN];
if (tor_addr_to_str(canonical_addr_buf, &conn->addr, if (tor_addr_to_str(canonical_addr_buf, &or_conn->canonical_orport.addr,
sizeof(canonical_addr_buf), 1)) { sizeof(canonical_addr_buf), 1)) {
strlcat(extra_buf, " canonical_addr=", sizeof(extra_buf)); tor_snprintf(extra_buf+strlen(extra_buf),
strlcat(extra_buf, canonical_addr_buf, sizeof(extra_buf)); sizeof(extra_buf)-strlen(extra_buf),
" canonical_addr=%s:%"PRIu16,
canonical_addr_buf,
or_conn->canonical_orport.port);
} }
} }
} else if (conn->type == CONN_TYPE_EXIT) { } else if (conn->type == CONN_TYPE_EXIT) {
@ -570,6 +566,7 @@ or_connection_new(int type, int socket_family)
tor_assert(type == CONN_TYPE_OR || type == CONN_TYPE_EXT_OR); tor_assert(type == CONN_TYPE_OR || type == CONN_TYPE_EXT_OR);
connection_init(now, TO_CONN(or_conn), type, socket_family); connection_init(now, TO_CONN(or_conn), type, socket_family);
tor_addr_make_unspec(&or_conn->canonical_orport.addr);
connection_or_set_canonical(or_conn, 0); connection_or_set_canonical(or_conn, 0);
if (type == CONN_TYPE_EXT_OR) if (type == CONN_TYPE_EXT_OR)
@ -2252,16 +2249,7 @@ connection_connect_log_client_use_ip_version(const connection_t *conn)
? fascist_firewall_prefer_ipv6_orport(options) ? fascist_firewall_prefer_ipv6_orport(options)
: fascist_firewall_prefer_ipv6_dirport(options)); : fascist_firewall_prefer_ipv6_dirport(options));
tor_addr_t real_addr; tor_addr_t real_addr;
tor_addr_make_null(&real_addr, AF_UNSPEC);
/* OR conns keep the original address in real_addr, as addr gets overwritten
* with the descriptor address */
if (conn->type == CONN_TYPE_OR) {
const or_connection_t *or_conn = CONST_TO_OR_CONN(conn);
tor_addr_copy(&real_addr, &or_conn->real_addr);
} else if (conn->type == CONN_TYPE_DIR) {
tor_addr_copy(&real_addr, &conn->addr); tor_addr_copy(&real_addr, &conn->addr);
}
/* Check if we broke a mandatory address family restriction */ /* Check if we broke a mandatory address family restriction */
if ((must_ipv4 && tor_addr_family(&real_addr) == AF_INET6) if ((must_ipv4 && tor_addr_family(&real_addr) == AF_INET6)

View File

@ -3255,6 +3255,9 @@ channel_when_last_xmit(channel_t *chan)
* *
* This function calls the lower layer and asks if this channel matches a * This function calls the lower layer and asks if this channel matches a
* given extend_info_t. * given extend_info_t.
*
* NOTE that this function only checks for an address/port match, and should
* be used only when no identity is available.
*/ */
int int
channel_matches_extend_info(channel_t *chan, extend_info_t *extend_info) channel_matches_extend_info(channel_t *chan, extend_info_t *extend_info)

View File

@ -548,14 +548,8 @@ channel_tls_get_remote_addr_method(const channel_t *chan,
return 0; return 0;
} }
if (! tor_addr_is_null(&tlschan->conn->real_addr)) { /* They want the real address, so give it to them. */
/* They want the real address, and real_addr is set. */
tor_addr_copy(addr_out, &(tlschan->conn->real_addr));
} else {
/* We'll have to give them the nominal address, which hopefully has
* not been overwritten yet. */
tor_addr_copy(addr_out, &TO_CONN(tlschan->conn)->addr); tor_addr_copy(addr_out, &TO_CONN(tlschan->conn)->addr);
}
return 1; return 1;
} }
@ -673,6 +667,9 @@ channel_tls_is_canonical_method(channel_t *chan, int req)
* *
* This implements the matches_extend_info method for channel_tls_t; the upper * 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. * 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 static int
channel_tls_matches_extend_info_method(channel_t *chan, channel_tls_matches_extend_info_method(channel_t *chan,
@ -692,6 +689,16 @@ channel_tls_matches_extend_info_method(channel_t *chan,
return 0; return 0;
} }
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, return extend_info_has_orport(extend_info,
&TO_CONN(tlschan->conn)->addr, &TO_CONN(tlschan->conn)->addr,
TO_CONN(tlschan->conn)->port); TO_CONN(tlschan->conn)->port);
@ -722,8 +729,8 @@ channel_tls_matches_target_method(channel_t *chan,
return 0; return 0;
} }
/* real_addr is the address this connection came from. /* addr is the address this connection came from.
* base_.addr is updated by connection_or_init_conn_from_address() * canonical_orport is updated by connection_or_init_conn_from_address()
* to be the address in the descriptor. It may be tempting to * 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 * allow either address to be allowed, but if we did so, it would
* enable someone who steals a relay's keys to covertly impersonate/MITM it * enable someone who steals a relay's keys to covertly impersonate/MITM it
@ -734,7 +741,7 @@ channel_tls_matches_target_method(channel_t *chan,
* An adversary who has stolen a relay's keys could also post a fake relay * An adversary who has stolen a relay's keys could also post a fake relay
* descriptor, but that attack is easier to detect. * 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);
} }
/** /**
@ -1883,7 +1890,7 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
* might be doing something funny, but nobody else is doing a MITM * might be doing something funny, but nobody else is doing a MITM
* on the relay's TCP. * 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); connection_or_set_canonical(chan->conn, 1);
break; break;
} }
@ -1921,7 +1928,7 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
* we were unable to resolve it previously. The endpoint address is passed * 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 * in order to make sure to never consider an address that is the same as
* our endpoint. */ * our endpoint. */
relay_address_new_suggestion(&my_apparent_addr, &chan->conn->real_addr, relay_address_new_suggestion(&my_apparent_addr, &TO_CONN(chan->conn)->addr,
identity_digest); identity_digest);
if (! chan->conn->handshake_state->sent_netinfo) { if (! chan->conn->handshake_state->sent_netinfo) {

View File

@ -893,7 +893,9 @@ connection_or_init_conn_from_address(or_connection_t *conn,
conn->base_.port = port; conn->base_.port = port;
tor_addr_copy(&conn->base_.addr, addr); tor_addr_copy(&conn->base_.addr, addr);
tor_addr_copy(&conn->real_addr, addr); if (! conn->base_.address) {
conn->base_.address = tor_strdup(fmt_addr(addr));
}
connection_or_check_canonicity(conn, started_here); connection_or_check_canonicity(conn, started_here);
} }
@ -905,9 +907,10 @@ connection_or_init_conn_from_address(or_connection_t *conn,
static void static void
connection_or_check_canonicity(or_connection_t *conn, int started_here) connection_or_check_canonicity(or_connection_t *conn, int started_here)
{ {
(void) started_here;
const char *id_digest = conn->identity_digest; const char *id_digest = conn->identity_digest;
const ed25519_public_key_t *ed_id = NULL; const ed25519_public_key_t *ed_id = NULL;
const tor_addr_t *addr = &conn->real_addr;
if (conn->chan) if (conn->chan)
ed_id = & TLS_CHAN_TO_BASE(conn->chan)->ed25519_identity; ed_id = & TLS_CHAN_TO_BASE(conn->chan)->ed25519_identity;
@ -936,34 +939,17 @@ connection_or_check_canonicity(or_connection_t *conn, int started_here)
} else { } else {
node_ap = &node_ipv6_ap; node_ap = &node_ipv6_ap;
} }
if (!started_here) { /* Remember the canonical addr/port so our log messages will make
/* Override the addr/port, so our log messages will make sense. sense. */
* This is dangerous, since if we ever try looking up a conn by tor_addr_port_copy(&conn->canonical_orport, node_ap);
* its actual addr/port, we won't remember. Careful! */
/* XXXX arma: this is stupid, and it's the reason we need real_addr
* to track is_canonical properly. What requires it? */
/* XXXX <arma> i believe the reason we did this, originally, is because
* we wanted to log what OR a connection was to, and if we logged the
* right IP address and port 56244, that wouldn't be as helpful. now we
* log the "right" port too, so we know if it's moria1 or moria2.
*/
/* See #33898 for a ticket that resolves this technical debt. */
tor_addr_copy(&conn->base_.addr, &node_ap->addr);
conn->base_.port = node_ap->port;
}
tor_free(conn->nickname); tor_free(conn->nickname);
conn->nickname = tor_strdup(node_get_nickname(r)); conn->nickname = tor_strdup(node_get_nickname(r));
tor_free(conn->base_.address);
conn->base_.address = tor_addr_to_str_dup(&node_ap->addr);
} else { } else {
tor_free(conn->nickname); tor_free(conn->nickname);
conn->nickname = tor_malloc(HEX_DIGEST_LEN+2); conn->nickname = tor_malloc(HEX_DIGEST_LEN+2);
conn->nickname[0] = '$'; conn->nickname[0] = '$';
base16_encode(conn->nickname+1, HEX_DIGEST_LEN+1, base16_encode(conn->nickname+1, HEX_DIGEST_LEN+1,
conn->identity_digest, DIGEST_LEN); conn->identity_digest, DIGEST_LEN);
tor_free(conn->base_.address);
conn->base_.address = tor_addr_to_str_dup(addr);
} }
/* /*
@ -1144,8 +1130,8 @@ connection_or_group_set_badness_(smartlist_t *group, int force)
(int)(now - or_conn->base_.timestamp_created), (int)(now - or_conn->base_.timestamp_created),
best->base_.s, (int)(now - best->base_.timestamp_created)); best->base_.s, (int)(now - best->base_.timestamp_created));
connection_or_mark_bad_for_new_circs(or_conn); connection_or_mark_bad_for_new_circs(or_conn);
} else if (!tor_addr_compare(&or_conn->real_addr, } else if (tor_addr_eq(&TO_CONN(or_conn)->addr,
&best->real_addr, CMP_EXACT)) { &TO_CONN(best)->addr)) {
log_info(LD_OR, log_info(LD_OR,
"Marking %s unsuitable for new circuits: " "Marking %s unsuitable for new circuits: "
"(fd "TOR_SOCKET_T_FORMAT", %d secs old). We have a better " "(fd "TOR_SOCKET_T_FORMAT", %d secs old). We have a better "
@ -1275,7 +1261,7 @@ static or_connect_failure_entry_t *
or_connect_failure_new(const or_connection_t *or_conn) or_connect_failure_new(const or_connection_t *or_conn)
{ {
or_connect_failure_entry_t *ocf = tor_malloc_zero(sizeof(*ocf)); or_connect_failure_entry_t *ocf = tor_malloc_zero(sizeof(*ocf));
or_connect_failure_init(or_conn->identity_digest, &or_conn->real_addr, or_connect_failure_init(or_conn->identity_digest, &TO_CONN(or_conn)->addr,
TO_CONN(or_conn)->port, ocf); TO_CONN(or_conn)->port, ocf);
return ocf; return ocf;
} }
@ -1653,8 +1639,8 @@ connection_tls_start_handshake,(or_connection_t *conn, int receiving))
log_warn(LD_BUG,"tor_tls_new failed. Closing."); log_warn(LD_BUG,"tor_tls_new failed. Closing.");
return -1; return -1;
} }
tor_tls_set_logged_address(conn->tls, // XXX client and relay? tor_tls_set_logged_address(conn->tls,
escaped_safe_str(conn->base_.address)); connection_describe_peer(TO_CONN(conn)));
connection_start_reading(TO_CONN(conn)); connection_start_reading(TO_CONN(conn));
log_debug(LD_HANDSHAKE,"starting TLS handshake on fd "TOR_SOCKET_T_FORMAT, log_debug(LD_HANDSHAKE,"starting TLS handshake on fd "TOR_SOCKET_T_FORMAT,
@ -1801,18 +1787,15 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn,
crypto_pk_t *identity_rcvd=NULL; crypto_pk_t *identity_rcvd=NULL;
const or_options_t *options = get_options(); const or_options_t *options = get_options();
int severity = server_mode(options) ? LOG_PROTOCOL_WARN : LOG_WARN; int severity = server_mode(options) ? LOG_PROTOCOL_WARN : LOG_WARN;
const char *safe_address =
started_here ? conn->base_.address :
safe_str_client(conn->base_.address);
const char *conn_type = started_here ? "outgoing" : "incoming"; const char *conn_type = started_here ? "outgoing" : "incoming";
int has_cert = 0; int has_cert = 0;
check_no_tls_errors(); check_no_tls_errors();
has_cert = tor_tls_peer_has_cert(conn->tls); has_cert = tor_tls_peer_has_cert(conn->tls);
if (started_here && !has_cert) { if (started_here && !has_cert) {
log_info(LD_HANDSHAKE,"Tried connecting to router at %s:%d, but it didn't " log_info(LD_HANDSHAKE,"Tried connecting to router at %s, but it didn't "
"send a cert! Closing.", "send a cert! Closing.",
safe_address, conn->base_.port); connection_describe_peer(TO_CONN(conn)));
return -1; return -1;
} else if (!has_cert) { } else if (!has_cert) {
log_debug(LD_HANDSHAKE,"Got incoming connection with no certificate. " log_debug(LD_HANDSHAKE,"Got incoming connection with no certificate. "
@ -1824,9 +1807,9 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn,
int v = tor_tls_verify(started_here?severity:LOG_INFO, int v = tor_tls_verify(started_here?severity:LOG_INFO,
conn->tls, &identity_rcvd); conn->tls, &identity_rcvd);
if (started_here && v<0) { if (started_here && v<0) {
log_fn(severity,LD_HANDSHAKE,"Tried connecting to router at %s:%d: It" log_fn(severity,LD_HANDSHAKE,"Tried connecting to router at %s: It"
" has a cert but it's invalid. Closing.", " has a cert but it's invalid. Closing.",
safe_address, conn->base_.port); connection_describe_peer(TO_CONN(conn)));
return -1; return -1;
} else if (v<0) { } else if (v<0) {
log_info(LD_HANDSHAKE,"Incoming connection gave us an invalid cert " log_info(LD_HANDSHAKE,"Incoming connection gave us an invalid cert "
@ -1834,7 +1817,8 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn,
} else { } else {
log_debug(LD_HANDSHAKE, log_debug(LD_HANDSHAKE,
"The certificate seems to be valid on %s connection " "The certificate seems to be valid on %s connection "
"with %s:%d", conn_type, safe_address, conn->base_.port); "with %s", conn_type,
connection_describe_peer(TO_CONN(conn)));
} }
check_no_tls_errors(); check_no_tls_errors();
} }
@ -2027,9 +2011,14 @@ connection_or_client_learned_peer_id(or_connection_t *conn,
/* If we learned an identity for this connection, then we might have /* If we learned an identity for this connection, then we might have
* just discovered it to be canonical. */ * just discovered it to be canonical. */
connection_or_check_canonicity(conn, conn->handshake_state->started_here); connection_or_check_canonicity(conn, conn->handshake_state->started_here);
if (conn->tls)
tor_tls_set_logged_address(conn->tls,
connection_describe_peer(TO_CONN(conn)));
} }
if (authdir_mode_tests_reachability(options)) { if (authdir_mode_tests_reachability(options)) {
// We don't want to use canonical_orport here -- we want the address
// that we really used.
dirserv_orconn_tls_done(&conn->base_.addr, conn->base_.port, dirserv_orconn_tls_done(&conn->base_.addr, conn->base_.port,
(const char*)rsa_peer_id, ed_peer_id); (const char*)rsa_peer_id, ed_peer_id);
} }
@ -2507,11 +2496,9 @@ connection_or_send_netinfo,(or_connection_t *conn))
netinfo_cell_set_timestamp(netinfo_cell, (uint32_t)now); netinfo_cell_set_timestamp(netinfo_cell, (uint32_t)now);
/* Their address. */ /* Their address. */
const tor_addr_t *remote_tor_addr = const tor_addr_t *remote_tor_addr = &TO_CONN(conn)->addr;
!tor_addr_is_null(&conn->real_addr) ? &conn->real_addr : &conn->base_.addr; /* We can safely use TO_CONN(conn)->addr here, since we no longer replace
/* We use &conn->real_addr below, unless it hasn't yet been set. If it * it with a canonical address. */
* hasn't yet been set, we know that base_.addr hasn't been tampered with
* yet either. */
netinfo_addr_t *their_addr = netinfo_addr_from_tor_addr(remote_tor_addr); netinfo_addr_t *their_addr = netinfo_addr_from_tor_addr(remote_tor_addr);
netinfo_cell_set_other_addr(netinfo_cell, their_addr); netinfo_cell_set_other_addr(netinfo_cell, their_addr);

View File

@ -137,15 +137,11 @@ struct connection_t {
* any more! * any more!
* *
* The misuses of this field include: * The misuses of this field include:
* * Setting it to the canonical address of a relay on an OR connection.
* * Setting it on linked connections, possibly. * * Setting it on linked connections, possibly.
* * Updating it based on the Forwarded-For header-- Forwarded-For is * * Updating it based on the Forwarded-For header-- Forwarded-For is
* set by a proxy, but not a local trusted troxy. * set by a proxy, but not a local trusted proxy.
**/ **/
tor_addr_t addr; /**< IP that socket "s" is directly connected to; tor_addr_t addr;
* may be the IP address for a proxy or pluggable transport,
* see "address" for the address of the final destination.
*/
uint16_t port; /**< If non-zero, port that socket "s" is directly connected uint16_t port; /**< If non-zero, port that socket "s" is directly connected
* to; may be the port for a proxy or pluggable transport, * to; may be the port for a proxy or pluggable transport,
* see "address" for the port at the final destination. */ * see "address" for the port at the final destination. */
@ -165,7 +161,6 @@ struct connection_t {
* *
* * An address we're trying to resolve (as an exit). * * An address we're trying to resolve (as an exit).
* * A unix address we're trying to bind to (as a listener). * * A unix address we're trying to bind to (as a listener).
* * A canonical address for an OR connection.
**/ **/
char *address; char *address;
/** Another connection that's connected to this one in lieu of a socket. */ /** Another connection that's connected to this one in lieu of a socket. */

View File

@ -584,7 +584,7 @@ dos_geoip_entry_about_to_free(const clientmap_entry_t *geoip_ent)
SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) { SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) {
if (conn->type == CONN_TYPE_OR) { if (conn->type == CONN_TYPE_OR) {
or_connection_t *or_conn = TO_OR_CONN(conn); or_connection_t *or_conn = TO_OR_CONN(conn);
if (!tor_addr_compare(&geoip_ent->addr, &or_conn->real_addr, if (!tor_addr_compare(&geoip_ent->addr, &TO_CONN(or_conn)->addr,
CMP_EXACT)) { CMP_EXACT)) {
or_conn->tracked_for_dos_mitigation = 0; or_conn->tracked_for_dos_mitigation = 0;
} }
@ -696,12 +696,12 @@ dos_new_client_conn(or_connection_t *or_conn, const char *transport_name)
* reason to do so is because network reentry is possible where a client * reason to do so is because network reentry is possible where a client
* connection comes from an Exit node. Even when we'll fix reentry, this is * connection comes from an Exit node. Even when we'll fix reentry, this is
* a robust defense to keep in place. */ * a robust defense to keep in place. */
if (nodelist_probably_contains_address(&or_conn->real_addr)) { if (nodelist_probably_contains_address(&TO_CONN(or_conn)->addr)) {
goto end; goto end;
} }
/* We are only interested in client connection from the geoip cache. */ /* We are only interested in client connection from the geoip cache. */
entry = geoip_lookup_client(&or_conn->real_addr, transport_name, entry = geoip_lookup_client(&TO_CONN(or_conn)->addr, transport_name,
GEOIP_CLIENT_CONNECT); GEOIP_CLIENT_CONNECT);
if (BUG(entry == NULL)) { if (BUG(entry == NULL)) {
/* Should never happen because we note down the address in the geoip /* Should never happen because we note down the address in the geoip
@ -712,7 +712,7 @@ dos_new_client_conn(or_connection_t *or_conn, const char *transport_name)
entry->dos_stats.concurrent_count++; entry->dos_stats.concurrent_count++;
or_conn->tracked_for_dos_mitigation = 1; or_conn->tracked_for_dos_mitigation = 1;
log_debug(LD_DOS, "Client address %s has now %u concurrent connections.", log_debug(LD_DOS, "Client address %s has now %u concurrent connections.",
fmt_addr(&or_conn->real_addr), fmt_addr(&TO_CONN(or_conn)->addr),
entry->dos_stats.concurrent_count); entry->dos_stats.concurrent_count);
end: end:
@ -735,7 +735,7 @@ dos_close_client_conn(const or_connection_t *or_conn)
} }
/* We are only interested in client connection from the geoip cache. */ /* We are only interested in client connection from the geoip cache. */
entry = geoip_lookup_client(&or_conn->real_addr, NULL, entry = geoip_lookup_client(&TO_CONN(or_conn)->addr, NULL,
GEOIP_CLIENT_CONNECT); GEOIP_CLIENT_CONNECT);
if (entry == NULL) { if (entry == NULL) {
/* This can happen because we can close a connection before the channel /* This can happen because we can close a connection before the channel
@ -753,7 +753,7 @@ dos_close_client_conn(const or_connection_t *or_conn)
entry->dos_stats.concurrent_count--; entry->dos_stats.concurrent_count--;
log_debug(LD_DOS, "Client address %s has lost a connection. Concurrent " log_debug(LD_DOS, "Client address %s has lost a connection. Concurrent "
"connections are now at %u", "connections are now at %u",
fmt_addr(&or_conn->real_addr), fmt_addr(&TO_CONN(or_conn)->addr),
entry->dos_stats.concurrent_count); entry->dos_stats.concurrent_count);
end: end:

View File

@ -50,17 +50,18 @@ struct or_connection_t {
channel_tls_t *chan; channel_tls_t *chan;
/** /**
* The actual address (as modified by any proxies) that this connection * The "canonical" address and port for this relay's ORPort, if this is
* came from or went to. (See connection_t.addr for caveats.) * a known relay.
* *
* TECHNICAL DEBT: * An ORPort is "canonical" in this sense only if it is the same ORPort
* that is listed for this identity in the consensus we have.
* *
* This field shouldn't really exist. We need it because our code * This field may be set on outbound connections for _any_ relay, and on
* overwrites conenction_t.addr with the "canonical address" of the OR we * inbound connections after authentication. If we don't know the relay's
* are talking to, taken from the descriptor of the authenticated OR. * identity, or if we don't have the relay's identity in our consensus, we
* That's a bad choice. * leave this address as UNSPEC.
**/ **/
tor_addr_t real_addr; tor_addr_port_t canonical_orport;
/** Should this connection be used for extending circuits to the server /** Should this connection be used for extending circuits to the server
* matching the <b>identity_digest</b> field? Set to true if we're pretty * matching the <b>identity_digest</b> field? Set to true if we're pretty

View File

@ -2114,6 +2114,18 @@ tor_addr_port_eq(const tor_addr_port_t *a,
return tor_addr_eq(&a->addr, &b->addr) && a->port == b->port; return tor_addr_eq(&a->addr, &b->addr) && a->port == b->port;
} }
/**
* Copy a tor_addr_port_t from @a source to @a dest.
**/
void
tor_addr_port_copy(tor_addr_port_t *dest,
const tor_addr_port_t *source)
{
tor_assert(dest);
tor_assert(source);
memcpy(dest, source, sizeof(tor_addr_port_t));
}
/** Return true if <b>string</b> represents a valid IPv4 adddress in /** Return true if <b>string</b> represents a valid IPv4 adddress in
* 'a.b.c.d' form. * 'a.b.c.d' form.
*/ */

View File

@ -394,6 +394,7 @@ get_interface_address_list(int severity, int include_internal)
tor_addr_port_t *tor_addr_port_new(const tor_addr_t *addr, uint16_t port); tor_addr_port_t *tor_addr_port_new(const tor_addr_t *addr, uint16_t port);
int tor_addr_port_eq(const tor_addr_port_t *a, int tor_addr_port_eq(const tor_addr_port_t *a,
const tor_addr_port_t *b); const tor_addr_port_t *b);
void tor_addr_port_copy(tor_addr_port_t *dest, const tor_addr_port_t *source);
int string_is_valid_dest(const char *string); int string_is_valid_dest(const char *string);
int string_is_valid_nonrfc_hostname(const char *string); int string_is_valid_nonrfc_hostname(const char *string);

View File

@ -1554,7 +1554,7 @@ test_channel_listener(void *arg)
#define TEST_SETUP_MATCHES_ADDR(orcon, addr, src, rv) STMT_BEGIN \ #define TEST_SETUP_MATCHES_ADDR(orcon, addr, src, rv) STMT_BEGIN \
rv = tor_inet_pton(addr.family, src, &addr.addr); \ rv = tor_inet_pton(addr.family, src, &addr.addr); \
tt_int_op(rv, OP_EQ, 1); \ tt_int_op(rv, OP_EQ, 1); \
orcon->real_addr = addr; \ orcon->base_.addr = addr; \
STMT_END; STMT_END;
#define TEST_MATCHES_ADDR(chan, addr4, addr6, rv, exp) STMT_BEGIN \ #define TEST_MATCHES_ADDR(chan, addr4, addr6, rv, exp) STMT_BEGIN \

View File

@ -293,7 +293,7 @@ tlschan_connection_or_connect_mock(const tor_addr_t *addr,
result->base_.port = port; result->base_.port = port;
memcpy(result->identity_digest, digest, DIGEST_LEN); memcpy(result->identity_digest, digest, DIGEST_LEN);
result->chan = tlschan; result->chan = tlschan;
memcpy(&(result->real_addr), addr, sizeof(tor_addr_t)); memcpy(&result->base_.addr, addr, sizeof(tor_addr_t));
result->tls = (tor_tls_t *)((void *)(&fake_tortls)); result->tls = (tor_tls_t *)((void *)(&fake_tortls));
done: done:

View File

@ -911,7 +911,8 @@ test_failed_orconn_tracker(void *arg)
/* Prepare the OR connection that will be used in this test */ /* Prepare the OR connection that will be used in this test */
or_connection_t or_conn; or_connection_t or_conn;
tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&or_conn.real_addr, "18.0.0.1")); tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&or_conn.canonical_orport.addr,
"18.0.0.1"));
tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&or_conn.base_.addr, "18.0.0.1")); tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&or_conn.base_.addr, "18.0.0.1"));
or_conn.base_.port = 1; or_conn.base_.port = 1;
memset(or_conn.identity_digest, 'c', sizeof(or_conn.identity_digest)); memset(or_conn.identity_digest, 'c', sizeof(or_conn.identity_digest));
@ -1048,17 +1049,20 @@ test_conn_describe(void *arg)
tt_str_op(connection_describe(conn), OP_EQ, tt_str_op(connection_describe(conn), OP_EQ,
"OR connection (open) with [ffff:3333:1111::2]:8080 " "OR connection (open) with [ffff:3333:1111::2]:8080 "
"ID=0000000700000000000000000000000000000000"); "ID=0000000700000000000000000000000000000000");
// Add a 'real address' that is the same as the one we have. // Add a 'canonical address' that is the same as the one we have.
tor_addr_parse(&TO_OR_CONN(conn)->real_addr, "[ffff:3333:1111::2]"); tor_addr_parse(&TO_OR_CONN(conn)->canonical_orport.addr,
"[ffff:3333:1111::2]");
TO_OR_CONN(conn)->canonical_orport.port = 8080;
tt_str_op(connection_describe(conn), OP_EQ, tt_str_op(connection_describe(conn), OP_EQ,
"OR connection (open) with [ffff:3333:1111::2]:8080 " "OR connection (open) with [ffff:3333:1111::2]:8080 "
"ID=0000000700000000000000000000000000000000"); "ID=0000000700000000000000000000000000000000");
// Add a different 'real address' // Add a different 'canonical address'
tor_addr_parse(&TO_OR_CONN(conn)->real_addr, "[ffff:3333:1111::8]"); tor_addr_parse(&TO_OR_CONN(conn)->canonical_orport.addr,
"[ffff:3333:1111::8]");
tt_str_op(connection_describe(conn), OP_EQ, tt_str_op(connection_describe(conn), OP_EQ,
"OR connection (open) with [ffff:3333:1111::8]:8080 " "OR connection (open) with [ffff:3333:1111::2]:8080 "
"ID=0000000700000000000000000000000000000000 " "ID=0000000700000000000000000000000000000000 "
"canonical_addr=[ffff:3333:1111::2]"); "canonical_addr=[ffff:3333:1111::8]:8080");
// Clear identity_digest so that free_minimal won't complain. // Clear identity_digest so that free_minimal won't complain.
memset(TO_OR_CONN(conn)->identity_digest, 0, DIGEST_LEN); memset(TO_OR_CONN(conn)->identity_digest, 0, DIGEST_LEN);

View File

@ -66,9 +66,9 @@ test_dos_conn_creation(void *arg)
/* Initialize test data */ /* Initialize test data */
or_connection_t or_conn; or_connection_t or_conn;
time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */ time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&or_conn.real_addr, tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&TO_CONN(&or_conn)->addr,
"18.0.0.1")); "18.0.0.1"));
tor_addr_t *addr = &or_conn.real_addr; tor_addr_t *addr = &TO_CONN(&or_conn)->addr;
/* Get DoS subsystem limits */ /* Get DoS subsystem limits */
dos_init(); dos_init();
@ -139,9 +139,9 @@ test_dos_circuit_creation(void *arg)
/* Initialize test data */ /* Initialize test data */
or_connection_t or_conn; or_connection_t or_conn;
time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */ time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&or_conn.real_addr, tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&TO_CONN(&or_conn)->addr,
"18.0.0.1")); "18.0.0.1"));
tor_addr_t *addr = &or_conn.real_addr; tor_addr_t *addr = &TO_CONN(&or_conn)->addr;
/* Get DoS subsystem limits */ /* Get DoS subsystem limits */
dos_init(); dos_init();
@ -202,9 +202,9 @@ test_dos_bucket_refill(void *arg)
channel_init(chan); channel_init(chan);
chan->is_client = 1; chan->is_client = 1;
or_connection_t or_conn; or_connection_t or_conn;
tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&or_conn.real_addr, tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&TO_CONN(&or_conn)->addr,
"18.0.0.1")); "18.0.0.1"));
tor_addr_t *addr = &or_conn.real_addr; tor_addr_t *addr = &TO_CONN(&or_conn)->addr;
/* Initialize DoS subsystem and get relevant limits */ /* Initialize DoS subsystem and get relevant limits */
dos_init(); dos_init();
@ -443,10 +443,10 @@ test_known_relay(void *arg)
/* Setup an OR conn so we can pass it to the DoS subsystem. */ /* Setup an OR conn so we can pass it to the DoS subsystem. */
or_connection_t or_conn; or_connection_t or_conn;
tor_addr_parse(&or_conn.real_addr, "42.42.42.42"); tor_addr_parse(&TO_CONN(&or_conn)->addr, "42.42.42.42");
rs = tor_malloc_zero(sizeof(*rs)); rs = tor_malloc_zero(sizeof(*rs));
tor_addr_copy(&rs->ipv4_addr, &or_conn.real_addr); tor_addr_copy(&rs->ipv4_addr, &TO_CONN(&or_conn)->addr);
crypto_rand(rs->identity_digest, sizeof(rs->identity_digest)); crypto_rand(rs->identity_digest, sizeof(rs->identity_digest));
smartlist_add(dummy_ns->routerstatus_list, rs); smartlist_add(dummy_ns->routerstatus_list, rs);
@ -457,7 +457,8 @@ test_known_relay(void *arg)
/* We have now a node in our list so we'll make sure we don't count it as a /* We have now a node in our list so we'll make sure we don't count it as a
* client connection. */ * client connection. */
geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &or_conn.real_addr, NULL, 0); geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &TO_CONN(&or_conn)->addr,
NULL, 0);
/* Suppose we have 5 connections in rapid succession, the counter should /* Suppose we have 5 connections in rapid succession, the counter should
* always be 0 because we should ignore this. */ * always be 0 because we should ignore this. */
dos_new_client_conn(&or_conn, NULL); dos_new_client_conn(&or_conn, NULL);
@ -465,18 +466,21 @@ test_known_relay(void *arg)
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); dos_new_client_conn(&or_conn, NULL);
entry = geoip_lookup_client(&or_conn.real_addr, NULL, GEOIP_CLIENT_CONNECT); entry = geoip_lookup_client(&TO_CONN(&or_conn)->addr, NULL,
GEOIP_CLIENT_CONNECT);
tt_assert(entry); tt_assert(entry);
/* We should have a count of 0. */ /* We should have a count of 0. */
tt_uint_op(entry->dos_stats.concurrent_count, OP_EQ, 0); tt_uint_op(entry->dos_stats.concurrent_count, OP_EQ, 0);
/* To make sure that his is working properly, make a unknown client /* To make sure that his is working properly, make a unknown client
* connection and see if we do get it. */ * connection and see if we do get it. */
tor_addr_parse(&or_conn.real_addr, "42.42.42.43"); tor_addr_parse(&TO_CONN(&or_conn)->addr, "42.42.42.43");
geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &or_conn.real_addr, NULL, 0); geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &TO_CONN(&or_conn)->addr,
NULL, 0);
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); entry = geoip_lookup_client(&TO_CONN(&or_conn)->addr, NULL,
GEOIP_CLIENT_CONNECT);
tt_assert(entry); tt_assert(entry);
/* We should have a count of 2. */ /* We should have a count of 2. */
tt_uint_op(entry->dos_stats.concurrent_count, OP_EQ, 2); tt_uint_op(entry->dos_stats.concurrent_count, OP_EQ, 2);