mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-13 22:53:44 +01:00
core/or: Support IPv6 EXTEND2 cells
Allow clients and relays to send dual-stack and IPv6-only EXTEND2 cells. Parse dual-stack and IPv6-only EXTEND2 cells on relays. Relays do not make connections or extend circuits via IPv6: that's the next step. Closes ticket 33901.
This commit is contained in:
parent
3253c357ee
commit
bd6ab90ad4
4
changes/ticket33901
Normal file
4
changes/ticket33901
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
o Minor features (IPv6, relay):
|
||||||
|
- Allow clients and relays to send dual-stack and IPv6-only EXTEND2 cells.
|
||||||
|
Parse dual-stack and IPv6-only EXTEND2 cells on relays.
|
||||||
|
Closes ticket 33901.
|
@ -240,11 +240,21 @@ created_cell_parse(created_cell_t *cell_out, const cell_t *cell_in)
|
|||||||
static int
|
static int
|
||||||
check_extend_cell(const extend_cell_t *cell)
|
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))
|
if (tor_digest_is_zero((const char*)cell->node_id))
|
||||||
return -1;
|
return -1;
|
||||||
/* We don't currently allow EXTEND2 cells without an IPv4 address */
|
if (tor_addr_family(&cell->orport_ipv4.addr) == AF_UNSPEC) {
|
||||||
if (tor_addr_family(&cell->orport_ipv4.addr) == AF_UNSPEC)
|
/* EXTEND cells must have an IPv4 address. */
|
||||||
|
if (!is_extend2) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
/* EXTEND2 cells must have at least one IP address.
|
||||||
|
* It can be IPv4 or IPv6. */
|
||||||
|
if (tor_addr_family(&cell->orport_ipv6.addr) == AF_UNSPEC) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (cell->create_cell.cell_type == CELL_CREATE) {
|
if (cell->create_cell.cell_type == CELL_CREATE) {
|
||||||
if (cell->cell_type != RELAY_COMMAND_EXTEND)
|
if (cell->cell_type != RELAY_COMMAND_EXTEND)
|
||||||
return -1;
|
return -1;
|
||||||
@ -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 -1;
|
||||||
|
|
||||||
return create_cell_from_create2_cell_body(&cell_out->create_cell,
|
return create_cell_from_create2_cell_body(&cell_out->create_cell,
|
||||||
@ -620,12 +635,13 @@ extend_cell_format(uint8_t *command_out, uint16_t *len_out,
|
|||||||
break;
|
break;
|
||||||
case RELAY_COMMAND_EXTEND2:
|
case RELAY_COMMAND_EXTEND2:
|
||||||
{
|
{
|
||||||
uint8_t n_specifiers = 2;
|
uint8_t n_specifiers = 1;
|
||||||
*command_out = RELAY_COMMAND_EXTEND2;
|
*command_out = RELAY_COMMAND_EXTEND2;
|
||||||
extend2_cell_body_t *cell = extend2_cell_body_new();
|
extend2_cell_body_t *cell = extend2_cell_body_new();
|
||||||
link_specifier_t *ls;
|
link_specifier_t *ls;
|
||||||
{
|
if (tor_addr_port_is_valid_ap(&cell_in->orport_ipv4, 0)) {
|
||||||
/* IPv4 specifier first. */
|
/* Maybe IPv4 specifier first. */
|
||||||
|
++n_specifiers;
|
||||||
ls = link_specifier_new();
|
ls = link_specifier_new();
|
||||||
extend2_cell_body_add_ls(cell, ls);
|
extend2_cell_body_add_ls(cell, ls);
|
||||||
ls->ls_type = LS_IPV4;
|
ls->ls_type = LS_IPV4;
|
||||||
@ -651,6 +667,17 @@ extend_cell_format(uint8_t *command_out, uint16_t *len_out,
|
|||||||
ls->ls_len = 32;
|
ls->ls_len = 32;
|
||||||
memcpy(ls->un_ed25519_id, cell_in->ed_pubkey.pubkey, 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_get_ipv6_bytes((char *)ls->un_ipv6_addr,
|
||||||
|
&cell_in->orport_ipv6.addr);
|
||||||
|
ls->un_ipv6_port = cell_in->orport_ipv6.port;
|
||||||
|
}
|
||||||
cell->n_spec = n_specifiers;
|
cell->n_spec = n_specifiers;
|
||||||
|
|
||||||
/* Now, the handshake */
|
/* Now, the handshake */
|
||||||
|
@ -903,6 +903,20 @@ tor_addr_from_in6(tor_addr_t *dest, const struct in6_addr *in6)
|
|||||||
tor_addr_from_ipv6_bytes(dest, (const char*)in6->s6_addr);
|
tor_addr_from_ipv6_bytes(dest, (const char*)in6->s6_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Set the 16 bytes at <b>dest</b> to equal the IPv6 address <b>src</b>.
|
||||||
|
* <b>src</b> must be an IPv6 address, if it is not, log a warning, and clear
|
||||||
|
* <b>dest</b>. */
|
||||||
|
void
|
||||||
|
tor_addr_get_ipv6_bytes(char *dest, const tor_addr_t *src)
|
||||||
|
{
|
||||||
|
tor_assert(dest);
|
||||||
|
tor_assert(src);
|
||||||
|
memset(dest, 0, 16);
|
||||||
|
IF_BUG_ONCE(src->family != AF_INET6)
|
||||||
|
return;
|
||||||
|
memcpy(dest, src->addr.in6_addr.s6_addr, 16);
|
||||||
|
}
|
||||||
|
|
||||||
/** Copy a tor_addr_t from <b>src</b> to <b>dest</b>.
|
/** Copy a tor_addr_t from <b>src</b> to <b>dest</b>.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
|
@ -303,6 +303,7 @@ void tor_addr_from_ipv6_bytes(tor_addr_t *dest, const char *bytes);
|
|||||||
#define tor_addr_from_in(dest, in) \
|
#define tor_addr_from_in(dest, in) \
|
||||||
tor_addr_from_ipv4n((dest), (in)->s_addr);
|
tor_addr_from_ipv4n((dest), (in)->s_addr);
|
||||||
void tor_addr_from_in6(tor_addr_t *dest, const struct in6_addr *in6);
|
void tor_addr_from_in6(tor_addr_t *dest, const struct in6_addr *in6);
|
||||||
|
void tor_addr_get_ipv6_bytes(char *dest, const tor_addr_t *src);
|
||||||
|
|
||||||
int tor_addr_is_null(const tor_addr_t *addr);
|
int tor_addr_is_null(const tor_addr_t *addr);
|
||||||
int tor_addr_is_loopback(const tor_addr_t *addr);
|
int tor_addr_is_loopback(const tor_addr_t *addr);
|
||||||
|
@ -713,16 +713,20 @@ test_cfmt_extend_cells(void *arg)
|
|||||||
tt_mem_op(cc->onionskin,OP_EQ, b, 99+20);
|
tt_mem_op(cc->onionskin,OP_EQ, b, 99+20);
|
||||||
tt_int_op(0, OP_EQ, extend_cell_format(&p2_cmd, &p2_len, p2, &ec));
|
tt_int_op(0, OP_EQ, extend_cell_format(&p2_cmd, &p2_len, p2, &ec));
|
||||||
tt_int_op(p2_cmd, OP_EQ, RELAY_COMMAND_EXTEND2);
|
tt_int_op(p2_cmd, OP_EQ, RELAY_COMMAND_EXTEND2);
|
||||||
/* We'll generate it minus the IPv6 address and minus the konami code */
|
/* We'll generate it minus the konami code */
|
||||||
tt_int_op(p2_len, OP_EQ, 89+99-34-20);
|
tt_int_op(p2_len, OP_EQ, 89+99-34);
|
||||||
test_memeq_hex(p2,
|
test_memeq_hex(p2,
|
||||||
/* Two items: one that same darn IP address. */
|
/* Three items */
|
||||||
"02000612F40001F0F1"
|
"03"
|
||||||
/* The next is a digest : anthropomorphization */
|
/* IPv4 address */
|
||||||
"0214616e7468726f706f6d6f727068697a6174696f6e"
|
"0006" "12F40001" "F0F1"
|
||||||
|
/* The next is an RSA digest: anthropomorphization */
|
||||||
|
"0214" "616e7468726f706f6d6f727068697a6174696f6e"
|
||||||
|
/*IPv6 address */
|
||||||
|
"0112" "20020000000000000000000000f0c51e" "1112"
|
||||||
/* Now the handshake prologue */
|
/* Now the handshake prologue */
|
||||||
"01050063");
|
"01050063");
|
||||||
tt_mem_op(p2+1+8+22+4,OP_EQ, b, 99+20);
|
tt_mem_op(p2+1+8+22+20+4, OP_EQ, b, 99+20);
|
||||||
tt_int_op(0, OP_EQ, create_cell_format_relayed(&cell, cc));
|
tt_int_op(0, OP_EQ, create_cell_format_relayed(&cell, cc));
|
||||||
|
|
||||||
/* Now let's add an ed25519 key to that extend2 cell. */
|
/* Now let's add an ed25519 key to that extend2 cell. */
|
||||||
@ -732,22 +736,31 @@ test_cfmt_extend_cells(void *arg)
|
|||||||
/* As before, since we aren't extending by ed25519. */
|
/* As before, since we aren't extending by ed25519. */
|
||||||
get_options_mutable()->ExtendByEd25519ID = 0;
|
get_options_mutable()->ExtendByEd25519ID = 0;
|
||||||
tt_int_op(0, OP_EQ, extend_cell_format(&p2_cmd, &p2_len, p2, &ec));
|
tt_int_op(0, OP_EQ, extend_cell_format(&p2_cmd, &p2_len, p2, &ec));
|
||||||
tt_int_op(p2_len, OP_EQ, 89+99-34-20);
|
tt_int_op(p2_len, OP_EQ, 89+99-34);
|
||||||
test_memeq_hex(p2,
|
test_memeq_hex(p2,
|
||||||
"02000612F40001F0F1"
|
"03"
|
||||||
|
"000612F40001F0F1"
|
||||||
"0214616e7468726f706f6d6f727068697a6174696f6e"
|
"0214616e7468726f706f6d6f727068697a6174696f6e"
|
||||||
|
"011220020000000000000000000000f0c51e1112"
|
||||||
"01050063");
|
"01050063");
|
||||||
|
|
||||||
/* Now try with the ed25519 ID. */
|
/* Now try with the ed25519 ID. */
|
||||||
get_options_mutable()->ExtendByEd25519ID = 1;
|
get_options_mutable()->ExtendByEd25519ID = 1;
|
||||||
tt_int_op(0, OP_EQ, extend_cell_format(&p2_cmd, &p2_len, p2, &ec));
|
tt_int_op(0, OP_EQ, extend_cell_format(&p2_cmd, &p2_len, p2, &ec));
|
||||||
tt_int_op(p2_len, OP_EQ, 89+99-34-20 + 34);
|
tt_int_op(p2_len, OP_EQ, 89+99);
|
||||||
test_memeq_hex(p2,
|
test_memeq_hex(p2,
|
||||||
"03000612F40001F0F1"
|
/* Four items */
|
||||||
|
"04"
|
||||||
|
/* IPv4 address */
|
||||||
|
"0006" "12F40001" "F0F1"
|
||||||
|
/* The next is an RSA digest: anthropomorphization */
|
||||||
"0214616e7468726f706f6d6f727068697a6174696f6e"
|
"0214616e7468726f706f6d6f727068697a6174696f6e"
|
||||||
// ed digest follows:
|
/* Then an ed public key: brownshoesdontmakeit/brownshoesd */
|
||||||
"0320" "62726f776e73686f6573646f6e746d616b656"
|
"0320" "62726f776e73686f6573646f6e746d616b656"
|
||||||
"9742f62726f776e73686f657364"
|
"9742f62726f776e73686f657364"
|
||||||
|
/*IPv6 address */
|
||||||
|
"0112" "20020000000000000000000000f0c51e" "1112"
|
||||||
|
/* Now the handshake prologue */
|
||||||
"01050063");
|
"01050063");
|
||||||
/* Can we parse that? Did the key come through right? */
|
/* Can we parse that? Did the key come through right? */
|
||||||
memset(&ec, 0, sizeof(ec));
|
memset(&ec, 0, sizeof(ec));
|
||||||
@ -816,7 +829,7 @@ test_cfmt_extend_cells(void *arg)
|
|||||||
memcpy(p+1, "\x02\x14" "anarchoindividualist", 22);
|
memcpy(p+1, "\x02\x14" "anarchoindividualist", 22);
|
||||||
memcpy(p+23, "\x01\x12" "xxxxxxxxxxxxxxxxYY", 18);
|
memcpy(p+23, "\x01\x12" "xxxxxxxxxxxxxxxxYY", 18);
|
||||||
memcpy(p+41, "\xff\xff\x00\x20", 4);
|
memcpy(p+41, "\xff\xff\x00\x20", 4);
|
||||||
tt_int_op(-1, OP_EQ, extend_cell_parse(&ec, RELAY_COMMAND_EXTEND2,
|
tt_int_op(0, OP_EQ, extend_cell_parse(&ec, RELAY_COMMAND_EXTEND2,
|
||||||
p, sizeof(p)));
|
p, sizeof(p)));
|
||||||
|
|
||||||
/* Running out of space in specifiers */
|
/* Running out of space in specifiers */
|
||||||
|
Loading…
Reference in New Issue
Block a user