mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
Merge remote-tracking branch 'tor-github/pr/1801/head'
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
o Code simplification and refactoring:
|
||||
- Move the circuit extend code to the relay module.
|
||||
Split the circuit extend function into smaller functions.
|
||||
Closes ticket 33633.
|
||||
- Move LOG_PROTOCOL_WARN to app/config.c. Resolves a dependency inversion.
|
||||
Closes ticket 33633.
|
||||
@@ -83,9 +83,9 @@ problem dependency-violation /src/core/mainloop/netstatus.c 4
|
||||
problem dependency-violation /src/core/mainloop/periodic.c 2
|
||||
problem dependency-violation /src/core/or/address_set.c 1
|
||||
problem dependency-violation /src/core/or/cell_queue_st.h 1
|
||||
problem file-size /src/core/or/channel.c 3464
|
||||
problem file-size /src/core/or/channel.c 3500
|
||||
problem dependency-violation /src/core/or/channel.c 9
|
||||
problem file-size /src/core/or/channel.h 775
|
||||
problem file-size /src/core/or/channel.h 800
|
||||
problem dependency-violation /src/core/or/channel.h 1
|
||||
problem dependency-violation /src/core/or/channelpadding.c 6
|
||||
problem function-size /src/core/or/channeltls.c:channel_tls_handle_var_cell() 160
|
||||
@@ -94,9 +94,8 @@ problem function-size /src/core/or/channeltls.c:channel_tls_process_netinfo_cell
|
||||
problem function-size /src/core/or/channeltls.c:channel_tls_process_certs_cell() 246
|
||||
problem function-size /src/core/or/channeltls.c:channel_tls_process_authenticate_cell() 202
|
||||
problem dependency-violation /src/core/or/channeltls.c 11
|
||||
problem include-count /src/core/or/circuitbuild.c 54
|
||||
problem include-count /src/core/or/circuitbuild.c 53
|
||||
problem function-size /src/core/or/circuitbuild.c:get_unique_circ_id_by_chan() 128
|
||||
problem function-size /src/core/or/circuitbuild.c:circuit_extend() 147
|
||||
problem function-size /src/core/or/circuitbuild.c:choose_good_exit_server_general() 206
|
||||
problem dependency-violation /src/core/or/circuitbuild.c 25
|
||||
problem include-count /src/core/or/circuitlist.c 55
|
||||
@@ -129,7 +128,7 @@ problem function-size /src/core/or/circuituse.c:connection_ap_handshake_attach_c
|
||||
problem dependency-violation /src/core/or/circuituse.c 24
|
||||
problem function-size /src/core/or/command.c:command_process_create_cell() 156
|
||||
problem function-size /src/core/or/command.c:command_process_relay_cell() 132
|
||||
problem dependency-violation /src/core/or/command.c 8
|
||||
problem dependency-violation /src/core/or/command.c 9
|
||||
problem file-size /src/core/or/connection_edge.c 4655
|
||||
problem include-count /src/core/or/connection_edge.c 65
|
||||
problem function-size /src/core/or/connection_edge.c:connection_ap_expire_beginning() 117
|
||||
@@ -147,7 +146,7 @@ problem function-size /src/core/or/connection_or.c:connection_or_client_learned_
|
||||
problem dependency-violation /src/core/or/connection_or.c 21
|
||||
problem dependency-violation /src/core/or/dos.c 6
|
||||
problem dependency-violation /src/core/or/onion.c 2
|
||||
problem file-size /src/core/or/or.h 1107
|
||||
problem file-size /src/core/or/or.h 1105
|
||||
problem include-count /src/core/or/or.h 48
|
||||
problem dependency-violation /src/core/or/or.h 1
|
||||
problem dependency-violation /src/core/or/or_periodic.c 1
|
||||
@@ -156,7 +155,7 @@ problem function-size /src/core/or/policies.c:policy_summarize() 107
|
||||
problem dependency-violation /src/core/or/policies.c 14
|
||||
problem function-size /src/core/or/protover.c:protover_all_supported() 117
|
||||
problem dependency-violation /src/core/or/reasons.c 2
|
||||
problem file-size /src/core/or/relay.c 3264
|
||||
problem file-size /src/core/or/relay.c 3300
|
||||
problem function-size /src/core/or/relay.c:circuit_receive_relay_cell() 127
|
||||
problem function-size /src/core/or/relay.c:relay_send_command_from_edge_() 109
|
||||
problem function-size /src/core/or/relay.c:connection_ap_process_end_not_open() 192
|
||||
@@ -164,7 +163,7 @@ problem function-size /src/core/or/relay.c:connection_edge_process_relay_cell_no
|
||||
problem function-size /src/core/or/relay.c:handle_relay_cell_command() 369
|
||||
problem function-size /src/core/or/relay.c:connection_edge_package_raw_inbuf() 128
|
||||
problem function-size /src/core/or/relay.c:circuit_resume_edge_reading_helper() 146
|
||||
problem dependency-violation /src/core/or/relay.c 16
|
||||
problem dependency-violation /src/core/or/relay.c 17
|
||||
problem dependency-violation /src/core/or/scheduler.c 1
|
||||
problem function-size /src/core/or/scheduler_kist.c:kist_scheduler_run() 171
|
||||
problem dependency-violation /src/core/or/scheduler_kist.c 2
|
||||
|
||||
@@ -42,6 +42,8 @@ const char *escaped_safe_str(const char *address);
|
||||
void init_protocol_warning_severity_level(void);
|
||||
int get_protocol_warning_severity_level(void);
|
||||
|
||||
#define LOG_PROTOCOL_WARN (get_protocol_warning_severity_level())
|
||||
|
||||
/** An error from options_trial_assign() or options_init_from_string(). */
|
||||
typedef enum setopt_err_t {
|
||||
SETOPT_OK = 0,
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
**/
|
||||
#include "core/or/or.h"
|
||||
#include "core/or/channel.h"
|
||||
#include "core/or/circuitbuild.h"
|
||||
#include "core/or/circuitlist.h"
|
||||
#include "core/or/connection_or.h"
|
||||
#include "app/config/config.h"
|
||||
@@ -27,6 +26,7 @@
|
||||
#include "lib/crypt_ops/crypto_rand.h"
|
||||
#include "lib/crypt_ops/crypto_util.h"
|
||||
#include "core/or/onion.h"
|
||||
#include "feature/relay/circuitbuild_relay.h"
|
||||
#include "feature/relay/onion_queue.h"
|
||||
#include "feature/stats/rephist.h"
|
||||
#include "feature/relay/router.h"
|
||||
|
||||
+18
-17
@@ -2359,19 +2359,22 @@ channel_is_better(channel_t *a, channel_t *b)
|
||||
/**
|
||||
* Get a channel to extend a circuit.
|
||||
*
|
||||
* Pick a suitable channel to extend a circuit to given the desired digest
|
||||
* the address we believe is correct for that digest; this tries to see
|
||||
* if we already have one for the requested endpoint, but if there is no good
|
||||
* channel, set *msg_out to a message describing the channel's state
|
||||
* and our next action, and set *launch_out to a boolean indicated whether
|
||||
* the caller should try to launch a new channel with channel_connect().
|
||||
* Given the desired relay identity, pick a suitable channel to extend a
|
||||
* circuit to the target address requsted by the client. Search for an
|
||||
* existing channel for the requested endpoint. Make sure the channel is
|
||||
* usable for new circuits, and matches the target address.
|
||||
*
|
||||
* Try to return the best channel. But if there is no good channel, set
|
||||
* *msg_out to a message describing the channel's state and our next action,
|
||||
* and set *launch_out to a boolean indicated whether the caller should try to
|
||||
* launch a new channel with channel_connect().
|
||||
*/
|
||||
channel_t *
|
||||
channel_get_for_extend(const char *rsa_id_digest,
|
||||
const ed25519_public_key_t *ed_id,
|
||||
const tor_addr_t *target_addr,
|
||||
const char **msg_out,
|
||||
int *launch_out)
|
||||
MOCK_IMPL(channel_t *,
|
||||
channel_get_for_extend,(const char *rsa_id_digest,
|
||||
const ed25519_public_key_t *ed_id,
|
||||
const tor_addr_t *target_addr,
|
||||
const char **msg_out,
|
||||
int *launch_out))
|
||||
{
|
||||
channel_t *chan, *best = NULL;
|
||||
int n_inprogress_goodaddr = 0, n_old = 0;
|
||||
@@ -2382,9 +2385,7 @@ channel_get_for_extend(const char *rsa_id_digest,
|
||||
|
||||
chan = channel_find_by_remote_identity(rsa_id_digest, ed_id);
|
||||
|
||||
/* Walk the list, unrefing the old one and refing the new at each
|
||||
* iteration.
|
||||
*/
|
||||
/* Walk the list of channels */
|
||||
for (; chan; chan = channel_next_with_rsa_identity(chan)) {
|
||||
tor_assert(tor_memeq(chan->identity_digest,
|
||||
rsa_id_digest, DIGEST_LEN));
|
||||
@@ -2819,8 +2820,8 @@ channel_get_actual_remote_address(channel_t *chan)
|
||||
* Subsequent calls to channel_get_{actual,canonical}_remote_{address,descr}
|
||||
* may invalidate the return value from this function.
|
||||
*/
|
||||
const char *
|
||||
channel_get_canonical_remote_descr(channel_t *chan)
|
||||
MOCK_IMPL(const char *,
|
||||
channel_get_canonical_remote_descr,(channel_t *chan))
|
||||
{
|
||||
tor_assert(chan);
|
||||
tor_assert(chan->get_remote_descr);
|
||||
|
||||
@@ -658,11 +658,12 @@ channel_t * channel_connect(const tor_addr_t *addr, uint16_t port,
|
||||
const char *rsa_id_digest,
|
||||
const struct ed25519_public_key_t *ed_id);
|
||||
|
||||
channel_t * channel_get_for_extend(const char *rsa_id_digest,
|
||||
MOCK_DECL(channel_t *, channel_get_for_extend,(
|
||||
const char *rsa_id_digest,
|
||||
const struct ed25519_public_key_t *ed_id,
|
||||
const tor_addr_t *target_addr,
|
||||
const char **msg_out,
|
||||
int *launch_out);
|
||||
int *launch_out));
|
||||
|
||||
/* Ask which of two channels is better for circuit-extension purposes */
|
||||
int channel_is_better(channel_t *a, channel_t *b);
|
||||
@@ -723,7 +724,7 @@ const char * channel_get_actual_remote_descr(channel_t *chan);
|
||||
const char * channel_get_actual_remote_address(channel_t *chan);
|
||||
MOCK_DECL(int, channel_get_addr_if_possible, (channel_t *chan,
|
||||
tor_addr_t *addr_out));
|
||||
const char * channel_get_canonical_remote_descr(channel_t *chan);
|
||||
MOCK_DECL(const char *, channel_get_canonical_remote_descr,(channel_t *chan));
|
||||
int channel_has_queued_writes(channel_t *chan);
|
||||
int channel_is_bad_for_new_circs(channel_t *chan);
|
||||
void channel_mark_bad_for_new_circs(channel_t *chan);
|
||||
|
||||
+9
-264
@@ -21,8 +21,7 @@
|
||||
* cells arrive, the client will invoke circuit_send_next_onion_skin() to send
|
||||
* CREATE or RELAY_EXTEND cells.
|
||||
*
|
||||
* On the server side, this module also handles the logic of responding to
|
||||
* RELAY_EXTEND requests, using circuit_extend().
|
||||
* The server side is handled in feature/relay/circuitbuild_relay.c.
|
||||
**/
|
||||
|
||||
#define CIRCUITBUILD_PRIVATE
|
||||
@@ -35,7 +34,6 @@
|
||||
#include "core/crypto/onion_crypto.h"
|
||||
#include "core/crypto/onion_fast.h"
|
||||
#include "core/crypto/onion_tap.h"
|
||||
#include "core/crypto/relay_crypto.h"
|
||||
#include "core/mainloop/connection.h"
|
||||
#include "core/mainloop/mainloop.h"
|
||||
#include "core/or/channel.h"
|
||||
@@ -84,13 +82,6 @@
|
||||
#include "feature/nodelist/routerinfo_st.h"
|
||||
#include "feature/nodelist/routerstatus_st.h"
|
||||
|
||||
static channel_t * channel_connect_for_circuit(const tor_addr_t *addr,
|
||||
uint16_t port,
|
||||
const char *id_digest,
|
||||
const ed25519_public_key_t *ed_id);
|
||||
static int circuit_deliver_create_cell(circuit_t *circ,
|
||||
const create_cell_t *create_cell,
|
||||
int relayed);
|
||||
static int circuit_send_first_onion_skin(origin_circuit_t *circ);
|
||||
static int circuit_build_no_more_hops(origin_circuit_t *circ);
|
||||
static int circuit_send_intermediate_onion_skin(origin_circuit_t *circ,
|
||||
@@ -104,10 +95,10 @@ static const node_t *choose_good_middle_server(uint8_t purpose,
|
||||
* and then calls command_setup_channel() to give it the right
|
||||
* callbacks.
|
||||
*/
|
||||
static channel_t *
|
||||
channel_connect_for_circuit(const tor_addr_t *addr, uint16_t port,
|
||||
const char *id_digest,
|
||||
const ed25519_public_key_t *ed_id)
|
||||
MOCK_IMPL(channel_t *,
|
||||
channel_connect_for_circuit,(const tor_addr_t *addr, uint16_t port,
|
||||
const char *id_digest,
|
||||
const struct ed25519_public_key_t *ed_id))
|
||||
{
|
||||
channel_t *chan;
|
||||
|
||||
@@ -707,9 +698,10 @@ circuit_n_chan_done(channel_t *chan, int status, int close_origin_circuits)
|
||||
* gave us via an EXTEND cell, so we shouldn't worry if we don't understand
|
||||
* it. Return -1 if we failed to find a suitable circid, else return 0.
|
||||
*/
|
||||
static int
|
||||
circuit_deliver_create_cell(circuit_t *circ, const create_cell_t *create_cell,
|
||||
int relayed)
|
||||
MOCK_IMPL(int,
|
||||
circuit_deliver_create_cell,(circuit_t *circ,
|
||||
const struct create_cell_t *create_cell,
|
||||
int relayed))
|
||||
{
|
||||
cell_t cell;
|
||||
circid_t id;
|
||||
@@ -767,40 +759,6 @@ circuit_deliver_create_cell(circuit_t *circ, const create_cell_t *create_cell,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** We've decided to start our reachability testing. If all
|
||||
* is set, log this to the user. Return 1 if we did, or 0 if
|
||||
* we chose not to log anything. */
|
||||
int
|
||||
inform_testing_reachability(void)
|
||||
{
|
||||
char dirbuf[128];
|
||||
char *address;
|
||||
const routerinfo_t *me = router_get_my_routerinfo();
|
||||
if (!me)
|
||||
return 0;
|
||||
address = tor_dup_ip(me->addr);
|
||||
control_event_server_status(LOG_NOTICE,
|
||||
"CHECKING_REACHABILITY ORADDRESS=%s:%d",
|
||||
address, me->or_port);
|
||||
if (me->dir_port) {
|
||||
tor_snprintf(dirbuf, sizeof(dirbuf), " and DirPort %s:%d",
|
||||
address, me->dir_port);
|
||||
control_event_server_status(LOG_NOTICE,
|
||||
"CHECKING_REACHABILITY DIRADDRESS=%s:%d",
|
||||
address, me->dir_port);
|
||||
}
|
||||
log_notice(LD_OR, "Now checking whether ORPort %s:%d%s %s reachable... "
|
||||
"(this may take up to %d minutes -- look for log "
|
||||
"messages indicating success)",
|
||||
address, me->or_port,
|
||||
me->dir_port ? dirbuf : "",
|
||||
me->dir_port ? "are" : "is",
|
||||
TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT/60);
|
||||
|
||||
tor_free(address);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Return true iff we should send a create_fast cell to start building a given
|
||||
* circuit */
|
||||
static inline int
|
||||
@@ -1200,164 +1158,6 @@ circuit_note_clock_jumped(int64_t seconds_elapsed, bool was_idle)
|
||||
}
|
||||
}
|
||||
|
||||
/** Take the 'extend' <b>cell</b>, pull out addr/port plus the onion
|
||||
* skin and identity digest for the next hop. If we're already connected,
|
||||
* pass the onion skin to the next hop using a create cell; otherwise
|
||||
* launch a new OR connection, and <b>circ</b> will notice when the
|
||||
* connection succeeds or fails.
|
||||
*
|
||||
* Return -1 if we want to warn and tear down the circuit, else return 0.
|
||||
*/
|
||||
int
|
||||
circuit_extend(cell_t *cell, circuit_t *circ)
|
||||
{
|
||||
channel_t *n_chan;
|
||||
relay_header_t rh;
|
||||
extend_cell_t ec;
|
||||
const char *msg = NULL;
|
||||
int should_launch = 0;
|
||||
|
||||
if (circ->n_chan) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||
"n_chan already set. Bug/attack. Closing.");
|
||||
return -1;
|
||||
}
|
||||
if (circ->n_hop) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||
"conn to next hop already launched. Bug/attack. Closing.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!server_mode(get_options())) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||
"Got an extend cell, but running as a client. Closing.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
relay_header_unpack(&rh, cell->payload);
|
||||
|
||||
if (extend_cell_parse(&ec, rh.command,
|
||||
cell->payload+RELAY_HEADER_SIZE,
|
||||
rh.length) < 0) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||
"Can't parse extend cell. Closing circuit.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!ec.orport_ipv4.port || tor_addr_is_null(&ec.orport_ipv4.addr)) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||
"Client asked me to extend to zero destination port or addr.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tor_addr_is_internal(&ec.orport_ipv4.addr, 0) &&
|
||||
!get_options()->ExtendAllowPrivateAddresses) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||
"Client asked me to extend to a private address");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check if they asked us for 0000..0000. We support using
|
||||
* an empty fingerprint for the first hop (e.g. for a bridge relay),
|
||||
* but we don't want to let clients send us extend cells for empty
|
||||
* fingerprints -- a) because it opens the user up to a mitm attack,
|
||||
* and b) because it lets an attacker force the relay to hold open a
|
||||
* new TLS connection for each extend request. */
|
||||
if (tor_digest_is_zero((const char*)ec.node_id)) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||
"Client asked me to extend without specifying an id_digest.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Fill in ed_pubkey if it was not provided and we can infer it from
|
||||
* our networkstatus */
|
||||
if (ed25519_public_key_is_zero(&ec.ed_pubkey)) {
|
||||
const node_t *node = node_get_by_id((const char*)ec.node_id);
|
||||
const ed25519_public_key_t *node_ed_id = NULL;
|
||||
if (node &&
|
||||
node_supports_ed25519_link_authentication(node, 1) &&
|
||||
(node_ed_id = node_get_ed25519_id(node))) {
|
||||
ed25519_pubkey_copy(&ec.ed_pubkey, node_ed_id);
|
||||
}
|
||||
}
|
||||
|
||||
/* Next, check if we're being asked to connect to the hop that the
|
||||
* extend cell came from. There isn't any reason for that, and it can
|
||||
* assist circular-path attacks. */
|
||||
if (tor_memeq(ec.node_id,
|
||||
TO_OR_CIRCUIT(circ)->p_chan->identity_digest,
|
||||
DIGEST_LEN)) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||
"Client asked me to extend back to the previous hop.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check the previous hop Ed25519 ID too */
|
||||
if (! ed25519_public_key_is_zero(&ec.ed_pubkey) &&
|
||||
ed25519_pubkey_eq(&ec.ed_pubkey,
|
||||
&TO_OR_CIRCUIT(circ)->p_chan->ed25519_identity)) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||
"Client asked me to extend back to the previous hop "
|
||||
"(by Ed25519 ID).");
|
||||
return -1;
|
||||
}
|
||||
|
||||
n_chan = channel_get_for_extend((const char*)ec.node_id,
|
||||
&ec.ed_pubkey,
|
||||
&ec.orport_ipv4.addr,
|
||||
&msg,
|
||||
&should_launch);
|
||||
|
||||
if (!n_chan) {
|
||||
log_debug(LD_CIRC|LD_OR,"Next router (%s): %s",
|
||||
fmt_addrport(&ec.orport_ipv4.addr,ec.orport_ipv4.port),
|
||||
msg?msg:"????");
|
||||
|
||||
circ->n_hop = extend_info_new(NULL /*nickname*/,
|
||||
(const char*)ec.node_id,
|
||||
&ec.ed_pubkey,
|
||||
NULL, /*onion_key*/
|
||||
NULL, /*curve25519_key*/
|
||||
&ec.orport_ipv4.addr,
|
||||
ec.orport_ipv4.port);
|
||||
|
||||
circ->n_chan_create_cell = tor_memdup(&ec.create_cell,
|
||||
sizeof(ec.create_cell));
|
||||
|
||||
circuit_set_state(circ, CIRCUIT_STATE_CHAN_WAIT);
|
||||
|
||||
if (should_launch) {
|
||||
/* we should try to open a connection */
|
||||
n_chan = channel_connect_for_circuit(&ec.orport_ipv4.addr,
|
||||
ec.orport_ipv4.port,
|
||||
(const char*)ec.node_id,
|
||||
&ec.ed_pubkey);
|
||||
if (!n_chan) {
|
||||
log_info(LD_CIRC,"Launching n_chan failed. Closing circuit.");
|
||||
circuit_mark_for_close(circ, END_CIRC_REASON_CONNECTFAILED);
|
||||
return 0;
|
||||
}
|
||||
log_debug(LD_CIRC,"connecting in progress (or finished). Good.");
|
||||
}
|
||||
/* return success. The onion/circuit/etc will be taken care of
|
||||
* automatically (may already have been) whenever n_chan reaches
|
||||
* OR_CONN_STATE_OPEN.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
tor_assert(!circ->n_hop); /* Connection is already established. */
|
||||
circ->n_chan = n_chan;
|
||||
log_debug(LD_CIRC,
|
||||
"n_chan is %s",
|
||||
channel_get_canonical_remote_descr(n_chan));
|
||||
|
||||
if (circuit_deliver_create_cell(circ, &ec.create_cell, 1) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** A "created" cell <b>reply</b> came back to us on circuit <b>circ</b>.
|
||||
* (The body of <b>reply</b> varies depending on what sort of handshake
|
||||
* this is.)
|
||||
@@ -1467,61 +1267,6 @@ circuit_truncated(origin_circuit_t *circ, int reason)
|
||||
#endif /* 0 */
|
||||
}
|
||||
|
||||
/** Given a response payload and keys, initialize, then send a created
|
||||
* cell back.
|
||||
*/
|
||||
int
|
||||
onionskin_answer(or_circuit_t *circ,
|
||||
const created_cell_t *created_cell,
|
||||
const char *keys, size_t keys_len,
|
||||
const uint8_t *rend_circ_nonce)
|
||||
{
|
||||
cell_t cell;
|
||||
|
||||
tor_assert(keys_len == CPATH_KEY_MATERIAL_LEN);
|
||||
|
||||
if (created_cell_format(&cell, created_cell) < 0) {
|
||||
log_warn(LD_BUG,"couldn't format created cell (type=%d, len=%d)",
|
||||
(int)created_cell->cell_type, (int)created_cell->handshake_len);
|
||||
return -1;
|
||||
}
|
||||
cell.circ_id = circ->p_circ_id;
|
||||
|
||||
circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OPEN);
|
||||
|
||||
log_debug(LD_CIRC,"init digest forward 0x%.8x, backward 0x%.8x.",
|
||||
(unsigned int)get_uint32(keys),
|
||||
(unsigned int)get_uint32(keys+20));
|
||||
if (relay_crypto_init(&circ->crypto, keys, keys_len, 0, 0)<0) {
|
||||
log_warn(LD_BUG,"Circuit initialization failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(circ->rend_circ_nonce, rend_circ_nonce, DIGEST_LEN);
|
||||
|
||||
int used_create_fast = (created_cell->cell_type == CELL_CREATED_FAST);
|
||||
|
||||
append_cell_to_circuit_queue(TO_CIRCUIT(circ),
|
||||
circ->p_chan, &cell, CELL_DIRECTION_IN, 0);
|
||||
log_debug(LD_CIRC,"Finished sending '%s' cell.",
|
||||
used_create_fast ? "created_fast" : "created");
|
||||
|
||||
/* Ignore the local bit when ExtendAllowPrivateAddresses is set:
|
||||
* it violates the assumption that private addresses are local.
|
||||
* Also, many test networks run on local addresses, and
|
||||
* TestingTorNetwork sets ExtendAllowPrivateAddresses. */
|
||||
if ((!channel_is_local(circ->p_chan)
|
||||
|| get_options()->ExtendAllowPrivateAddresses)
|
||||
&& !channel_is_outgoing(circ->p_chan)) {
|
||||
/* record that we could process create cells from a non-local conn
|
||||
* that we didn't initiate; presumably this means that create cells
|
||||
* can reach us too. */
|
||||
router_orport_found_reachable();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Helper for new_route_len(). Choose a circuit length for purpose
|
||||
* <b>purpose</b>: DEFAULT_ROUTE_LEN (+ 1 if someone else chose the
|
||||
* exit). If someone else chose the exit, they could be colluding
|
||||
|
||||
@@ -29,19 +29,13 @@ struct circuit_guard_state_t *origin_circuit_get_guard_state(
|
||||
int circuit_handle_first_hop(origin_circuit_t *circ);
|
||||
void circuit_n_chan_done(channel_t *chan, int status,
|
||||
int close_origin_circuits);
|
||||
int inform_testing_reachability(void);
|
||||
int circuit_timeout_want_to_count_circ(const origin_circuit_t *circ);
|
||||
int circuit_send_next_onion_skin(origin_circuit_t *circ);
|
||||
void circuit_note_clock_jumped(int64_t seconds_elapsed, bool was_idle);
|
||||
int circuit_extend(cell_t *cell, circuit_t *circ);
|
||||
struct created_cell_t;
|
||||
int circuit_finish_handshake(origin_circuit_t *circ,
|
||||
const struct created_cell_t *created_cell);
|
||||
int circuit_truncated(origin_circuit_t *circ, int reason);
|
||||
int onionskin_answer(or_circuit_t *circ,
|
||||
const struct created_cell_t *created_cell,
|
||||
const char *keys, size_t keys_len,
|
||||
const uint8_t *rend_circ_nonce);
|
||||
MOCK_DECL(int, circuit_all_predicted_ports_handled, (time_t now,
|
||||
int *need_uptime,
|
||||
int *need_capacity));
|
||||
@@ -77,6 +71,20 @@ const node_t *choose_good_entry_server(uint8_t purpose,
|
||||
struct circuit_guard_state_t **guard_state_out);
|
||||
void circuit_upgrade_circuits_from_guard_wait(void);
|
||||
|
||||
struct ed25519_public_key_t;
|
||||
|
||||
MOCK_DECL(channel_t *,
|
||||
channel_connect_for_circuit,(const tor_addr_t *addr,
|
||||
uint16_t port,
|
||||
const char *id_digest,
|
||||
const struct ed25519_public_key_t *ed_id));
|
||||
|
||||
struct create_cell_t;
|
||||
MOCK_DECL(int,
|
||||
circuit_deliver_create_cell,(circuit_t *circ,
|
||||
const struct create_cell_t *create_cell,
|
||||
int relayed));
|
||||
|
||||
#ifdef CIRCUITBUILD_PRIVATE
|
||||
STATIC circid_t get_unique_circ_id_by_chan(channel_t *chan);
|
||||
STATIC int new_route_len(uint8_t purpose, extend_info_t *exit_ei,
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
#include "feature/nodelist/describe.h"
|
||||
#include "feature/nodelist/nodelist.h"
|
||||
#include "feature/nodelist/routerlist.h"
|
||||
#include "feature/relay/circuitbuild_relay.h"
|
||||
#include "feature/relay/routermode.h"
|
||||
#include "feature/stats/rephist.h"
|
||||
#include "lib/crypt_ops/crypto_util.h"
|
||||
|
||||
+5
-3
@@ -374,9 +374,11 @@ extend_cell_from_extend2_cell_body(extend_cell_t *cell_out,
|
||||
/** Parse an EXTEND or EXTEND2 cell (according to <b>command</b>) from the
|
||||
* <b>payload_length</b> bytes of <b>payload</b> into <b>cell_out</b>. Return
|
||||
* 0 on success, -1 on failure. */
|
||||
int
|
||||
extend_cell_parse(extend_cell_t *cell_out, const uint8_t command,
|
||||
const uint8_t *payload, size_t payload_length)
|
||||
MOCK_IMPL(int,
|
||||
extend_cell_parse,(extend_cell_t *cell_out,
|
||||
const uint8_t command,
|
||||
const uint8_t *payload,
|
||||
size_t payload_length))
|
||||
{
|
||||
|
||||
tor_assert(cell_out);
|
||||
|
||||
+4
-2
@@ -74,8 +74,10 @@ void create_cell_init(create_cell_t *cell_out, uint8_t cell_type,
|
||||
const uint8_t *onionskin);
|
||||
int create_cell_parse(create_cell_t *cell_out, const cell_t *cell_in);
|
||||
int created_cell_parse(created_cell_t *cell_out, const cell_t *cell_in);
|
||||
int extend_cell_parse(extend_cell_t *cell_out, const uint8_t command,
|
||||
const uint8_t *payload_in, size_t payload_len);
|
||||
MOCK_DECL(int,extend_cell_parse,(extend_cell_t *cell_out,
|
||||
const uint8_t command,
|
||||
const uint8_t *payload_in,
|
||||
size_t payload_len));
|
||||
int extended_cell_parse(extended_cell_t *cell_out, const uint8_t command,
|
||||
const uint8_t *payload_in, size_t payload_len);
|
||||
|
||||
|
||||
@@ -995,8 +995,6 @@ typedef struct routerset_t routerset_t;
|
||||
|
||||
typedef struct or_options_t or_options_t;
|
||||
|
||||
#define LOG_PROTOCOL_WARN (get_protocol_warning_severity_level())
|
||||
|
||||
typedef struct or_state_t or_state_t;
|
||||
|
||||
#define MAX_SOCKS_ADDR_LEN 256
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
#include "lib/crypt_ops/crypto_util.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/relay/dns.h"
|
||||
#include "feature/relay/circuitbuild_relay.h"
|
||||
#include "feature/stats/geoip_stats.h"
|
||||
#include "feature/hs/hs_cache.h"
|
||||
#include "core/mainloop/mainloop.h"
|
||||
|
||||
@@ -1074,8 +1074,8 @@ node_get_by_nickname,(const char *nickname, unsigned flags))
|
||||
|
||||
/** Return the Ed25519 identity key for the provided node, or NULL if it
|
||||
* doesn't have one. */
|
||||
const ed25519_public_key_t *
|
||||
node_get_ed25519_id(const node_t *node)
|
||||
MOCK_IMPL(const ed25519_public_key_t *,
|
||||
node_get_ed25519_id,(const node_t *node))
|
||||
{
|
||||
const ed25519_public_key_t *ri_pk = NULL;
|
||||
const ed25519_public_key_t *md_pk = NULL;
|
||||
@@ -1158,9 +1158,9 @@ node_get_protover_summary_flags(const node_t *node)
|
||||
* by ed25519 ID during the link handshake. If <b>compatible_with_us</b>,
|
||||
* it needs to be using a link authentication method that we understand.
|
||||
* If not, any plausible link authentication method will do. */
|
||||
int
|
||||
node_supports_ed25519_link_authentication(const node_t *node,
|
||||
int compatible_with_us)
|
||||
MOCK_IMPL(int,
|
||||
node_supports_ed25519_link_authentication,(const node_t *node,
|
||||
int compatible_with_us))
|
||||
{
|
||||
if (! node_get_ed25519_id(node))
|
||||
return 0;
|
||||
|
||||
@@ -70,11 +70,13 @@ const char *node_get_platform(const node_t *node);
|
||||
uint32_t node_get_prim_addr_ipv4h(const node_t *node);
|
||||
void node_get_address_string(const node_t *node, char *cp, size_t len);
|
||||
long node_get_declared_uptime(const node_t *node);
|
||||
const struct ed25519_public_key_t *node_get_ed25519_id(const node_t *node);
|
||||
MOCK_DECL(const struct ed25519_public_key_t *,node_get_ed25519_id,
|
||||
(const node_t *node));
|
||||
int node_ed25519_id_matches(const node_t *node,
|
||||
const struct ed25519_public_key_t *id);
|
||||
int node_supports_ed25519_link_authentication(const node_t *node,
|
||||
int compatible_with_us);
|
||||
MOCK_DECL(int,node_supports_ed25519_link_authentication,
|
||||
(const node_t *node,
|
||||
int compatible_with_us));
|
||||
int node_supports_v3_hsdir(const node_t *node);
|
||||
int node_supports_ed25519_hs_intro(const node_t *node);
|
||||
int node_supports_v3_rendezvous_point(const node_t *node);
|
||||
|
||||
@@ -0,0 +1,399 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2020, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file circuitbuild_relay.c
|
||||
* @brief Implements the details of exteding circuits (by relaying extend
|
||||
* cells as create cells, and answering create cells).
|
||||
*
|
||||
* On the server side, this module handles the logic of responding to
|
||||
* RELAY_EXTEND requests, using circuit_extend() and onionskin_answer().
|
||||
*
|
||||
* The shared client and server code is in core/or/circuitbuild.c.
|
||||
**/
|
||||
|
||||
#include "orconfig.h"
|
||||
#include "feature/relay/circuitbuild_relay.h"
|
||||
|
||||
#include "core/or/or.h"
|
||||
#include "app/config/config.h"
|
||||
|
||||
#include "core/crypto/relay_crypto.h"
|
||||
|
||||
#include "core/or/cell_st.h"
|
||||
#include "core/or/circuit_st.h"
|
||||
#include "core/or/extend_info_st.h"
|
||||
#include "core/or/or_circuit_st.h"
|
||||
|
||||
#include "core/or/channel.h"
|
||||
#include "core/or/circuitbuild.h"
|
||||
#include "core/or/circuitlist.h"
|
||||
#include "core/or/onion.h"
|
||||
#include "core/or/relay.h"
|
||||
|
||||
#include "feature/nodelist/nodelist.h"
|
||||
|
||||
#include "feature/relay/routermode.h"
|
||||
#include "feature/relay/selftest.h"
|
||||
|
||||
/* Before replying to an extend cell, check the state of the circuit
|
||||
* <b>circ</b>, and the configured tor mode.
|
||||
*
|
||||
* <b>circ</b> must not be NULL.
|
||||
*
|
||||
* If the state and mode are valid, return 0.
|
||||
* Otherwise, if they are invalid, log a protocol warning, and return -1.
|
||||
*/
|
||||
STATIC int
|
||||
circuit_extend_state_valid_helper(const struct circuit_t *circ)
|
||||
{
|
||||
if (!server_mode(get_options())) {
|
||||
circuitbuild_warn_client_extend();
|
||||
return -1;
|
||||
}
|
||||
|
||||
IF_BUG_ONCE(!circ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (circ->n_chan) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||
"n_chan already set. Bug/attack. Closing.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (circ->n_hop) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||
"conn to next hop already launched. Bug/attack. Closing.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make sure the extend cell <b>ec</b> has an ed25519 link specifier.
|
||||
*
|
||||
* First, check that the RSA node id is valid.
|
||||
* If the node id is valid, add the ed25519 link specifier (if required),
|
||||
* and return 0.
|
||||
*
|
||||
* Otherwise, if the node id is invalid, log a protocol warning,
|
||||
* and return -1.(And do not modify the extend cell.)
|
||||
*
|
||||
* Must be called before circuit_extend_lspec_valid_helper().
|
||||
*/
|
||||
STATIC int
|
||||
circuit_extend_add_ed25519_helper(struct extend_cell_t *ec)
|
||||
{
|
||||
IF_BUG_ONCE(!ec) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check if they asked us for 0000..0000. We support using
|
||||
* an empty fingerprint for the first hop (e.g. for a bridge relay),
|
||||
* but we don't want to let clients send us extend cells for empty
|
||||
* fingerprints -- a) because it opens the user up to a mitm attack,
|
||||
* and b) because it lets an attacker force the relay to hold open a
|
||||
* new TLS connection for each extend request. */
|
||||
if (tor_digest_is_zero((const char*)ec->node_id)) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||
"Client asked me to extend without specifying an id_digest.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Fill in ed_pubkey if it was not provided and we can infer it from
|
||||
* our networkstatus */
|
||||
if (ed25519_public_key_is_zero(&ec->ed_pubkey)) {
|
||||
const node_t *node = node_get_by_id((const char*)ec->node_id);
|
||||
const ed25519_public_key_t *node_ed_id = NULL;
|
||||
if (node &&
|
||||
node_supports_ed25519_link_authentication(node, 1) &&
|
||||
(node_ed_id = node_get_ed25519_id(node))) {
|
||||
ed25519_pubkey_copy(&ec->ed_pubkey, node_ed_id);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Before replying to an extend cell, check the link specifiers in the extend
|
||||
* cell <b>ec</b>, which was received on the circuit <b>circ</b>.
|
||||
*
|
||||
* If they are valid, return 0.
|
||||
* Otherwise, if they are invalid, log a protocol warning, and return -1.
|
||||
*
|
||||
* Must be called after circuit_extend_add_ed25519_helper().
|
||||
*/
|
||||
STATIC int
|
||||
circuit_extend_lspec_valid_helper(const struct extend_cell_t *ec,
|
||||
const struct circuit_t *circ)
|
||||
{
|
||||
IF_BUG_ONCE(!ec) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
IF_BUG_ONCE(!circ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!ec->orport_ipv4.port || tor_addr_is_null(&ec->orport_ipv4.addr)) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||
"Client asked me to extend to zero destination port or addr.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tor_addr_is_internal(&ec->orport_ipv4.addr, 0) &&
|
||||
!get_options()->ExtendAllowPrivateAddresses) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||
"Client asked me to extend to a private address.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
IF_BUG_ONCE(circ->magic != OR_CIRCUIT_MAGIC) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const channel_t *p_chan = CONST_TO_OR_CIRCUIT(circ)->p_chan;
|
||||
|
||||
IF_BUG_ONCE(!p_chan) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Next, check if we're being asked to connect to the hop that the
|
||||
* extend cell came from. There isn't any reason for that, and it can
|
||||
* assist circular-path attacks. */
|
||||
if (tor_memeq(ec->node_id, p_chan->identity_digest, DIGEST_LEN)) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||
"Client asked me to extend back to the previous hop.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check the previous hop Ed25519 ID too */
|
||||
if (! ed25519_public_key_is_zero(&ec->ed_pubkey) &&
|
||||
ed25519_pubkey_eq(&ec->ed_pubkey, &p_chan->ed25519_identity)) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||
"Client asked me to extend back to the previous hop "
|
||||
"(by Ed25519 ID).");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* When there is no open channel for an extend cell <b>ec</b>, set up the
|
||||
* circuit <b>circ</b> to wait for a new connection. If <b>should_launch</b>
|
||||
* is true, open a new connection. (Otherwise, we are already waiting for a
|
||||
* new connection to the same relay.)
|
||||
*/
|
||||
STATIC void
|
||||
circuit_open_connection_for_extend(const struct extend_cell_t *ec,
|
||||
struct circuit_t *circ,
|
||||
int should_launch)
|
||||
{
|
||||
/* We have to check circ first, so we can close it on all other failures */
|
||||
IF_BUG_ONCE(!circ) {
|
||||
/* We can't mark a NULL circuit for close. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now we know that circ is not NULL */
|
||||
IF_BUG_ONCE(!ec) {
|
||||
circuit_mark_for_close(circ, END_CIRC_REASON_CONNECTFAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
circ->n_hop = extend_info_new(NULL /*nickname*/,
|
||||
(const char*)ec->node_id,
|
||||
&ec->ed_pubkey,
|
||||
NULL, /*onion_key*/
|
||||
NULL, /*curve25519_key*/
|
||||
&ec->orport_ipv4.addr,
|
||||
ec->orport_ipv4.port);
|
||||
|
||||
circ->n_chan_create_cell = tor_memdup(&ec->create_cell,
|
||||
sizeof(ec->create_cell));
|
||||
|
||||
circuit_set_state(circ, CIRCUIT_STATE_CHAN_WAIT);
|
||||
|
||||
if (should_launch) {
|
||||
/* we should try to open a connection */
|
||||
channel_t *n_chan = channel_connect_for_circuit(&ec->orport_ipv4.addr,
|
||||
ec->orport_ipv4.port,
|
||||
(const char*)ec->node_id,
|
||||
&ec->ed_pubkey);
|
||||
if (!n_chan) {
|
||||
log_info(LD_CIRC,"Launching n_chan failed. Closing circuit.");
|
||||
circuit_mark_for_close(circ, END_CIRC_REASON_CONNECTFAILED);
|
||||
return;
|
||||
}
|
||||
log_debug(LD_CIRC,"connecting in progress (or finished). Good.");
|
||||
}
|
||||
}
|
||||
|
||||
/** Take the 'extend' <b>cell</b>, pull out addr/port plus the onion
|
||||
* skin and identity digest for the next hop. If we're already connected,
|
||||
* pass the onion skin to the next hop using a create cell; otherwise
|
||||
* launch a new OR connection, and <b>circ</b> will notice when the
|
||||
* connection succeeds or fails.
|
||||
*
|
||||
* Return -1 if we want to warn and tear down the circuit, else return 0.
|
||||
*/
|
||||
int
|
||||
circuit_extend(struct cell_t *cell, struct circuit_t *circ)
|
||||
{
|
||||
channel_t *n_chan;
|
||||
relay_header_t rh;
|
||||
extend_cell_t ec;
|
||||
const char *msg = NULL;
|
||||
int should_launch = 0;
|
||||
|
||||
IF_BUG_ONCE(!cell) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
IF_BUG_ONCE(!circ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (circuit_extend_state_valid_helper(circ) < 0)
|
||||
return -1;
|
||||
|
||||
relay_header_unpack(&rh, cell->payload);
|
||||
|
||||
if (extend_cell_parse(&ec, rh.command,
|
||||
cell->payload+RELAY_HEADER_SIZE,
|
||||
rh.length) < 0) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||
"Can't parse extend cell. Closing circuit.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (circuit_extend_add_ed25519_helper(&ec) < 0)
|
||||
return -1;
|
||||
|
||||
if (circuit_extend_lspec_valid_helper(&ec, circ) < 0)
|
||||
return -1;
|
||||
|
||||
n_chan = channel_get_for_extend((const char*)ec.node_id,
|
||||
&ec.ed_pubkey,
|
||||
&ec.orport_ipv4.addr,
|
||||
&msg,
|
||||
&should_launch);
|
||||
|
||||
if (!n_chan) {
|
||||
log_debug(LD_CIRC|LD_OR,"Next router (%s): %s.",
|
||||
fmt_addrport(&ec.orport_ipv4.addr,ec.orport_ipv4.port),
|
||||
msg?msg:"????");
|
||||
|
||||
circuit_open_connection_for_extend(&ec, circ, should_launch);
|
||||
|
||||
/* return success. The onion/circuit/etc will be taken care of
|
||||
* automatically (may already have been) whenever n_chan reaches
|
||||
* OR_CONN_STATE_OPEN.
|
||||
*/
|
||||
return 0;
|
||||
} else {
|
||||
/* Connection is already established.
|
||||
* So we need to extend the circuit to the next hop. */
|
||||
tor_assert(!circ->n_hop);
|
||||
circ->n_chan = n_chan;
|
||||
log_debug(LD_CIRC,
|
||||
"n_chan is %s.",
|
||||
channel_get_canonical_remote_descr(n_chan));
|
||||
|
||||
if (circuit_deliver_create_cell(circ, &ec.create_cell, 1) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** On a relay, accept a create cell, initialise a circuit, and send a
|
||||
* created cell back.
|
||||
*
|
||||
* Given:
|
||||
* - a response payload consisting of:
|
||||
* - the <b>created_cell</b> and
|
||||
* - an optional <b>rend_circ_nonce</b>, and
|
||||
* - <b>keys</b> of length <b>keys_len</b>, which must be
|
||||
* CPATH_KEY_MATERIAL_LEN;
|
||||
* then:
|
||||
* - initialize the circuit <b>circ</b>'s cryptographic material,
|
||||
* - set the circuit's state to open, and
|
||||
* - send a created cell back on that circuit.
|
||||
*
|
||||
* If we haven't found our ORPorts reachable yet, and the channel meets the
|
||||
* necessary conditions, mark the relevant ORPorts as reachable.
|
||||
*
|
||||
* Returns -1 if cell or circuit initialisation fails.
|
||||
*/
|
||||
int
|
||||
onionskin_answer(struct or_circuit_t *circ,
|
||||
const created_cell_t *created_cell,
|
||||
const char *keys, size_t keys_len,
|
||||
const uint8_t *rend_circ_nonce)
|
||||
{
|
||||
cell_t cell;
|
||||
|
||||
IF_BUG_ONCE(!circ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
IF_BUG_ONCE(!created_cell) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
IF_BUG_ONCE(!keys) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
IF_BUG_ONCE(!rend_circ_nonce) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
tor_assert(keys_len == CPATH_KEY_MATERIAL_LEN);
|
||||
|
||||
if (created_cell_format(&cell, created_cell) < 0) {
|
||||
log_warn(LD_BUG,"couldn't format created cell (type=%d, len=%d).",
|
||||
(int)created_cell->cell_type, (int)created_cell->handshake_len);
|
||||
return -1;
|
||||
}
|
||||
cell.circ_id = circ->p_circ_id;
|
||||
|
||||
circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OPEN);
|
||||
|
||||
log_debug(LD_CIRC,"init digest forward 0x%.8x, backward 0x%.8x.",
|
||||
(unsigned int)get_uint32(keys),
|
||||
(unsigned int)get_uint32(keys+20));
|
||||
if (relay_crypto_init(&circ->crypto, keys, keys_len, 0, 0)<0) {
|
||||
log_warn(LD_BUG,"Circuit initialization failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(circ->rend_circ_nonce, rend_circ_nonce, DIGEST_LEN);
|
||||
|
||||
int used_create_fast = (created_cell->cell_type == CELL_CREATED_FAST);
|
||||
|
||||
append_cell_to_circuit_queue(TO_CIRCUIT(circ),
|
||||
circ->p_chan, &cell, CELL_DIRECTION_IN, 0);
|
||||
log_debug(LD_CIRC,"Finished sending '%s' cell.",
|
||||
used_create_fast ? "created_fast" : "created");
|
||||
|
||||
/* Ignore the local bit when ExtendAllowPrivateAddresses is set:
|
||||
* it violates the assumption that private addresses are local.
|
||||
* Also, many test networks run on local addresses, and
|
||||
* TestingTorNetwork sets ExtendAllowPrivateAddresses. */
|
||||
if ((!channel_is_local(circ->p_chan)
|
||||
|| get_options()->ExtendAllowPrivateAddresses)
|
||||
&& !channel_is_outgoing(circ->p_chan)) {
|
||||
/* record that we could process create cells from a non-local conn
|
||||
* that we didn't initiate; presumably this means that create cells
|
||||
* can reach us too. */
|
||||
router_orport_found_reachable();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2020, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file circuitbuild_relay.h
|
||||
* @brief Header for feature/relay/circuitbuild_relay.c
|
||||
**/
|
||||
|
||||
#ifndef TOR_FEATURE_RELAY_CIRCUITBUILD_RELAY_H
|
||||
#define TOR_FEATURE_RELAY_CIRCUITBUILD_RELAY_H
|
||||
|
||||
#include "lib/cc/torint.h"
|
||||
#include "lib/log/log.h"
|
||||
|
||||
#include "app/config/config.h"
|
||||
|
||||
struct cell_t;
|
||||
struct created_cell_t;
|
||||
|
||||
struct circuit_t;
|
||||
struct or_circuit_t;
|
||||
struct extend_cell_t;
|
||||
|
||||
/* Log a protocol warning about getting an extend cell on a client. */
|
||||
static inline void
|
||||
circuitbuild_warn_client_extend(void)
|
||||
{
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||
"Got an extend cell, but running as a client. Closing.");
|
||||
}
|
||||
|
||||
#ifdef HAVE_MODULE_RELAY
|
||||
|
||||
int circuit_extend(struct cell_t *cell, struct circuit_t *circ);
|
||||
|
||||
int onionskin_answer(struct or_circuit_t *circ,
|
||||
const struct created_cell_t *created_cell,
|
||||
const char *keys, size_t keys_len,
|
||||
const uint8_t *rend_circ_nonce);
|
||||
|
||||
#else /* !defined(HAVE_MODULE_RELAY) */
|
||||
|
||||
static inline int
|
||||
circuit_extend(struct cell_t *cell, struct circuit_t *circ)
|
||||
{
|
||||
(void)cell;
|
||||
(void)circ;
|
||||
circuitbuild_warn_client_extend();
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int
|
||||
onionskin_answer(struct or_circuit_t *circ,
|
||||
const struct created_cell_t *created_cell,
|
||||
const char *keys, size_t keys_len,
|
||||
const uint8_t *rend_circ_nonce)
|
||||
{
|
||||
(void)circ;
|
||||
(void)created_cell;
|
||||
(void)keys;
|
||||
(void)keys_len;
|
||||
(void)rend_circ_nonce;
|
||||
tor_assert_nonfatal_unreached();
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* defined(HAVE_MODULE_RELAY) */
|
||||
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
|
||||
STATIC int circuit_extend_state_valid_helper(const struct circuit_t *circ);
|
||||
STATIC int circuit_extend_add_ed25519_helper(struct extend_cell_t *ec);
|
||||
STATIC int circuit_extend_lspec_valid_helper(const struct extend_cell_t *ec,
|
||||
const struct circuit_t *circ);
|
||||
STATIC void circuit_open_connection_for_extend(const struct extend_cell_t *ec,
|
||||
struct circuit_t *circ,
|
||||
int should_launch);
|
||||
|
||||
#endif /* defined(TOR_UNIT_TESTS) */
|
||||
|
||||
#endif /* !defined(TOR_FEATURE_RELAY_CIRCUITBUILD_RELAY_H) */
|
||||
@@ -8,6 +8,7 @@ LIBTOR_APP_A_SOURCES += \
|
||||
|
||||
# ADD_C_FILE: INSERT SOURCES HERE.
|
||||
MODULE_RELAY_SOURCES = \
|
||||
src/feature/relay/circuitbuild_relay.c \
|
||||
src/feature/relay/dns.c \
|
||||
src/feature/relay/ext_orport.c \
|
||||
src/feature/relay/routermode.c \
|
||||
@@ -21,6 +22,7 @@ MODULE_RELAY_SOURCES = \
|
||||
|
||||
# ADD_C_FILE: INSERT HEADERS HERE.
|
||||
noinst_HEADERS += \
|
||||
src/feature/relay/circuitbuild_relay.h \
|
||||
src/feature/relay/dns.h \
|
||||
src/feature/relay/dns_structs.h \
|
||||
src/feature/relay/ext_orport.h \
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include "core/mainloop/connection.h"
|
||||
#include "core/mainloop/cpuworker.h"
|
||||
#include "core/mainloop/mainloop.h"
|
||||
#include "core/or/circuitbuild.h"
|
||||
#include "core/or/connection_or.h"
|
||||
#include "core/or/port_cfg_st.h"
|
||||
|
||||
@@ -44,6 +43,7 @@
|
||||
#include "feature/dircache/consdiffmgr.h"
|
||||
#include "feature/relay/dns.h"
|
||||
#include "feature/relay/routermode.h"
|
||||
#include "feature/relay/selftest.h"
|
||||
|
||||
/** Contents of most recently read DirPortFrontPage file. */
|
||||
static char *global_dirfrontpagecontents = NULL;
|
||||
|
||||
@@ -213,6 +213,40 @@ router_do_reachability_checks(int test_or, int test_dir)
|
||||
}
|
||||
}
|
||||
|
||||
/** We've decided to start our reachability testing. If all
|
||||
* is set, log this to the user. Return 1 if we did, or 0 if
|
||||
* we chose not to log anything. */
|
||||
int
|
||||
inform_testing_reachability(void)
|
||||
{
|
||||
char dirbuf[128];
|
||||
char *address;
|
||||
const routerinfo_t *me = router_get_my_routerinfo();
|
||||
if (!me)
|
||||
return 0;
|
||||
address = tor_dup_ip(me->addr);
|
||||
control_event_server_status(LOG_NOTICE,
|
||||
"CHECKING_REACHABILITY ORADDRESS=%s:%d",
|
||||
address, me->or_port);
|
||||
if (me->dir_port) {
|
||||
tor_snprintf(dirbuf, sizeof(dirbuf), " and DirPort %s:%d",
|
||||
address, me->dir_port);
|
||||
control_event_server_status(LOG_NOTICE,
|
||||
"CHECKING_REACHABILITY DIRADDRESS=%s:%d",
|
||||
address, me->dir_port);
|
||||
}
|
||||
log_notice(LD_OR, "Now checking whether ORPort %s:%d%s %s reachable... "
|
||||
"(this may take up to %d minutes -- look for log "
|
||||
"messages indicating success)",
|
||||
address, me->or_port,
|
||||
me->dir_port ? dirbuf : "",
|
||||
me->dir_port ? "are" : "is",
|
||||
TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT/60);
|
||||
|
||||
tor_free(address);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Annotate that we found our ORPort reachable. */
|
||||
void
|
||||
router_orport_found_reachable(void)
|
||||
|
||||
@@ -13,14 +13,18 @@
|
||||
#define TOR_SELFTEST_H
|
||||
|
||||
#ifdef HAVE_MODULE_RELAY
|
||||
|
||||
struct or_options_t;
|
||||
int check_whether_orport_reachable(const struct or_options_t *options);
|
||||
int check_whether_dirport_reachable(const struct or_options_t *options);
|
||||
|
||||
void router_do_reachability_checks(int test_or, int test_dir);
|
||||
void router_perform_bandwidth_test(int num_circs, time_t now);
|
||||
int inform_testing_reachability(void);
|
||||
|
||||
void router_orport_found_reachable(void);
|
||||
void router_dirport_found_reachable(void);
|
||||
void router_perform_bandwidth_test(int num_circs, time_t now);
|
||||
|
||||
void router_reset_reachability(void);
|
||||
|
||||
#else /* !defined(HAVE_MODULE_RELAY) */
|
||||
@@ -30,13 +34,6 @@ void router_reset_reachability(void);
|
||||
#define check_whether_dirport_reachable(opts) \
|
||||
((void)(opts), 0)
|
||||
|
||||
#define router_orport_found_reachable() \
|
||||
STMT_NIL
|
||||
#define router_dirport_found_reachable() \
|
||||
STMT_NIL
|
||||
#define router_reset_reachability() \
|
||||
STMT_NIL
|
||||
|
||||
static inline void
|
||||
router_do_reachability_checks(int test_or, int test_dir)
|
||||
{
|
||||
@@ -51,6 +48,20 @@ router_perform_bandwidth_test(int num_circs, time_t now)
|
||||
(void)now;
|
||||
tor_assert_nonfatal_unreached();
|
||||
}
|
||||
static inline int
|
||||
inform_testing_reachability(void)
|
||||
{
|
||||
tor_assert_nonfatal_unreached();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define router_orport_found_reachable() \
|
||||
STMT_NIL
|
||||
#define router_dirport_found_reachable() \
|
||||
STMT_NIL
|
||||
|
||||
#define router_reset_reachability() \
|
||||
STMT_NIL
|
||||
|
||||
#endif /* defined(HAVE_MODULE_RELAY) */
|
||||
|
||||
|
||||
+1077
-8
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user