diff options
Diffstat (limited to 'src/core/or/onion.c')
-rw-r--r-- | src/core/or/onion.c | 53 |
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 */ |