aboutsummaryrefslogtreecommitdiff
path: root/src/core/or/onion.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/or/onion.c')
-rw-r--r--src/core/or/onion.c53
1 files changed, 41 insertions, 12 deletions
diff --git a/src/core/or/onion.c b/src/core/or/onion.c
index aeddedd807..a3b5c6922d 100644
--- a/src/core/or/onion.c
+++ b/src/core/or/onion.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -240,11 +240,21 @@ created_cell_parse(created_cell_t *cell_out, const cell_t *cell_in)
static int
check_extend_cell(const extend_cell_t *cell)
{
+ const bool is_extend2 = (cell->cell_type == RELAY_COMMAND_EXTEND2);
+
if (tor_digest_is_zero((const char*)cell->node_id))
return -1;
- /* We don't currently allow EXTEND2 cells without an IPv4 address */
- if (tor_addr_family(&cell->orport_ipv4.addr) == AF_UNSPEC)
- return -1;
+ if (!tor_addr_port_is_valid_ap(&cell->orport_ipv4, 0)) {
+ /* EXTEND cells must have an IPv4 address. */
+ if (!is_extend2) {
+ return -1;
+ }
+ /* EXTEND2 cells must have at least one IP address.
+ * It can be IPv4 or IPv6. */
+ if (!tor_addr_port_is_valid_ap(&cell->orport_ipv6, 0)) {
+ return -1;
+ }
+ }
if (cell->create_cell.cell_type == CELL_CREATE) {
if (cell->cell_type != RELAY_COMMAND_EXTEND)
return -1;
@@ -343,7 +353,7 @@ extend_cell_from_extend2_cell_body(extend_cell_t *cell_out,
continue;
found_ipv6 = 1;
tor_addr_from_ipv6_bytes(&cell_out->orport_ipv6.addr,
- (const char *)ls->un_ipv6_addr);
+ ls->un_ipv6_addr);
cell_out->orport_ipv6.port = ls->un_ipv6_port;
break;
case LS_LEGACY_ID:
@@ -364,7 +374,12 @@ extend_cell_from_extend2_cell_body(extend_cell_t *cell_out,
}
}
- if (!found_rsa_id || !found_ipv4) /* These are mandatory */
+ /* EXTEND2 cells must have an RSA ID */
+ if (!found_rsa_id)
+ return -1;
+
+ /* EXTEND2 cells must have at least one IP address */
+ if (!found_ipv4 && !found_ipv6)
return -1;
return create_cell_from_create2_cell_body(&cell_out->create_cell,
@@ -374,9 +389,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);
@@ -618,12 +635,13 @@ extend_cell_format(uint8_t *command_out, uint16_t *len_out,
break;
case RELAY_COMMAND_EXTEND2:
{
- uint8_t n_specifiers = 2;
+ uint8_t n_specifiers = 1;
*command_out = RELAY_COMMAND_EXTEND2;
extend2_cell_body_t *cell = extend2_cell_body_new();
link_specifier_t *ls;
- {
- /* IPv4 specifier first. */
+ if (tor_addr_port_is_valid_ap(&cell_in->orport_ipv4, 0)) {
+ /* Maybe IPv4 specifier first. */
+ ++n_specifiers;
ls = link_specifier_new();
extend2_cell_body_add_ls(cell, ls);
ls->ls_type = LS_IPV4;
@@ -649,6 +667,17 @@ extend_cell_format(uint8_t *command_out, uint16_t *len_out,
ls->ls_len = 32;
memcpy(ls->un_ed25519_id, cell_in->ed_pubkey.pubkey, 32);
}
+ if (tor_addr_port_is_valid_ap(&cell_in->orport_ipv6, 0)) {
+ /* Then maybe IPv6 specifier. */
+ ++n_specifiers;
+ ls = link_specifier_new();
+ extend2_cell_body_add_ls(cell, ls);
+ ls->ls_type = LS_IPV6;
+ ls->ls_len = 18;
+ tor_addr_copy_ipv6_bytes(ls->un_ipv6_addr,
+ &cell_in->orport_ipv6.addr);
+ ls->un_ipv6_port = cell_in->orport_ipv6.port;
+ }
cell->n_spec = n_specifiers;
/* Now, the handshake */