2020-01-08 18:39:17 -05:00
|
|
|
/* Copyright (c) 2016-2020, The Tor Project, Inc. */
|
2016-08-09 19:11:47 -04:00
|
|
|
/* See LICENSE for licensing information */
|
|
|
|
|
|
|
|
#define PROTOVER_PRIVATE
|
2020-02-12 22:07:26 +10:00
|
|
|
#define DIRVOTE_PRIVATE
|
2016-08-09 19:11:47 -04:00
|
|
|
|
|
|
|
#include "orconfig.h"
|
2018-06-20 09:35:05 -04:00
|
|
|
#include "test/test.h"
|
2016-08-09 19:11:47 -04:00
|
|
|
|
2020-05-15 23:21:13 +10:00
|
|
|
#include "lib/tls/tortls.h"
|
2016-08-09 19:11:47 -04:00
|
|
|
|
2018-07-05 16:34:59 -04:00
|
|
|
#include "core/or/or.h"
|
2020-05-15 23:21:13 +10:00
|
|
|
|
2018-07-05 16:34:59 -04:00
|
|
|
#include "core/or/connection_or.h"
|
2020-05-15 23:21:13 +10:00
|
|
|
#include "core/or/protover.h"
|
|
|
|
#include "core/or/versions.h"
|
2018-01-30 01:53:41 +11:00
|
|
|
|
2020-02-12 22:07:26 +10:00
|
|
|
#include "feature/dirauth/dirvote.h"
|
|
|
|
|
2020-05-15 14:59:10 +10:00
|
|
|
#include "feature/relay/relay_handshake.h"
|
|
|
|
|
2016-08-09 19:11:47 -04:00
|
|
|
static void
|
|
|
|
test_protover_parse(void *arg)
|
|
|
|
{
|
|
|
|
(void) arg;
|
2017-09-27 19:48:07 +00:00
|
|
|
#ifdef HAVE_RUST
|
|
|
|
/** This test is disabled on rust builds, because it only exists to test
|
|
|
|
* internal C functions. */
|
|
|
|
tt_skip();
|
|
|
|
done:
|
|
|
|
;
|
2019-09-30 08:57:37 -04:00
|
|
|
#else /* !defined(HAVE_RUST) */
|
2016-08-09 19:11:47 -04:00
|
|
|
char *re_encoded = NULL;
|
|
|
|
|
|
|
|
const char *orig = "Foo=1,3 Bar=3 Baz= Quux=9-12,14,15-16,900";
|
|
|
|
smartlist_t *elts = parse_protocol_list(orig);
|
|
|
|
|
|
|
|
tt_assert(elts);
|
|
|
|
tt_int_op(smartlist_len(elts), OP_EQ, 4);
|
|
|
|
|
|
|
|
const proto_entry_t *e;
|
|
|
|
const proto_range_t *r;
|
|
|
|
e = smartlist_get(elts, 0);
|
|
|
|
tt_str_op(e->name, OP_EQ, "Foo");
|
|
|
|
tt_int_op(smartlist_len(e->ranges), OP_EQ, 2);
|
|
|
|
{
|
|
|
|
r = smartlist_get(e->ranges, 0);
|
|
|
|
tt_int_op(r->low, OP_EQ, 1);
|
|
|
|
tt_int_op(r->high, OP_EQ, 1);
|
|
|
|
|
|
|
|
r = smartlist_get(e->ranges, 1);
|
|
|
|
tt_int_op(r->low, OP_EQ, 3);
|
|
|
|
tt_int_op(r->high, OP_EQ, 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
e = smartlist_get(elts, 1);
|
|
|
|
tt_str_op(e->name, OP_EQ, "Bar");
|
|
|
|
tt_int_op(smartlist_len(e->ranges), OP_EQ, 1);
|
|
|
|
{
|
|
|
|
r = smartlist_get(e->ranges, 0);
|
|
|
|
tt_int_op(r->low, OP_EQ, 3);
|
|
|
|
tt_int_op(r->high, OP_EQ, 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
e = smartlist_get(elts, 2);
|
|
|
|
tt_str_op(e->name, OP_EQ, "Baz");
|
|
|
|
tt_int_op(smartlist_len(e->ranges), OP_EQ, 0);
|
|
|
|
|
|
|
|
e = smartlist_get(elts, 3);
|
|
|
|
tt_str_op(e->name, OP_EQ, "Quux");
|
|
|
|
tt_int_op(smartlist_len(e->ranges), OP_EQ, 4);
|
|
|
|
{
|
|
|
|
r = smartlist_get(e->ranges, 0);
|
|
|
|
tt_int_op(r->low, OP_EQ, 9);
|
|
|
|
tt_int_op(r->high, OP_EQ, 12);
|
|
|
|
|
|
|
|
r = smartlist_get(e->ranges, 1);
|
|
|
|
tt_int_op(r->low, OP_EQ, 14);
|
|
|
|
tt_int_op(r->high, OP_EQ, 14);
|
|
|
|
|
|
|
|
r = smartlist_get(e->ranges, 2);
|
|
|
|
tt_int_op(r->low, OP_EQ, 15);
|
|
|
|
tt_int_op(r->high, OP_EQ, 16);
|
|
|
|
|
|
|
|
r = smartlist_get(e->ranges, 3);
|
|
|
|
tt_int_op(r->low, OP_EQ, 900);
|
|
|
|
tt_int_op(r->high, OP_EQ, 900);
|
|
|
|
}
|
|
|
|
|
|
|
|
re_encoded = encode_protocol_list(elts);
|
|
|
|
tt_assert(re_encoded);
|
|
|
|
tt_str_op(re_encoded, OP_EQ, orig);
|
|
|
|
|
|
|
|
done:
|
|
|
|
if (elts)
|
|
|
|
SMARTLIST_FOREACH(elts, proto_entry_t *, ent, proto_entry_free(ent));
|
|
|
|
smartlist_free(elts);
|
|
|
|
tor_free(re_encoded);
|
2019-06-05 09:33:35 -04:00
|
|
|
#endif /* defined(HAVE_RUST) */
|
2016-08-09 19:11:47 -04:00
|
|
|
}
|
|
|
|
|
2016-08-23 14:02:48 -04:00
|
|
|
static void
|
|
|
|
test_protover_parse_fail(void *arg)
|
|
|
|
{
|
|
|
|
(void)arg;
|
2017-09-27 19:48:07 +00:00
|
|
|
#ifdef HAVE_RUST
|
|
|
|
/** This test is disabled on rust builds, because it only exists to test
|
|
|
|
* internal C functions. */
|
|
|
|
tt_skip();
|
|
|
|
#else
|
2016-08-23 14:02:48 -04:00
|
|
|
smartlist_t *elts;
|
|
|
|
|
|
|
|
/* random junk */
|
|
|
|
elts = parse_protocol_list("!!3@*");
|
2017-08-24 15:55:27 -04:00
|
|
|
tt_ptr_op(elts, OP_EQ, NULL);
|
2016-08-23 14:02:48 -04:00
|
|
|
|
|
|
|
/* Missing equals sign in an entry */
|
|
|
|
elts = parse_protocol_list("Link=4 Haprauxymatyve Desc=9");
|
2017-08-24 15:55:27 -04:00
|
|
|
tt_ptr_op(elts, OP_EQ, NULL);
|
2016-08-23 14:02:48 -04:00
|
|
|
|
|
|
|
/* Missing word. */
|
|
|
|
elts = parse_protocol_list("Link=4 =3 Desc=9");
|
2017-08-24 15:55:27 -04:00
|
|
|
tt_ptr_op(elts, OP_EQ, NULL);
|
2016-08-23 14:02:48 -04:00
|
|
|
|
|
|
|
/* Broken numbers */
|
|
|
|
elts = parse_protocol_list("Link=fred");
|
2017-08-24 15:55:27 -04:00
|
|
|
tt_ptr_op(elts, OP_EQ, NULL);
|
2016-08-23 14:02:48 -04:00
|
|
|
elts = parse_protocol_list("Link=1,fred");
|
2017-08-24 15:55:27 -04:00
|
|
|
tt_ptr_op(elts, OP_EQ, NULL);
|
2016-08-23 14:02:48 -04:00
|
|
|
elts = parse_protocol_list("Link=1,fred,3");
|
2017-08-24 15:55:27 -04:00
|
|
|
tt_ptr_op(elts, OP_EQ, NULL);
|
2016-08-23 14:02:48 -04:00
|
|
|
|
|
|
|
/* Broken range */
|
|
|
|
elts = parse_protocol_list("Link=1,9-8,3");
|
2017-08-24 15:55:27 -04:00
|
|
|
tt_ptr_op(elts, OP_EQ, NULL);
|
protover: TROVE-2018-005 Fix potential DoS in protover protocol parsing.
In protover.c, the `expand_protocol_list()` function expands a `smartlist_t` of
`proto_entry_t`s to their protocol name concatenated with each version number.
For example, given a `proto_entry_t` like so:
proto_entry_t *proto = tor_malloc(sizeof(proto_entry_t));
proto_range_t *range = tor_malloc_zero(sizeof(proto_range_t));
proto->name = tor_strdup("DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa");
proto->ranges = smartlist_new();
range->low = 1;
range->high = 65536;
smartlist_add(proto->ranges, range);
(Where `[19KB]` is roughly 19KB of `"a"` bytes.) This would expand in
`expand_protocol_list()` to a `smartlist_t` containing 65536 copies of the
string, e.g.:
"DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=1"
"DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=2"
[…]
"DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=65535"
Thus constituting a potential resource exhaustion attack.
The Rust implementation is not subject to this attack, because it instead
expands the above string into a `HashMap<String, HashSet<u32>` prior to #24031,
and a `HashMap<UnvalidatedProtocol, ProtoSet>` after). Neither Rust version is
subject to this attack, because it only stores the `String` once per protocol.
(Although a related, but apparently of too minor impact to be usable, DoS bug
has been fixed in #24031. [0])
[0]: https://bugs.torproject.org/24031
* ADDS hard limit on protocol name lengths in protover.c and checks in
parse_single_entry() and expand_protocol_list().
* ADDS tests to ensure the bug is caught.
* FIXES #25517: https://bugs.torproject.org/25517
2018-03-29 01:54:05 +00:00
|
|
|
|
|
|
|
/* Protocol name too long */
|
|
|
|
elts = parse_protocol_list("DoSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
2018-05-22 12:32:00 -04:00
|
|
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
|
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
|
protover: TROVE-2018-005 Fix potential DoS in protover protocol parsing.
In protover.c, the `expand_protocol_list()` function expands a `smartlist_t` of
`proto_entry_t`s to their protocol name concatenated with each version number.
For example, given a `proto_entry_t` like so:
proto_entry_t *proto = tor_malloc(sizeof(proto_entry_t));
proto_range_t *range = tor_malloc_zero(sizeof(proto_range_t));
proto->name = tor_strdup("DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa");
proto->ranges = smartlist_new();
range->low = 1;
range->high = 65536;
smartlist_add(proto->ranges, range);
(Where `[19KB]` is roughly 19KB of `"a"` bytes.) This would expand in
`expand_protocol_list()` to a `smartlist_t` containing 65536 copies of the
string, e.g.:
"DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=1"
"DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=2"
[…]
"DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=65535"
Thus constituting a potential resource exhaustion attack.
The Rust implementation is not subject to this attack, because it instead
expands the above string into a `HashMap<String, HashSet<u32>` prior to #24031,
and a `HashMap<UnvalidatedProtocol, ProtoSet>` after). Neither Rust version is
subject to this attack, because it only stores the `String` once per protocol.
(Although a related, but apparently of too minor impact to be usable, DoS bug
has been fixed in #24031. [0])
[0]: https://bugs.torproject.org/24031
* ADDS hard limit on protocol name lengths in protover.c and checks in
parse_single_entry() and expand_protocol_list().
* ADDS tests to ensure the bug is caught.
* FIXES #25517: https://bugs.torproject.org/25517
2018-03-29 01:54:05 +00:00
|
|
|
tt_ptr_op(elts, OP_EQ, NULL);
|
|
|
|
|
2019-06-05 09:33:35 -04:00
|
|
|
#endif /* defined(HAVE_RUST) */
|
2016-08-23 14:02:48 -04:00
|
|
|
done:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
2016-08-19 18:04:02 -04:00
|
|
|
static void
|
|
|
|
test_protover_vote(void *arg)
|
|
|
|
{
|
|
|
|
(void) arg;
|
|
|
|
|
|
|
|
smartlist_t *lst = smartlist_new();
|
2016-09-12 14:11:44 -04:00
|
|
|
char *result = protover_compute_vote(lst, 1);
|
2016-08-19 18:04:02 -04:00
|
|
|
|
|
|
|
tt_str_op(result, OP_EQ, "");
|
|
|
|
tor_free(result);
|
|
|
|
|
|
|
|
smartlist_add(lst, (void*) "Foo=1-10,500 Bar=1,3-7,8");
|
2016-09-12 14:11:44 -04:00
|
|
|
result = protover_compute_vote(lst, 1);
|
2016-08-19 18:04:02 -04:00
|
|
|
tt_str_op(result, OP_EQ, "Bar=1,3-8 Foo=1-10,500");
|
|
|
|
tor_free(result);
|
|
|
|
|
|
|
|
smartlist_add(lst, (void*) "Quux=123-456,78 Bar=2-6,8 Foo=9");
|
2016-09-12 14:11:44 -04:00
|
|
|
result = protover_compute_vote(lst, 1);
|
2016-08-19 18:04:02 -04:00
|
|
|
tt_str_op(result, OP_EQ, "Bar=1-8 Foo=1-10,500 Quux=78,123-456");
|
|
|
|
tor_free(result);
|
|
|
|
|
2016-09-12 14:11:44 -04:00
|
|
|
result = protover_compute_vote(lst, 2);
|
2016-08-19 18:04:02 -04:00
|
|
|
tt_str_op(result, OP_EQ, "Bar=3-6,8 Foo=9");
|
|
|
|
tor_free(result);
|
|
|
|
|
2018-02-14 11:56:03 -05:00
|
|
|
/* High threshold */
|
|
|
|
result = protover_compute_vote(lst, 3);
|
|
|
|
tt_str_op(result, OP_EQ, "");
|
|
|
|
tor_free(result);
|
|
|
|
|
2018-08-18 18:15:59 +00:00
|
|
|
/* Don't count double-voting. */
|
|
|
|
smartlist_clear(lst);
|
|
|
|
smartlist_add(lst, (void*) "Foo=1 Foo=1");
|
|
|
|
smartlist_add(lst, (void*) "Bar=1-2,2-3");
|
|
|
|
result = protover_compute_vote(lst, 2);
|
|
|
|
tt_str_op(result, OP_EQ, "");
|
|
|
|
tor_free(result);
|
|
|
|
|
2018-02-14 11:56:03 -05:00
|
|
|
/* Bad votes: the result must be empty */
|
|
|
|
smartlist_clear(lst);
|
|
|
|
smartlist_add(lst, (void*) "Faux=10-5");
|
|
|
|
result = protover_compute_vote(lst, 1);
|
|
|
|
tt_str_op(result, OP_EQ, "");
|
|
|
|
tor_free(result);
|
|
|
|
|
2018-02-15 08:46:13 -05:00
|
|
|
/* This fails, since "-0" is not valid. */
|
2018-02-14 11:56:03 -05:00
|
|
|
smartlist_clear(lst);
|
|
|
|
smartlist_add(lst, (void*) "Faux=-0");
|
|
|
|
result = protover_compute_vote(lst, 1);
|
2018-02-15 08:46:13 -05:00
|
|
|
tt_str_op(result, OP_EQ, "");
|
2018-02-14 11:56:03 -05:00
|
|
|
tor_free(result);
|
|
|
|
|
|
|
|
/* Vote large protover lists that are just below the threshold */
|
|
|
|
|
|
|
|
/* Just below the threshold: Rust */
|
|
|
|
smartlist_clear(lst);
|
|
|
|
smartlist_add(lst, (void*) "Sleen=1-500");
|
|
|
|
result = protover_compute_vote(lst, 1);
|
|
|
|
tt_str_op(result, OP_EQ, "Sleen=1-500");
|
|
|
|
tor_free(result);
|
|
|
|
|
|
|
|
/* Just below the threshold: C */
|
|
|
|
smartlist_clear(lst);
|
|
|
|
smartlist_add(lst, (void*) "Sleen=1-65536");
|
|
|
|
result = protover_compute_vote(lst, 1);
|
|
|
|
tt_str_op(result, OP_EQ, "Sleen=1-65536");
|
|
|
|
tor_free(result);
|
|
|
|
|
|
|
|
/* Large protover lists that exceed the threshold */
|
|
|
|
|
|
|
|
/* By adding two votes, C allows us to exceed the limit */
|
|
|
|
smartlist_add(lst, (void*) "Sleen=1-65536");
|
|
|
|
smartlist_add(lst, (void*) "Sleen=100000");
|
|
|
|
result = protover_compute_vote(lst, 1);
|
|
|
|
tt_str_op(result, OP_EQ, "Sleen=1-65536,100000");
|
|
|
|
tor_free(result);
|
|
|
|
|
|
|
|
/* Large integers */
|
|
|
|
smartlist_clear(lst);
|
|
|
|
smartlist_add(lst, (void*) "Sleen=4294967294");
|
|
|
|
result = protover_compute_vote(lst, 1);
|
|
|
|
tt_str_op(result, OP_EQ, "Sleen=4294967294");
|
|
|
|
tor_free(result);
|
|
|
|
|
|
|
|
/* This parses, but fails at the vote stage */
|
|
|
|
smartlist_clear(lst);
|
|
|
|
smartlist_add(lst, (void*) "Sleen=4294967295");
|
|
|
|
result = protover_compute_vote(lst, 1);
|
2018-02-15 18:56:29 -05:00
|
|
|
tt_str_op(result, OP_EQ, "");
|
2018-02-14 11:56:03 -05:00
|
|
|
tor_free(result);
|
|
|
|
|
|
|
|
smartlist_clear(lst);
|
|
|
|
smartlist_add(lst, (void*) "Sleen=4294967296");
|
|
|
|
result = protover_compute_vote(lst, 1);
|
|
|
|
tt_str_op(result, OP_EQ, "");
|
|
|
|
tor_free(result);
|
|
|
|
|
protover: TROVE-2018-005 Fix potential DoS in protover protocol parsing.
In protover.c, the `expand_protocol_list()` function expands a `smartlist_t` of
`proto_entry_t`s to their protocol name concatenated with each version number.
For example, given a `proto_entry_t` like so:
proto_entry_t *proto = tor_malloc(sizeof(proto_entry_t));
proto_range_t *range = tor_malloc_zero(sizeof(proto_range_t));
proto->name = tor_strdup("DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa");
proto->ranges = smartlist_new();
range->low = 1;
range->high = 65536;
smartlist_add(proto->ranges, range);
(Where `[19KB]` is roughly 19KB of `"a"` bytes.) This would expand in
`expand_protocol_list()` to a `smartlist_t` containing 65536 copies of the
string, e.g.:
"DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=1"
"DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=2"
[…]
"DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=65535"
Thus constituting a potential resource exhaustion attack.
The Rust implementation is not subject to this attack, because it instead
expands the above string into a `HashMap<String, HashSet<u32>` prior to #24031,
and a `HashMap<UnvalidatedProtocol, ProtoSet>` after). Neither Rust version is
subject to this attack, because it only stores the `String` once per protocol.
(Although a related, but apparently of too minor impact to be usable, DoS bug
has been fixed in #24031. [0])
[0]: https://bugs.torproject.org/24031
* ADDS hard limit on protocol name lengths in protover.c and checks in
parse_single_entry() and expand_protocol_list().
* ADDS tests to ensure the bug is caught.
* FIXES #25517: https://bugs.torproject.org/25517
2018-03-29 01:54:05 +00:00
|
|
|
/* Protocol name too long */
|
|
|
|
smartlist_clear(lst);
|
|
|
|
smartlist_add(lst, (void*) "DoSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
2018-05-22 12:32:00 -04:00
|
|
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
|
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
|
protover: TROVE-2018-005 Fix potential DoS in protover protocol parsing.
In protover.c, the `expand_protocol_list()` function expands a `smartlist_t` of
`proto_entry_t`s to their protocol name concatenated with each version number.
For example, given a `proto_entry_t` like so:
proto_entry_t *proto = tor_malloc(sizeof(proto_entry_t));
proto_range_t *range = tor_malloc_zero(sizeof(proto_range_t));
proto->name = tor_strdup("DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa");
proto->ranges = smartlist_new();
range->low = 1;
range->high = 65536;
smartlist_add(proto->ranges, range);
(Where `[19KB]` is roughly 19KB of `"a"` bytes.) This would expand in
`expand_protocol_list()` to a `smartlist_t` containing 65536 copies of the
string, e.g.:
"DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=1"
"DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=2"
[…]
"DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=65535"
Thus constituting a potential resource exhaustion attack.
The Rust implementation is not subject to this attack, because it instead
expands the above string into a `HashMap<String, HashSet<u32>` prior to #24031,
and a `HashMap<UnvalidatedProtocol, ProtoSet>` after). Neither Rust version is
subject to this attack, because it only stores the `String` once per protocol.
(Although a related, but apparently of too minor impact to be usable, DoS bug
has been fixed in #24031. [0])
[0]: https://bugs.torproject.org/24031
* ADDS hard limit on protocol name lengths in protover.c and checks in
parse_single_entry() and expand_protocol_list().
* ADDS tests to ensure the bug is caught.
* FIXES #25517: https://bugs.torproject.org/25517
2018-03-29 01:54:05 +00:00
|
|
|
result = protover_compute_vote(lst, 1);
|
|
|
|
tt_str_op(result, OP_EQ, "");
|
|
|
|
tor_free(result);
|
|
|
|
|
2016-08-19 18:04:02 -04:00
|
|
|
done:
|
|
|
|
tor_free(result);
|
|
|
|
smartlist_free(lst);
|
|
|
|
}
|
|
|
|
|
2016-08-23 13:47:14 -04:00
|
|
|
static void
|
|
|
|
test_protover_all_supported(void *arg)
|
|
|
|
{
|
|
|
|
(void)arg;
|
|
|
|
char *msg = NULL;
|
|
|
|
|
|
|
|
tt_assert(protover_all_supported(NULL, &msg));
|
2017-08-24 15:55:27 -04:00
|
|
|
tt_ptr_op(msg, OP_EQ, NULL);
|
2016-08-23 13:47:14 -04:00
|
|
|
|
|
|
|
tt_assert(protover_all_supported("", &msg));
|
2017-08-24 15:55:27 -04:00
|
|
|
tt_ptr_op(msg, OP_EQ, NULL);
|
2016-08-23 13:47:14 -04:00
|
|
|
|
|
|
|
// Some things that we do support
|
|
|
|
tt_assert(protover_all_supported("Link=3-4", &msg));
|
2017-08-24 15:55:27 -04:00
|
|
|
tt_ptr_op(msg, OP_EQ, NULL);
|
2016-08-23 13:47:14 -04:00
|
|
|
tt_assert(protover_all_supported("Link=3-4 Desc=2", &msg));
|
2017-08-24 15:55:27 -04:00
|
|
|
tt_ptr_op(msg, OP_EQ, NULL);
|
2016-08-23 13:47:14 -04:00
|
|
|
|
|
|
|
// Some things we don't support
|
2018-09-21 04:57:26 +00:00
|
|
|
tt_assert(! protover_all_supported("Wombat=9", NULL));
|
2016-08-23 13:47:14 -04:00
|
|
|
tt_assert(! protover_all_supported("Wombat=9", &msg));
|
|
|
|
tt_str_op(msg, OP_EQ, "Wombat=9");
|
|
|
|
tor_free(msg);
|
|
|
|
tt_assert(! protover_all_supported("Link=999", &msg));
|
|
|
|
tt_str_op(msg, OP_EQ, "Link=999");
|
|
|
|
tor_free(msg);
|
|
|
|
|
|
|
|
// Mix of things we support and things we don't
|
|
|
|
tt_assert(! protover_all_supported("Link=3-4 Wombat=9", &msg));
|
|
|
|
tt_str_op(msg, OP_EQ, "Wombat=9");
|
|
|
|
tor_free(msg);
|
2018-03-27 16:59:49 +00:00
|
|
|
|
|
|
|
/* Mix of things we support and don't support within a single protocol
|
|
|
|
* which we do support */
|
2016-08-23 13:47:14 -04:00
|
|
|
tt_assert(! protover_all_supported("Link=3-999", &msg));
|
2018-03-27 16:59:49 +00:00
|
|
|
tt_str_op(msg, OP_EQ, "Link=6-999");
|
|
|
|
tor_free(msg);
|
|
|
|
tt_assert(! protover_all_supported("Link=1-3,345-666", &msg));
|
|
|
|
tt_str_op(msg, OP_EQ, "Link=345-666");
|
|
|
|
tor_free(msg);
|
|
|
|
tt_assert(! protover_all_supported("Link=1-3,5-12", &msg));
|
|
|
|
tt_str_op(msg, OP_EQ, "Link=6-12");
|
|
|
|
tor_free(msg);
|
|
|
|
|
|
|
|
/* Mix of protocols we do support and some we don't, where the protocols
|
|
|
|
* we do support have some versions we don't support. */
|
|
|
|
tt_assert(! protover_all_supported("Link=1-3,5-12 Quokka=9000-9001", &msg));
|
|
|
|
tt_str_op(msg, OP_EQ, "Link=6-12 Quokka=9000-9001");
|
2016-08-23 13:47:14 -04:00
|
|
|
tor_free(msg);
|
|
|
|
|
tests: Make inline comments in test_protover.c more accurate.
The DoS potential is slightly higher in C now due to some differences to the
Rust code, see the C_RUST_DIFFERS tags in src/rust/protover/tests/protover.rs.
Also, the comment about "failing at the splitting stage" in Rust wasn't true,
since when we split, we ignore empty chunks (e.g. "1--1" parses into
"(1,None),(None,1)" and "None" can't be parsed into an integer).
Finally, the comment about "Rust seems to experience an internal error" is only
true in debug mode, where u32s are bounds-checked at runtime. In release mode,
code expressing the equivalent of this test will error with
`Err(ProtoverError::Unparseable)` because 4294967295 is too large.
2018-03-27 21:34:00 +00:00
|
|
|
/* We shouldn't be able to DoS ourselves parsing a large range. */
|
2018-08-18 16:54:09 +00:00
|
|
|
tt_assert(! protover_all_supported("Sleen=1-2147483648", &msg));
|
|
|
|
tt_str_op(msg, OP_EQ, "Sleen=1-2147483648");
|
2018-02-14 11:56:03 -05:00
|
|
|
tor_free(msg);
|
|
|
|
|
2018-02-15 09:05:55 -05:00
|
|
|
/* This case is allowed. */
|
2018-08-18 16:54:09 +00:00
|
|
|
tt_assert(! protover_all_supported("Sleen=1-4294967294", &msg));
|
|
|
|
tt_str_op(msg, OP_EQ, "Sleen=1-4294967294");
|
2018-02-14 11:56:03 -05:00
|
|
|
tor_free(msg);
|
|
|
|
|
2018-03-27 21:36:10 +00:00
|
|
|
/* If we get a (barely) valid (but unsupported list, we say "yes, that's
|
|
|
|
* supported." */
|
|
|
|
tt_assert(protover_all_supported("Fribble=", &msg));
|
|
|
|
tt_ptr_op(msg, OP_EQ, NULL);
|
|
|
|
|
2020-03-06 19:09:50 +02:00
|
|
|
#ifndef ALL_BUGS_ARE_FATAL
|
2018-03-27 21:36:10 +00:00
|
|
|
/* If we get a completely unparseable list, protover_all_supported should
|
|
|
|
* hit a fatal assertion for BUG(entries == NULL). */
|
2018-02-15 09:05:55 -05:00
|
|
|
tor_capture_bugs_(1);
|
|
|
|
tt_assert(protover_all_supported("Fribble", &msg));
|
|
|
|
tor_end_capture_bugs_();
|
|
|
|
|
2018-03-27 21:36:10 +00:00
|
|
|
/* If we get a completely unparseable list, protover_all_supported should
|
|
|
|
* hit a fatal assertion for BUG(entries == NULL). */
|
2018-02-15 09:05:55 -05:00
|
|
|
tor_capture_bugs_(1);
|
2018-08-18 16:54:09 +00:00
|
|
|
tt_assert(protover_all_supported("Sleen=1-4294967295", &msg));
|
2018-02-15 09:05:55 -05:00
|
|
|
tor_end_capture_bugs_();
|
2020-03-06 19:09:50 +02:00
|
|
|
#endif /* !defined(ALL_BUGS_ARE_FATAL) */
|
2018-02-15 09:05:55 -05:00
|
|
|
|
protover: TROVE-2018-005 Fix potential DoS in protover protocol parsing.
In protover.c, the `expand_protocol_list()` function expands a `smartlist_t` of
`proto_entry_t`s to their protocol name concatenated with each version number.
For example, given a `proto_entry_t` like so:
proto_entry_t *proto = tor_malloc(sizeof(proto_entry_t));
proto_range_t *range = tor_malloc_zero(sizeof(proto_range_t));
proto->name = tor_strdup("DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa");
proto->ranges = smartlist_new();
range->low = 1;
range->high = 65536;
smartlist_add(proto->ranges, range);
(Where `[19KB]` is roughly 19KB of `"a"` bytes.) This would expand in
`expand_protocol_list()` to a `smartlist_t` containing 65536 copies of the
string, e.g.:
"DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=1"
"DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=2"
[…]
"DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=65535"
Thus constituting a potential resource exhaustion attack.
The Rust implementation is not subject to this attack, because it instead
expands the above string into a `HashMap<String, HashSet<u32>` prior to #24031,
and a `HashMap<UnvalidatedProtocol, ProtoSet>` after). Neither Rust version is
subject to this attack, because it only stores the `String` once per protocol.
(Although a related, but apparently of too minor impact to be usable, DoS bug
has been fixed in #24031. [0])
[0]: https://bugs.torproject.org/24031
* ADDS hard limit on protocol name lengths in protover.c and checks in
parse_single_entry() and expand_protocol_list().
* ADDS tests to ensure the bug is caught.
* FIXES #25517: https://bugs.torproject.org/25517
2018-03-29 01:54:05 +00:00
|
|
|
/* Protocol name too long */
|
2020-03-06 19:09:50 +02:00
|
|
|
#if !defined(HAVE_RUST) && !defined(ALL_BUGS_ARE_FATAL)
|
protover: TROVE-2018-005 Fix potential DoS in protover protocol parsing.
In protover.c, the `expand_protocol_list()` function expands a `smartlist_t` of
`proto_entry_t`s to their protocol name concatenated with each version number.
For example, given a `proto_entry_t` like so:
proto_entry_t *proto = tor_malloc(sizeof(proto_entry_t));
proto_range_t *range = tor_malloc_zero(sizeof(proto_range_t));
proto->name = tor_strdup("DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa");
proto->ranges = smartlist_new();
range->low = 1;
range->high = 65536;
smartlist_add(proto->ranges, range);
(Where `[19KB]` is roughly 19KB of `"a"` bytes.) This would expand in
`expand_protocol_list()` to a `smartlist_t` containing 65536 copies of the
string, e.g.:
"DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=1"
"DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=2"
[…]
"DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=65535"
Thus constituting a potential resource exhaustion attack.
The Rust implementation is not subject to this attack, because it instead
expands the above string into a `HashMap<String, HashSet<u32>` prior to #24031,
and a `HashMap<UnvalidatedProtocol, ProtoSet>` after). Neither Rust version is
subject to this attack, because it only stores the `String` once per protocol.
(Although a related, but apparently of too minor impact to be usable, DoS bug
has been fixed in #24031. [0])
[0]: https://bugs.torproject.org/24031
* ADDS hard limit on protocol name lengths in protover.c and checks in
parse_single_entry() and expand_protocol_list().
* ADDS tests to ensure the bug is caught.
* FIXES #25517: https://bugs.torproject.org/25517
2018-03-29 01:54:05 +00:00
|
|
|
tor_capture_bugs_(1);
|
2018-05-22 12:32:00 -04:00
|
|
|
tt_assert(protover_all_supported(
|
|
|
|
"DoSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
|
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
|
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
|
|
"aaaaaaaaaaaa=1-65536", &msg));
|
protover: TROVE-2018-005 Fix potential DoS in protover protocol parsing.
In protover.c, the `expand_protocol_list()` function expands a `smartlist_t` of
`proto_entry_t`s to their protocol name concatenated with each version number.
For example, given a `proto_entry_t` like so:
proto_entry_t *proto = tor_malloc(sizeof(proto_entry_t));
proto_range_t *range = tor_malloc_zero(sizeof(proto_range_t));
proto->name = tor_strdup("DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa");
proto->ranges = smartlist_new();
range->low = 1;
range->high = 65536;
smartlist_add(proto->ranges, range);
(Where `[19KB]` is roughly 19KB of `"a"` bytes.) This would expand in
`expand_protocol_list()` to a `smartlist_t` containing 65536 copies of the
string, e.g.:
"DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=1"
"DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=2"
[…]
"DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=65535"
Thus constituting a potential resource exhaustion attack.
The Rust implementation is not subject to this attack, because it instead
expands the above string into a `HashMap<String, HashSet<u32>` prior to #24031,
and a `HashMap<UnvalidatedProtocol, ProtoSet>` after). Neither Rust version is
subject to this attack, because it only stores the `String` once per protocol.
(Although a related, but apparently of too minor impact to be usable, DoS bug
has been fixed in #24031. [0])
[0]: https://bugs.torproject.org/24031
* ADDS hard limit on protocol name lengths in protover.c and checks in
parse_single_entry() and expand_protocol_list().
* ADDS tests to ensure the bug is caught.
* FIXES #25517: https://bugs.torproject.org/25517
2018-03-29 01:54:05 +00:00
|
|
|
tor_end_capture_bugs_();
|
2020-03-06 19:09:50 +02:00
|
|
|
#endif /* !defined(HAVE_RUST) && !defined(ALL_BUGS_ARE_FATAL) */
|
protover: TROVE-2018-005 Fix potential DoS in protover protocol parsing.
In protover.c, the `expand_protocol_list()` function expands a `smartlist_t` of
`proto_entry_t`s to their protocol name concatenated with each version number.
For example, given a `proto_entry_t` like so:
proto_entry_t *proto = tor_malloc(sizeof(proto_entry_t));
proto_range_t *range = tor_malloc_zero(sizeof(proto_range_t));
proto->name = tor_strdup("DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa");
proto->ranges = smartlist_new();
range->low = 1;
range->high = 65536;
smartlist_add(proto->ranges, range);
(Where `[19KB]` is roughly 19KB of `"a"` bytes.) This would expand in
`expand_protocol_list()` to a `smartlist_t` containing 65536 copies of the
string, e.g.:
"DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=1"
"DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=2"
[…]
"DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=65535"
Thus constituting a potential resource exhaustion attack.
The Rust implementation is not subject to this attack, because it instead
expands the above string into a `HashMap<String, HashSet<u32>` prior to #24031,
and a `HashMap<UnvalidatedProtocol, ProtoSet>` after). Neither Rust version is
subject to this attack, because it only stores the `String` once per protocol.
(Although a related, but apparently of too minor impact to be usable, DoS bug
has been fixed in #24031. [0])
[0]: https://bugs.torproject.org/24031
* ADDS hard limit on protocol name lengths in protover.c and checks in
parse_single_entry() and expand_protocol_list().
* ADDS tests to ensure the bug is caught.
* FIXES #25517: https://bugs.torproject.org/25517
2018-03-29 01:54:05 +00:00
|
|
|
|
2016-08-23 13:47:14 -04:00
|
|
|
done:
|
2018-02-15 09:05:55 -05:00
|
|
|
tor_end_capture_bugs_();
|
2016-08-23 13:47:14 -04:00
|
|
|
tor_free(msg);
|
|
|
|
}
|
|
|
|
|
2017-09-27 19:48:07 +00:00
|
|
|
static void
|
|
|
|
test_protover_list_supports_protocol_returns_true(void *arg)
|
|
|
|
{
|
|
|
|
(void)arg;
|
|
|
|
|
|
|
|
const char *protocols = "Link=1";
|
|
|
|
int is_supported = protocol_list_supports_protocol(protocols, PRT_LINK, 1);
|
|
|
|
tt_int_op(is_supported, OP_EQ, 1);
|
|
|
|
|
|
|
|
done:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
test_protover_list_supports_protocol_for_unsupported_returns_false(void *arg)
|
|
|
|
{
|
|
|
|
(void)arg;
|
|
|
|
|
|
|
|
const char *protocols = "Link=1";
|
|
|
|
int is_supported = protocol_list_supports_protocol(protocols, PRT_LINK, 10);
|
|
|
|
tt_int_op(is_supported, OP_EQ, 0);
|
|
|
|
|
|
|
|
done:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
2017-09-11 09:50:31 -04:00
|
|
|
static void
|
|
|
|
test_protover_supports_version(void *arg)
|
|
|
|
{
|
|
|
|
(void)arg;
|
|
|
|
|
|
|
|
tt_assert(protocol_list_supports_protocol("Link=3-6", PRT_LINK, 3));
|
|
|
|
tt_assert(protocol_list_supports_protocol("Link=3-6", PRT_LINK, 6));
|
|
|
|
tt_assert(!protocol_list_supports_protocol("Link=3-6", PRT_LINK, 7));
|
|
|
|
tt_assert(!protocol_list_supports_protocol("Link=3-6", PRT_LINKAUTH, 3));
|
|
|
|
|
|
|
|
tt_assert(!protocol_list_supports_protocol("Link=4-6 LinkAuth=3",
|
|
|
|
PRT_LINKAUTH, 2));
|
|
|
|
tt_assert(protocol_list_supports_protocol("Link=4-6 LinkAuth=3",
|
|
|
|
PRT_LINKAUTH, 3));
|
|
|
|
tt_assert(!protocol_list_supports_protocol("Link=4-6 LinkAuth=3",
|
|
|
|
PRT_LINKAUTH, 4));
|
|
|
|
tt_assert(!protocol_list_supports_protocol_or_later("Link=4-6 LinkAuth=3",
|
|
|
|
PRT_LINKAUTH, 4));
|
|
|
|
tt_assert(protocol_list_supports_protocol_or_later("Link=4-6 LinkAuth=3",
|
|
|
|
PRT_LINKAUTH, 3));
|
|
|
|
tt_assert(protocol_list_supports_protocol_or_later("Link=4-6 LinkAuth=3",
|
|
|
|
PRT_LINKAUTH, 2));
|
|
|
|
|
|
|
|
tt_assert(!protocol_list_supports_protocol_or_later("Link=4-6 LinkAuth=3",
|
|
|
|
PRT_DESC, 2));
|
|
|
|
done:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
2018-01-30 01:53:41 +11:00
|
|
|
/* This could be MAX_PROTOCOLS_TO_EXPAND, but that's not exposed by protover */
|
|
|
|
#define MAX_PROTOCOLS_TO_TEST 1024
|
|
|
|
|
|
|
|
/* LinkAuth and Relay protocol versions.
|
|
|
|
* Hard-coded here, because they are not in the code, or not exposed in the
|
|
|
|
* headers. */
|
|
|
|
#define PROTOVER_LINKAUTH_V1 1
|
2020-05-15 14:59:10 +10:00
|
|
|
#define PROTOVER_LINKAUTH_V2 2
|
2018-01-30 01:53:41 +11:00
|
|
|
#define PROTOVER_RELAY_V1 1
|
|
|
|
|
2020-05-15 14:59:10 +10:00
|
|
|
/* Deprecated HSIntro versions */
|
|
|
|
#define PROTOVER_HS_INTRO_DEPRECATED_1 1
|
|
|
|
#define PROTOVER_HS_INTRO_DEPRECATED_2 2
|
2018-01-30 01:53:41 +11:00
|
|
|
/* Highest supported HSv2 introduce protocol version.
|
|
|
|
* It's not clear if we actually support version 2, see #25068. */
|
2020-05-15 14:59:10 +10:00
|
|
|
#define PROTOVER_HS_INTRO_V2 3
|
2018-01-30 01:53:41 +11:00
|
|
|
|
2020-05-15 14:59:10 +10:00
|
|
|
/* HSv2 Rend and HSDir protocol versions. */
|
2018-01-30 01:53:41 +11:00
|
|
|
#define PROTOVER_HS_RENDEZVOUS_POINT_V2 1
|
|
|
|
#define PROTOVER_HSDIR_V2 1
|
|
|
|
|
2020-05-15 14:59:10 +10:00
|
|
|
/* DirCache, Desc, Microdesc, and Cons protocol versions. */
|
2018-01-30 01:53:41 +11:00
|
|
|
#define PROTOVER_DIRCACHE_V1 1
|
|
|
|
#define PROTOVER_DIRCACHE_V2 2
|
|
|
|
|
|
|
|
#define PROTOVER_DESC_V1 1
|
|
|
|
#define PROTOVER_DESC_V2 2
|
|
|
|
|
|
|
|
#define PROTOVER_MICRODESC_V1 1
|
|
|
|
#define PROTOVER_MICRODESC_V2 2
|
|
|
|
|
|
|
|
#define PROTOVER_CONS_V1 1
|
|
|
|
#define PROTOVER_CONS_V2 2
|
|
|
|
|
2020-05-15 14:59:10 +10:00
|
|
|
#define PROTOVER_PADDING_V1 1
|
|
|
|
|
|
|
|
#define PROTOVER_FLOWCTRL_V1 1
|
|
|
|
|
2018-01-30 01:53:41 +11:00
|
|
|
/* Make sure we haven't forgotten any supported protocols */
|
|
|
|
static void
|
|
|
|
test_protover_supported_protocols(void *arg)
|
|
|
|
{
|
|
|
|
(void)arg;
|
|
|
|
|
|
|
|
const char *supported_protocols = protover_get_supported_protocols();
|
|
|
|
|
|
|
|
/* Test for new Link in the code, that hasn't been added to supported
|
|
|
|
* protocols */
|
|
|
|
tt_assert(protocol_list_supports_protocol(supported_protocols,
|
|
|
|
PRT_LINK,
|
|
|
|
MAX_LINK_PROTO));
|
|
|
|
for (uint16_t i = 0; i < MAX_PROTOCOLS_TO_TEST; i++) {
|
2020-05-15 14:59:10 +10:00
|
|
|
tt_int_op(protocol_list_supports_protocol(supported_protocols,
|
2018-01-30 01:53:41 +11:00
|
|
|
PRT_LINK,
|
2020-05-15 14:59:10 +10:00
|
|
|
i),
|
|
|
|
OP_EQ,
|
|
|
|
is_or_protocol_version_known(i));
|
2018-01-30 01:53:41 +11:00
|
|
|
}
|
|
|
|
|
2020-05-15 14:59:10 +10:00
|
|
|
/* Legacy LinkAuth is only supported on OpenSSL and similar. */
|
|
|
|
tt_int_op(protocol_list_supports_protocol(supported_protocols,
|
2018-01-30 01:53:41 +11:00
|
|
|
PRT_LINKAUTH,
|
2020-05-15 14:59:10 +10:00
|
|
|
PROTOVER_LINKAUTH_V1),
|
|
|
|
OP_EQ,
|
|
|
|
authchallenge_type_is_supported(AUTHTYPE_RSA_SHA256_TLSSECRET));
|
|
|
|
/* LinkAuth=2 is unused */
|
|
|
|
tt_assert(!protocol_list_supports_protocol(supported_protocols,
|
|
|
|
PRT_LINKAUTH,
|
|
|
|
PROTOVER_LINKAUTH_V2));
|
|
|
|
tt_assert(
|
|
|
|
protocol_list_supports_protocol(supported_protocols,
|
|
|
|
PRT_LINKAUTH,
|
|
|
|
PROTOVER_LINKAUTH_ED25519_HANDSHAKE));
|
2018-01-30 01:53:41 +11:00
|
|
|
|
|
|
|
/* Relay protovers do not appear anywhere in the code. */
|
|
|
|
tt_assert(protocol_list_supports_protocol(supported_protocols,
|
|
|
|
PRT_RELAY,
|
|
|
|
PROTOVER_RELAY_V1));
|
|
|
|
tt_assert(protocol_list_supports_protocol(supported_protocols,
|
|
|
|
PRT_RELAY,
|
2020-05-15 14:59:10 +10:00
|
|
|
PROTOVER_RELAY_EXTEND2));
|
|
|
|
tt_assert(protocol_list_supports_protocol(supported_protocols,
|
|
|
|
PRT_RELAY,
|
|
|
|
PROTOVER_RELAY_ACCEPT_IPV6));
|
|
|
|
tt_assert(protocol_list_supports_protocol(supported_protocols,
|
|
|
|
PRT_RELAY,
|
|
|
|
PROTOVER_RELAY_EXTEND_IPV6));
|
|
|
|
tt_assert(protocol_list_supports_protocol(supported_protocols,
|
|
|
|
PRT_RELAY,
|
|
|
|
PROTOVER_RELAY_CANONICAL_IPV6));
|
2018-01-30 01:53:41 +11:00
|
|
|
|
2020-05-15 14:59:10 +10:00
|
|
|
/* These HSIntro versions are deprecated */
|
|
|
|
tt_assert(!protocol_list_supports_protocol(supported_protocols,
|
|
|
|
PRT_HSINTRO,
|
|
|
|
PROTOVER_HS_INTRO_DEPRECATED_1));
|
|
|
|
tt_assert(!protocol_list_supports_protocol(supported_protocols,
|
|
|
|
PRT_HSINTRO,
|
|
|
|
PROTOVER_HS_INTRO_DEPRECATED_2));
|
2018-01-30 01:53:41 +11:00
|
|
|
/* We could test legacy HSIntro by calling rend_service_update_descriptor(),
|
|
|
|
* and checking the protocols field. But that's unlikely to change, so
|
|
|
|
* we just use a hard-coded value. */
|
|
|
|
tt_assert(protocol_list_supports_protocol(supported_protocols,
|
|
|
|
PRT_HSINTRO,
|
2020-05-15 14:59:10 +10:00
|
|
|
PROTOVER_HS_INTRO_V2));
|
2018-01-30 01:53:41 +11:00
|
|
|
/* Test for HSv3 HSIntro */
|
|
|
|
tt_assert(protocol_list_supports_protocol(supported_protocols,
|
|
|
|
PRT_HSINTRO,
|
|
|
|
PROTOVER_HS_INTRO_V3));
|
2020-05-15 14:59:10 +10:00
|
|
|
/* Test for HSIntro DoS */
|
|
|
|
tt_assert(protocol_list_supports_protocol(supported_protocols,
|
|
|
|
PRT_HSINTRO,
|
|
|
|
PROTOVER_HS_INTRO_DOS));
|
2018-01-30 01:53:41 +11:00
|
|
|
|
|
|
|
/* Legacy HSRend does not appear anywhere in the code. */
|
|
|
|
tt_assert(protocol_list_supports_protocol(supported_protocols,
|
|
|
|
PRT_HSREND,
|
|
|
|
PROTOVER_HS_RENDEZVOUS_POINT_V2));
|
|
|
|
/* Test for HSv3 HSRend */
|
|
|
|
tt_assert(protocol_list_supports_protocol(supported_protocols,
|
|
|
|
PRT_HSREND,
|
|
|
|
PROTOVER_HS_RENDEZVOUS_POINT_V3));
|
|
|
|
|
|
|
|
/* Legacy HSDir does not appear anywhere in the code. */
|
|
|
|
tt_assert(protocol_list_supports_protocol(supported_protocols,
|
|
|
|
PRT_HSDIR,
|
|
|
|
PROTOVER_HSDIR_V2));
|
|
|
|
/* Test for HSv3 HSDir */
|
|
|
|
tt_assert(protocol_list_supports_protocol(supported_protocols,
|
|
|
|
PRT_HSDIR,
|
|
|
|
PROTOVER_HSDIR_V3));
|
|
|
|
|
|
|
|
/* No DirCache versions appear anywhere in the code. */
|
|
|
|
tt_assert(protocol_list_supports_protocol(supported_protocols,
|
|
|
|
PRT_DIRCACHE,
|
|
|
|
PROTOVER_DIRCACHE_V1));
|
|
|
|
tt_assert(protocol_list_supports_protocol(supported_protocols,
|
|
|
|
PRT_DIRCACHE,
|
|
|
|
PROTOVER_DIRCACHE_V2));
|
|
|
|
|
|
|
|
/* No Desc versions appear anywhere in the code. */
|
|
|
|
tt_assert(protocol_list_supports_protocol(supported_protocols,
|
|
|
|
PRT_DESC,
|
|
|
|
PROTOVER_DESC_V1));
|
|
|
|
tt_assert(protocol_list_supports_protocol(supported_protocols,
|
|
|
|
PRT_DESC,
|
|
|
|
PROTOVER_DESC_V2));
|
|
|
|
/* Is there any way to test for new Desc? */
|
|
|
|
|
|
|
|
/* No Microdesc versions appear anywhere in the code. */
|
|
|
|
tt_assert(protocol_list_supports_protocol(supported_protocols,
|
|
|
|
PRT_MICRODESC,
|
|
|
|
PROTOVER_MICRODESC_V1));
|
|
|
|
tt_assert(protocol_list_supports_protocol(supported_protocols,
|
|
|
|
PRT_MICRODESC,
|
|
|
|
PROTOVER_MICRODESC_V2));
|
|
|
|
|
|
|
|
/* No Cons versions appear anywhere in the code. */
|
|
|
|
tt_assert(protocol_list_supports_protocol(supported_protocols,
|
|
|
|
PRT_CONS,
|
|
|
|
PROTOVER_CONS_V1));
|
|
|
|
tt_assert(protocol_list_supports_protocol(supported_protocols,
|
|
|
|
PRT_CONS,
|
|
|
|
PROTOVER_CONS_V2));
|
2020-05-15 14:59:10 +10:00
|
|
|
|
|
|
|
/* Padding=1 is deprecated. */
|
|
|
|
tt_assert(!protocol_list_supports_protocol(supported_protocols,
|
|
|
|
PRT_PADDING,
|
|
|
|
PROTOVER_PADDING_V1));
|
|
|
|
tt_assert(protocol_list_supports_protocol(supported_protocols,
|
|
|
|
PRT_PADDING,
|
|
|
|
PROTOVER_HS_SETUP_PADDING));
|
|
|
|
|
|
|
|
/* FlowCtrl */
|
|
|
|
tt_assert(protocol_list_supports_protocol(supported_protocols,
|
|
|
|
PRT_FLOWCTRL,
|
|
|
|
PROTOVER_FLOWCTRL_V1));
|
2018-01-30 01:53:41 +11:00
|
|
|
|
|
|
|
done:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
2018-02-14 11:47:05 -05:00
|
|
|
static void
|
|
|
|
test_protover_vote_roundtrip(void *args)
|
|
|
|
{
|
|
|
|
(void) args;
|
|
|
|
static const struct {
|
|
|
|
const char *input;
|
|
|
|
const char *expected_output;
|
|
|
|
} examples[] = {
|
2018-08-26 01:20:44 +00:00
|
|
|
{ "Risqu\u00e9=1", NULL },
|
|
|
|
{ ",,,=1", NULL },
|
|
|
|
{ "\xc1=1", NULL },
|
|
|
|
{ "Foo_Bar=1", NULL },
|
2018-02-14 11:47:05 -05:00
|
|
|
{ "Fkrkljdsf", NULL },
|
|
|
|
{ "Zn=4294967295", NULL },
|
|
|
|
{ "Zn=4294967295-1", NULL },
|
|
|
|
{ "Zn=4294967293-4294967295", NULL },
|
|
|
|
/* Will fail because of 4294967295. */
|
2018-08-18 16:54:09 +00:00
|
|
|
{ "Foo=1,3 Bar=3 Baz= Quux=9-12,14,15-16,900 Zn=1,4294967295",
|
2018-02-14 11:47:05 -05:00
|
|
|
NULL },
|
2018-08-18 16:54:09 +00:00
|
|
|
{ "Foo=1,3 Bar=3 Baz= Quux=9-12,14,15-16,900 Zn=1,4294967294",
|
|
|
|
"Bar=3 Foo=1,3 Quux=9-12,14-16,900 Zn=1,4294967294" },
|
|
|
|
{ "Zu16=1,65536", "Zu16=1,65536" },
|
2018-02-14 11:47:05 -05:00
|
|
|
{ "N-1=1,2", "N-1=1-2" },
|
|
|
|
{ "-1=4294967295", NULL },
|
|
|
|
{ "-1=3", "-1=3" },
|
|
|
|
/* junk. */
|
|
|
|
{ "!!3@*", NULL },
|
|
|
|
/* Missing equals sign */
|
|
|
|
{ "Link=4 Haprauxymatyve Desc=9", NULL },
|
|
|
|
{ "Link=4 Haprauxymatyve=7 Desc=9",
|
|
|
|
"Desc=9 Haprauxymatyve=7 Link=4" },
|
|
|
|
{ "=10-11", NULL },
|
|
|
|
{ "X=10-11", "X=10-11" },
|
|
|
|
{ "Link=4 =3 Desc=9", NULL },
|
|
|
|
{ "Link=4 Z=3 Desc=9", "Desc=9 Link=4 Z=3" },
|
|
|
|
{ "Link=fred", NULL },
|
|
|
|
{ "Link=1,fred", NULL },
|
|
|
|
{ "Link=1,fred,3", NULL },
|
|
|
|
{ "Link=1,9-8,3", NULL },
|
2018-02-15 08:46:13 -05:00
|
|
|
{ "Faux=-0", NULL },
|
|
|
|
{ "Faux=0--0", NULL },
|
2018-02-14 11:47:05 -05:00
|
|
|
{ "Faux=-1", NULL },
|
|
|
|
{ "Faux=-1-3", NULL },
|
|
|
|
{ "Faux=1--1", NULL },
|
2018-08-17 17:14:25 +00:00
|
|
|
{ "Link=1-2-", NULL },
|
|
|
|
{ "Link=1-2-3", NULL },
|
|
|
|
{ "Faux=1-2-", NULL },
|
|
|
|
{ "Faux=1-2-3", NULL },
|
2018-08-17 17:25:24 +00:00
|
|
|
{ "Link=\t1,3", NULL },
|
|
|
|
{ "Link=1\n,3", NULL },
|
|
|
|
{ "Faux=1,\r3", NULL },
|
|
|
|
{ "Faux=1,3\f", NULL },
|
2018-02-14 11:47:05 -05:00
|
|
|
/* Large integers */
|
|
|
|
{ "Link=4294967296", NULL },
|
|
|
|
/* Large range */
|
|
|
|
{ "Sleen=1-501", "Sleen=1-501" },
|
|
|
|
{ "Sleen=1-65537", NULL },
|
tests: Make inline comments in test_protover.c more accurate.
The DoS potential is slightly higher in C now due to some differences to the
Rust code, see the C_RUST_DIFFERS tags in src/rust/protover/tests/protover.rs.
Also, the comment about "failing at the splitting stage" in Rust wasn't true,
since when we split, we ignore empty chunks (e.g. "1--1" parses into
"(1,None),(None,1)" and "None" can't be parsed into an integer).
Finally, the comment about "Rust seems to experience an internal error" is only
true in debug mode, where u32s are bounds-checked at runtime. In release mode,
code expressing the equivalent of this test will error with
`Err(ProtoverError::Unparseable)` because 4294967295 is too large.
2018-03-27 21:34:00 +00:00
|
|
|
/* Both C/Rust implementations should be able to handle this mild DoS. */
|
2018-08-18 16:54:09 +00:00
|
|
|
{ "Sleen=1-2147483648", NULL },
|
tests: Make inline comments in test_protover.c more accurate.
The DoS potential is slightly higher in C now due to some differences to the
Rust code, see the C_RUST_DIFFERS tags in src/rust/protover/tests/protover.rs.
Also, the comment about "failing at the splitting stage" in Rust wasn't true,
since when we split, we ignore empty chunks (e.g. "1--1" parses into
"(1,None),(None,1)" and "None" can't be parsed into an integer).
Finally, the comment about "Rust seems to experience an internal error" is only
true in debug mode, where u32s are bounds-checked at runtime. In release mode,
code expressing the equivalent of this test will error with
`Err(ProtoverError::Unparseable)` because 4294967295 is too large.
2018-03-27 21:34:00 +00:00
|
|
|
/* Rust tests are built in debug mode, so ints are bounds-checked. */
|
2018-08-18 16:54:09 +00:00
|
|
|
{ "Sleen=1-4294967295", NULL },
|
2018-02-14 11:47:05 -05:00
|
|
|
};
|
|
|
|
unsigned u;
|
|
|
|
smartlist_t *votes = smartlist_new();
|
|
|
|
char *result = NULL;
|
|
|
|
|
|
|
|
for (u = 0; u < ARRAY_LENGTH(examples); ++u) {
|
|
|
|
const char *input = examples[u].input;
|
|
|
|
const char *expected_output = examples[u].expected_output;
|
|
|
|
|
|
|
|
smartlist_add(votes, (void*)input);
|
|
|
|
result = protover_compute_vote(votes, 1);
|
|
|
|
if (expected_output != NULL) {
|
|
|
|
tt_str_op(result, OP_EQ, expected_output);
|
|
|
|
} else {
|
|
|
|
tt_str_op(result, OP_EQ, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
smartlist_clear(votes);
|
|
|
|
tor_free(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
smartlist_free(votes);
|
|
|
|
tor_free(result);
|
|
|
|
}
|
|
|
|
|
2020-02-12 22:07:26 +10:00
|
|
|
static void
|
|
|
|
test_protover_vote_roundtrip_ours(void *args)
|
|
|
|
{
|
|
|
|
(void) args;
|
|
|
|
const char *examples[] = {
|
|
|
|
protover_get_supported_protocols(),
|
|
|
|
DIRVOTE_RECCOMEND_RELAY_PROTO,
|
|
|
|
DIRVOTE_RECCOMEND_CLIENT_PROTO,
|
|
|
|
DIRVOTE_REQUIRE_RELAY_PROTO,
|
|
|
|
DIRVOTE_REQUIRE_CLIENT_PROTO,
|
|
|
|
};
|
|
|
|
unsigned u;
|
|
|
|
smartlist_t *votes = smartlist_new();
|
|
|
|
char *result = NULL;
|
|
|
|
|
|
|
|
for (u = 0; u < ARRAY_LENGTH(examples); ++u) {
|
|
|
|
tt_assert(examples[u]);
|
|
|
|
const char *input = examples[u];
|
|
|
|
const char *expected_output = examples[u];
|
|
|
|
|
|
|
|
smartlist_add(votes, (void*)input);
|
|
|
|
result = protover_compute_vote(votes, 1);
|
|
|
|
if (expected_output != NULL) {
|
|
|
|
tt_str_op(result, OP_EQ, expected_output);
|
|
|
|
} else {
|
|
|
|
tt_str_op(result, OP_EQ, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
smartlist_clear(votes);
|
|
|
|
tor_free(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
smartlist_free(votes);
|
|
|
|
tor_free(result);
|
|
|
|
}
|
|
|
|
|
2020-05-15 23:21:13 +10:00
|
|
|
/* Stringifies its argument.
|
|
|
|
* 4 -> "4" */
|
|
|
|
#define STR(x) #x
|
|
|
|
|
|
|
|
#ifdef COCCI
|
|
|
|
#define PROTOVER(proto_string, version_macro)
|
|
|
|
#else
|
|
|
|
/* Generate a protocol version string using proto_string and version_macro.
|
|
|
|
* PROTOVER("HSIntro", PROTOVER_HS_INTRO_DOS) -> "HSIntro" "=" "5"
|
|
|
|
* Uses two levels of macros to turn PROTOVER_HS_INTRO_DOS into "5".
|
|
|
|
*/
|
|
|
|
#define PROTOVER(proto_string, version_macro) \
|
|
|
|
(proto_string "=" STR(version_macro))
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Test that the proto_string version version_macro sets summary_flag. */
|
|
|
|
#define TEST_PROTOVER(proto_string, version_macro, summary_flag) \
|
|
|
|
STMT_BEGIN \
|
|
|
|
memset(&flags, 0, sizeof(flags)); \
|
|
|
|
summarize_protover_flags(&flags, \
|
|
|
|
PROTOVER(proto_string, version_macro), \
|
|
|
|
NULL); \
|
|
|
|
tt_int_op(flags.protocols_known, OP_EQ, 1); \
|
|
|
|
tt_int_op(flags.summary_flag, OP_EQ, 1); \
|
|
|
|
flags.protocols_known = 0; \
|
|
|
|
flags.summary_flag = 0; \
|
|
|
|
tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags)); \
|
|
|
|
STMT_END
|
|
|
|
|
|
|
|
static void
|
|
|
|
test_protover_summarize_flags(void *args)
|
|
|
|
{
|
|
|
|
(void) args;
|
|
|
|
char pv[30];
|
|
|
|
memset(&pv, 0, sizeof(pv));
|
|
|
|
|
|
|
|
protover_summary_flags_t zero_flags;
|
|
|
|
memset(&zero_flags, 0, sizeof(zero_flags));
|
|
|
|
protover_summary_flags_t flags;
|
|
|
|
|
|
|
|
memset(&flags, 0, sizeof(flags));
|
|
|
|
summarize_protover_flags(&flags, NULL, NULL);
|
|
|
|
tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
|
|
|
|
|
|
|
|
/* "" sets the protocols_known flag */
|
|
|
|
memset(&flags, 0, sizeof(flags));
|
|
|
|
summarize_protover_flags(&flags, "", "");
|
|
|
|
tt_int_op(flags.protocols_known, OP_EQ, 1);
|
|
|
|
/* Now clear that flag, and check the rest are zero */
|
|
|
|
flags.protocols_known = 0;
|
|
|
|
tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
|
|
|
|
|
|
|
|
/* Now check version exceptions */
|
|
|
|
|
|
|
|
/* EXTEND2 cell support */
|
|
|
|
memset(&flags, 0, sizeof(flags));
|
|
|
|
summarize_protover_flags(&flags, NULL, "Tor 0.2.4.8-alpha");
|
|
|
|
tt_int_op(flags.protocols_known, OP_EQ, 1);
|
|
|
|
tt_int_op(flags.supports_extend2_cells, OP_EQ, 1);
|
|
|
|
/* Now clear those flags, and check the rest are zero */
|
|
|
|
flags.protocols_known = 0;
|
|
|
|
flags.supports_extend2_cells = 0;
|
|
|
|
tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
|
|
|
|
|
|
|
|
/* disabling HSDir v3 support for buggy versions */
|
|
|
|
memset(&flags, 0, sizeof(flags));
|
|
|
|
summarize_protover_flags(&flags,
|
|
|
|
PROTOVER("HSDir", PROTOVER_HSDIR_V3),
|
|
|
|
NULL);
|
|
|
|
tt_int_op(flags.protocols_known, OP_EQ, 1);
|
|
|
|
tt_int_op(flags.supports_v3_hsdir, OP_EQ, 1);
|
|
|
|
/* Now clear those flags, and check the rest are zero */
|
|
|
|
flags.protocols_known = 0;
|
|
|
|
flags.supports_v3_hsdir = 0;
|
|
|
|
tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
|
|
|
|
|
|
|
|
memset(&flags, 0, sizeof(flags));
|
|
|
|
summarize_protover_flags(&flags,
|
|
|
|
PROTOVER("HSDir", PROTOVER_HSDIR_V3),
|
|
|
|
"Tor 0.3.0.7");
|
|
|
|
tt_int_op(flags.protocols_known, OP_EQ, 1);
|
|
|
|
/* Now clear that flag, and check the rest are zero */
|
|
|
|
flags.protocols_known = 0;
|
|
|
|
tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
|
|
|
|
|
|
|
|
/* Now check standard summaries */
|
|
|
|
|
|
|
|
/* LinkAuth */
|
|
|
|
memset(&flags, 0, sizeof(flags));
|
|
|
|
summarize_protover_flags(&flags,
|
|
|
|
PROTOVER("LinkAuth",
|
|
|
|
PROTOVER_LINKAUTH_ED25519_HANDSHAKE),
|
|
|
|
NULL);
|
|
|
|
tt_int_op(flags.protocols_known, OP_EQ, 1);
|
|
|
|
tt_int_op(flags.supports_ed25519_link_handshake_compat, OP_EQ, 1);
|
|
|
|
tt_int_op(flags.supports_ed25519_link_handshake_any, OP_EQ, 1);
|
|
|
|
/* Now clear those flags, and check the rest are zero */
|
|
|
|
flags.protocols_known = 0;
|
|
|
|
flags.supports_ed25519_link_handshake_compat = 0;
|
|
|
|
flags.supports_ed25519_link_handshake_any = 0;
|
|
|
|
tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
|
|
|
|
|
|
|
|
/* Test one greater */
|
|
|
|
memset(&flags, 0, sizeof(flags));
|
|
|
|
snprintf(pv, sizeof(pv),
|
|
|
|
"%s=%d", "LinkAuth", PROTOVER_LINKAUTH_ED25519_HANDSHAKE + 1);
|
|
|
|
summarize_protover_flags(&flags, pv, NULL);
|
|
|
|
tt_int_op(flags.protocols_known, OP_EQ, 1);
|
|
|
|
tt_int_op(flags.supports_ed25519_link_handshake_compat, OP_EQ, 0);
|
|
|
|
tt_int_op(flags.supports_ed25519_link_handshake_any, OP_EQ, 1);
|
|
|
|
/* Now clear those flags, and check the rest are zero */
|
|
|
|
flags.protocols_known = 0;
|
|
|
|
flags.supports_ed25519_link_handshake_compat = 0;
|
|
|
|
flags.supports_ed25519_link_handshake_any = 0;
|
|
|
|
tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
|
|
|
|
|
|
|
|
/* Test one less */
|
|
|
|
memset(&flags, 0, sizeof(flags));
|
|
|
|
snprintf(pv, sizeof(pv),
|
|
|
|
"%s=%d", "LinkAuth", PROTOVER_LINKAUTH_ED25519_HANDSHAKE - 1);
|
|
|
|
summarize_protover_flags(&flags, pv, NULL);
|
|
|
|
tt_int_op(flags.protocols_known, OP_EQ, 1);
|
|
|
|
tt_int_op(flags.supports_ed25519_link_handshake_compat, OP_EQ, 0);
|
|
|
|
tt_int_op(flags.supports_ed25519_link_handshake_any, OP_EQ, 0);
|
|
|
|
/* Now clear those flags, and check the rest are zero */
|
|
|
|
flags.protocols_known = 0;
|
|
|
|
flags.supports_ed25519_link_handshake_compat = 0;
|
|
|
|
flags.supports_ed25519_link_handshake_any = 0;
|
|
|
|
tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
|
|
|
|
|
|
|
|
/* We don't test "one more" and "one less" for each protocol version.
|
|
|
|
* But that could be a useful thing to add. */
|
|
|
|
|
|
|
|
/* Relay */
|
|
|
|
memset(&flags, 0, sizeof(flags));
|
|
|
|
/* This test relies on these versions being equal */
|
|
|
|
tt_int_op(PROTOVER_RELAY_EXTEND2, OP_EQ, PROTOVER_RELAY_ACCEPT_IPV6);
|
|
|
|
summarize_protover_flags(&flags,
|
|
|
|
PROTOVER("Relay", PROTOVER_RELAY_EXTEND2), NULL);
|
|
|
|
tt_int_op(flags.protocols_known, OP_EQ, 1);
|
|
|
|
tt_int_op(flags.supports_extend2_cells, OP_EQ, 1);
|
|
|
|
tt_int_op(flags.supports_accepting_ipv6_extends, OP_EQ, 1);
|
|
|
|
/* Now clear those flags, and check the rest are zero */
|
|
|
|
flags.protocols_known = 0;
|
|
|
|
flags.supports_extend2_cells = 0;
|
|
|
|
flags.supports_accepting_ipv6_extends = 0;
|
|
|
|
tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
|
|
|
|
|
|
|
|
memset(&flags, 0, sizeof(flags));
|
|
|
|
/* This test relies on these versions being equal */
|
|
|
|
tt_int_op(PROTOVER_RELAY_EXTEND_IPV6, OP_EQ, PROTOVER_RELAY_CANONICAL_IPV6);
|
|
|
|
summarize_protover_flags(&flags,
|
|
|
|
PROTOVER("Relay", PROTOVER_RELAY_EXTEND_IPV6),
|
|
|
|
NULL);
|
|
|
|
tt_int_op(flags.protocols_known, OP_EQ, 1);
|
|
|
|
tt_int_op(flags.supports_accepting_ipv6_extends, OP_EQ, 1);
|
|
|
|
tt_int_op(flags.supports_initiating_ipv6_extends, OP_EQ, 1);
|
|
|
|
tt_int_op(flags.supports_canonical_ipv6_conns, OP_EQ, 1);
|
|
|
|
/* Now clear those flags, and check the rest are zero */
|
|
|
|
flags.protocols_known = 0;
|
|
|
|
flags.supports_accepting_ipv6_extends = 0;
|
|
|
|
flags.supports_initiating_ipv6_extends = 0;
|
|
|
|
flags.supports_canonical_ipv6_conns = 0;
|
|
|
|
tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
|
|
|
|
|
|
|
|
TEST_PROTOVER("HSIntro", PROTOVER_HS_INTRO_V3,
|
|
|
|
supports_ed25519_hs_intro);
|
|
|
|
TEST_PROTOVER("HSIntro", PROTOVER_HS_INTRO_DOS,
|
|
|
|
supports_establish_intro_dos_extension);
|
|
|
|
|
|
|
|
TEST_PROTOVER("HSRend", PROTOVER_HS_RENDEZVOUS_POINT_V3,
|
|
|
|
supports_v3_rendezvous_point);
|
|
|
|
|
|
|
|
TEST_PROTOVER("HSDir", PROTOVER_HSDIR_V3,
|
|
|
|
supports_v3_hsdir);
|
|
|
|
|
|
|
|
TEST_PROTOVER("Padding", PROTOVER_HS_SETUP_PADDING,
|
|
|
|
supports_hs_setup_padding);
|
|
|
|
|
|
|
|
done:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
2016-08-09 19:11:47 -04:00
|
|
|
#define PV_TEST(name, flags) \
|
|
|
|
{ #name, test_protover_ ##name, (flags), NULL, NULL }
|
|
|
|
|
|
|
|
struct testcase_t protover_tests[] = {
|
|
|
|
PV_TEST(parse, 0),
|
2016-08-23 14:02:48 -04:00
|
|
|
PV_TEST(parse_fail, 0),
|
2016-08-19 18:04:02 -04:00
|
|
|
PV_TEST(vote, 0),
|
2016-08-23 13:47:14 -04:00
|
|
|
PV_TEST(all_supported, 0),
|
2017-09-27 19:48:07 +00:00
|
|
|
PV_TEST(list_supports_protocol_for_unsupported_returns_false, 0),
|
|
|
|
PV_TEST(list_supports_protocol_returns_true, 0),
|
2017-09-11 09:50:31 -04:00
|
|
|
PV_TEST(supports_version, 0),
|
2018-01-30 01:53:41 +11:00
|
|
|
PV_TEST(supported_protocols, 0),
|
2018-02-14 11:47:05 -05:00
|
|
|
PV_TEST(vote_roundtrip, 0),
|
2020-02-12 22:07:26 +10:00
|
|
|
PV_TEST(vote_roundtrip_ours, 0),
|
2020-05-15 23:21:13 +10:00
|
|
|
/* fork, because we memoize flags internally */
|
|
|
|
PV_TEST(summarize_flags, TT_FORK),
|
2016-08-09 19:11:47 -04:00
|
|
|
END_OF_TESTCASES
|
|
|
|
};
|