aboutsummaryrefslogtreecommitdiff
path: root/src/test/test_protover.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/test_protover.c')
-rw-r--r--src/test/test_protover.c339
1 files changed, 301 insertions, 38 deletions
diff --git a/src/test/test_protover.c b/src/test/test_protover.c
index c4379a15e1..bdfb2d13cd 100644
--- a/src/test/test_protover.c
+++ b/src/test/test_protover.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Tor Project, Inc. */
+/* Copyright (c) 2016-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define PROTOVER_PRIVATE
@@ -8,10 +8,20 @@
#include "protover.h"
+#include "or.h"
+#include "connection_or.h"
+
static void
test_protover_parse(void *arg)
{
(void) arg;
+#ifdef HAVE_RUST
+ /** This test is disabled on rust builds, because it only exists to test
+ * internal C functions. */
+ tt_skip();
+ done:
+ ;
+#else
char *re_encoded = NULL;
const char *orig = "Foo=1,3 Bar=3 Baz= Quux=9-12,14,15-16,900";
@@ -78,38 +88,51 @@ test_protover_parse(void *arg)
SMARTLIST_FOREACH(elts, proto_entry_t *, ent, proto_entry_free(ent));
smartlist_free(elts);
tor_free(re_encoded);
+#endif
}
static void
test_protover_parse_fail(void *arg)
{
(void)arg;
+#ifdef HAVE_RUST
+ /** This test is disabled on rust builds, because it only exists to test
+ * internal C functions. */
+ tt_skip();
+#else
smartlist_t *elts;
/* random junk */
elts = parse_protocol_list("!!3@*");
- tt_assert(elts == NULL);
+ tt_ptr_op(elts, OP_EQ, NULL);
/* Missing equals sign in an entry */
elts = parse_protocol_list("Link=4 Haprauxymatyve Desc=9");
- tt_assert(elts == NULL);
+ tt_ptr_op(elts, OP_EQ, NULL);
/* Missing word. */
elts = parse_protocol_list("Link=4 =3 Desc=9");
- tt_assert(elts == NULL);
+ tt_ptr_op(elts, OP_EQ, NULL);
/* Broken numbers */
elts = parse_protocol_list("Link=fred");
- tt_assert(elts == NULL);
+ tt_ptr_op(elts, OP_EQ, NULL);
elts = parse_protocol_list("Link=1,fred");
- tt_assert(elts == NULL);
+ tt_ptr_op(elts, OP_EQ, NULL);
elts = parse_protocol_list("Link=1,fred,3");
- tt_assert(elts == NULL);
+ tt_ptr_op(elts, OP_EQ, NULL);
/* Broken range */
elts = parse_protocol_list("Link=1,9-8,3");
- tt_assert(elts == NULL);
+ tt_ptr_op(elts, OP_EQ, NULL);
+
+ /* Protocol name too long */
+ elts = parse_protocol_list("DoSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
+ tt_ptr_op(elts, OP_EQ, NULL);
+#endif
done:
;
}
@@ -203,6 +226,15 @@ test_protover_vote(void *arg)
tt_str_op(result, OP_EQ, "");
tor_free(result);
+ /* Protocol name too long */
+ smartlist_clear(lst);
+ smartlist_add(lst, (void*) "DoSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
+ result = protover_compute_vote(lst, 1);
+ tt_str_op(result, OP_EQ, "");
+ tor_free(result);
+
done:
tor_free(result);
smartlist_free(lst);
@@ -215,18 +247,19 @@ test_protover_all_supported(void *arg)
char *msg = NULL;
tt_assert(protover_all_supported(NULL, &msg));
- tt_assert(msg == NULL);
+ tt_ptr_op(msg, OP_EQ, NULL);
tt_assert(protover_all_supported("", &msg));
- tt_assert(msg == NULL);
+ tt_ptr_op(msg, OP_EQ, NULL);
// Some things that we do support
tt_assert(protover_all_supported("Link=3-4", &msg));
- tt_assert(msg == NULL);
+ tt_ptr_op(msg, OP_EQ, NULL);
tt_assert(protover_all_supported("Link=3-4 Desc=2", &msg));
- tt_assert(msg == NULL);
+ tt_ptr_op(msg, OP_EQ, NULL);
// Some things we don't support
+ tt_assert(! protover_all_supported("Wombat=9", NULL));
tt_assert(! protover_all_supported("Wombat=9", &msg));
tt_str_op(msg, OP_EQ, "Wombat=9");
tor_free(msg);
@@ -238,35 +271,60 @@ test_protover_all_supported(void *arg)
tt_assert(! protover_all_supported("Link=3-4 Wombat=9", &msg));
tt_str_op(msg, OP_EQ, "Wombat=9");
tor_free(msg);
+
+ /* Mix of things we support and don't support within a single protocol
+ * which we do support */
tt_assert(! protover_all_supported("Link=3-999", &msg));
- tt_str_op(msg, OP_EQ, "Link=3-999");
+ 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);
- /* CPU/RAM DoS loop: Rust only */
- tt_assert(! protover_all_supported("Sleen=0-2147483648", &msg));
- tt_str_op(msg, OP_EQ, "Sleen=0-2147483648");
+ /* 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");
+ tor_free(msg);
+
+ /* We shouldn't be able to DoS ourselves parsing a large range. */
+ tt_assert(! protover_all_supported("Sleen=1-2147483648", &msg));
+ tt_str_op(msg, OP_EQ, "Sleen=1-2147483648");
tor_free(msg);
/* This case is allowed. */
- tt_assert(! protover_all_supported("Sleen=0-4294967294", &msg));
- tt_str_op(msg, OP_EQ, "Sleen=0-4294967294");
+ tt_assert(! protover_all_supported("Sleen=1-4294967294", &msg));
+ tt_str_op(msg, OP_EQ, "Sleen=1-4294967294");
tor_free(msg);
- /* If we get an unparseable list, we say "yes, that's supported." */
-#ifndef HAVE_RUST
- // XXXX let's make this section unconditional: rust should behave the
- // XXXX same as C here!
+ /* 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);
+
+ /* If we get a completely unparseable list, protover_all_supported should
+ * hit a fatal assertion for BUG(entries == NULL). */
tor_capture_bugs_(1);
tt_assert(protover_all_supported("Fribble", &msg));
- tt_ptr_op(msg, OP_EQ, NULL);
tor_end_capture_bugs_();
- /* This case is forbidden. Since it came from a protover_all_supported,
- * it can trigger a bug message. */
+ /* If we get a completely unparseable list, protover_all_supported should
+ * hit a fatal assertion for BUG(entries == NULL). */
tor_capture_bugs_(1);
- tt_assert(protover_all_supported("Sleen=0-4294967295", &msg));
- tt_ptr_op(msg, OP_EQ, NULL);
- tor_free(msg);
+ tt_assert(protover_all_supported("Sleen=1-4294967295", &msg));
+ tor_end_capture_bugs_();
+
+ /* Protocol name too long */
+#ifndef HAVE_RUST // XXXXXX ?????
+ tor_capture_bugs_(1);
+ tt_assert(protover_all_supported(
+ "DoSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaa=1-65536", &msg));
tor_end_capture_bugs_();
#endif
@@ -276,6 +334,209 @@ test_protover_all_supported(void *arg)
}
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:
+ ;
+}
+
+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:
+ ;
+}
+
+/* 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
+#define PROTOVER_LINKAUTH_V3 3
+
+#define PROTOVER_RELAY_V1 1
+#define PROTOVER_RELAY_V2 2
+
+/* Highest supported HSv2 introduce protocol version.
+ * Hard-coded here, because it does not appear anywhere in the code.
+ * It's not clear if we actually support version 2, see #25068. */
+#define PROTOVER_HSINTRO_V2 3
+
+/* HSv2 Rend and HSDir protocol versions.
+ * Hard-coded here, because they do not appear anywhere in the code. */
+#define PROTOVER_HS_RENDEZVOUS_POINT_V2 1
+#define PROTOVER_HSDIR_V2 1
+
+/* DirCache, Desc, Microdesc, and Cons protocol versions.
+ * Hard-coded here, because they do not appear anywhere in the code. */
+#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
+
+/* 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++) {
+ if (is_or_protocol_version_known(i)) {
+ tt_assert(protocol_list_supports_protocol(supported_protocols,
+ PRT_LINK,
+ i));
+ }
+ }
+
+ /* Legacy LinkAuth does not appear anywhere in the code. */
+ tt_assert(protocol_list_supports_protocol(supported_protocols,
+ PRT_LINKAUTH,
+ PROTOVER_LINKAUTH_V1));
+ /* Latest LinkAuth is not exposed in the headers. */
+ tt_assert(protocol_list_supports_protocol(supported_protocols,
+ PRT_LINKAUTH,
+ PROTOVER_LINKAUTH_V3));
+ /* Is there any way to test for new LinkAuth? */
+
+ /* 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,
+ PROTOVER_RELAY_V2));
+ /* Is there any way to test for new Relay? */
+
+ /* 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,
+ PROTOVER_HSINTRO_V2));
+ /* Test for HSv3 HSIntro */
+ tt_assert(protocol_list_supports_protocol(supported_protocols,
+ PRT_HSINTRO,
+ PROTOVER_HS_INTRO_V3));
+ /* Is there any way to test for new HSIntro? */
+
+ /* 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));
+ /* Is there any way to test for new HSRend? */
+
+ /* 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));
+ /* Is there any way to test for new HSDir? */
+
+ /* 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));
+ /* Is there any way to test for new DirCache? */
+
+ /* 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));
+ /* Is there any way to test for new Microdesc? */
+
+ /* 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));
+ /* Is there any way to test for new Cons? */
+
+ done:
+ ;
+}
+
+static void
test_protover_vote_roundtrip(void *args)
{
(void) args;
@@ -292,11 +553,11 @@ test_protover_vote_roundtrip(void *args)
{ "Zn=4294967295-1", NULL },
{ "Zn=4294967293-4294967295", NULL },
/* Will fail because of 4294967295. */
- { "Foo=1,3 Bar=3 Baz= Quux=9-12,14,15-16,900 Zn=0,4294967295",
+ { "Foo=1,3 Bar=3 Baz= Quux=9-12,14,15-16,900 Zn=1,4294967295",
NULL },
- { "Foo=1,3 Bar=3 Baz= Quux=9-12,14,15-16,900 Zn=0,4294967294",
- "Bar=3 Foo=1,3 Quux=9-12,14-16,900 Zn=0,4294967294" },
- { "Zu16=0,65536", "Zu16=0,65536" },
+ { "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" },
{ "N-1=1,2", "N-1=1-2" },
{ "-1=4294967295", NULL },
{ "-1=3", "-1=3" },
@@ -316,8 +577,6 @@ test_protover_vote_roundtrip(void *args)
{ "Link=1,9-8,3", NULL },
{ "Faux=-0", NULL },
{ "Faux=0--0", NULL },
- // "These fail at the splitting stage in Rust, but the number parsing
- // stage in C."
{ "Faux=-1", NULL },
{ "Faux=-1-3", NULL },
{ "Faux=1--1", NULL },
@@ -326,10 +585,10 @@ test_protover_vote_roundtrip(void *args)
/* Large range */
{ "Sleen=1-501", "Sleen=1-501" },
{ "Sleen=1-65537", NULL },
- /* CPU/RAM DoS Loop: Rust only. */
- { "Sleen=0-2147483648", NULL },
- /* Rust seems to experience an internal error here. */
- { "Sleen=0-4294967295", NULL },
+ /* Both C/Rust implementations should be able to handle this mild DoS. */
+ { "Sleen=1-2147483648", NULL },
+ /* Rust tests are built in debug mode, so ints are bounds-checked. */
+ { "Sleen=1-4294967295", NULL },
};
unsigned u;
smartlist_t *votes = smartlist_new();
@@ -364,6 +623,10 @@ struct testcase_t protover_tests[] = {
PV_TEST(parse_fail, 0),
PV_TEST(vote, 0),
PV_TEST(all_supported, 0),
+ PV_TEST(list_supports_protocol_for_unsupported_returns_false, 0),
+ PV_TEST(list_supports_protocol_returns_true, 0),
+ PV_TEST(supports_version, 0),
+ PV_TEST(supported_protocols, 0),
PV_TEST(vote_roundtrip, 0),
END_OF_TESTCASES
};