return error;
}
+static int
+parse_notification_snapshot(xmlTextReaderPtr reader,
+ struct update_notification *notif)
+{
+ int error;
+
+ error = parse_file_metadata(reader, NULL, HR_MANDATORY, ¬if->snapshot);
+ if (error)
+ return error;
+
+ if (!uri_same_origin(notif->uri, notif->snapshot.uri))
+ return pr_val_err("Notification %s and Snapshot %s are not hosted by the same origin.",
+ uri_get_global(notif->uri), uri_get_global(notif->snapshot.uri));
+
+ return 0;
+}
+
static int
parse_notification_delta(xmlTextReaderPtr reader,
struct update_notification *notif)
return error;
}
+ if (!uri_same_origin(notif->uri, delta.meta.uri))
+ return pr_val_err("Notification %s and Delta %s are not hosted by the same origin.",
+ uri_get_global(notif->uri), uri_get_global(delta.meta.uri));
+
notification_deltas_add(¬if->deltas, &delta);
return 0;
}
if (xmlStrEqual(name, BAD_CAST RRDP_ELEM_DELTA)) {
return parse_notification_delta(reader, notif);
} else if (xmlStrEqual(name, BAD_CAST RRDP_ELEM_SNAPSHOT)) {
- return parse_file_metadata(reader, NULL, HR_MANDATORY,
- ¬if->snapshot);
+ return parse_notification_snapshot(reader, notif);
} else if (xmlStrEqual(name, BAD_CAST RRDP_ELEM_NOTIFICATION)) {
/* No need to validate session ID and serial */
return parse_session(reader, ¬if->session);
return strcmp(u1->global, u2->global) == 0;
}
+bool
+uri_same_origin(struct rpki_uri *u1, struct rpki_uri *u2)
+{
+ char const *g1, *g2;
+ size_t c, slashes;
+
+ g1 = u1->global;
+ g2 = u2->global;
+ slashes = 0;
+
+ for (c = 0; g1[c] == g2[c]; c++) {
+ switch (g1[c]) {
+ case '/':
+ slashes++;
+ if (slashes == 3)
+ return true;
+ break;
+ case '\0':
+ return slashes == 2;
+ }
+ }
+
+ if (g1[c] == '\0')
+ return (slashes == 2) && g2[c] == '/';
+ if (g2[c] == '\0')
+ return (slashes == 2) && g1[c] == '/';
+
+ return false;
+}
+
/* @ext must include the period. */
bool
uri_has_extension(struct rpki_uri *uri, char const *ext)
char const *uri_get_local(struct rpki_uri *);
bool uri_equals(struct rpki_uri *, struct rpki_uri *);
+bool uri_same_origin(struct rpki_uri *, struct rpki_uri *);
bool uri_has_extension(struct rpki_uri *, char const *);
bool uri_is_certificate(struct rpki_uri *);
}
END_TEST
+static void
+init_uri(struct rpki_uri *uri, char *global, char *local, enum uri_type type)
+{
+ uri->global = global;
+ uri->local = local;
+ uri->type = type;
+ uri->references = 1;
+}
+
+#define init_notif_uri(u, g, l) init_uri(u, g, l, UT_NOTIF)
+
START_TEST(test_parse_notification_ok)
{
- struct rpki_uri uri = { 0 };
+ struct rpki_uri uri;
struct update_notification notif;
ck_assert_int_eq(0, relax_ng_init());
- uri.local = "resources/rrdp/notif-ok.xml";
- uri.type = UT_NOTIF;
- uri.references = 1;
+ init_notif_uri(&uri, "https://host/notification.xml", "resources/rrdp/notif-ok.xml");
ck_assert_int_eq(0, parse_notification(&uri, ¬if));
ck_assert_str_eq("9df4b597-af9e-4dca-bdda-719cce2c4e28", (char const *)notif.session.session_id);
START_TEST(test_parse_notification_0deltas)
{
- struct rpki_uri uri = { 0 };
+ struct rpki_uri uri;
struct update_notification notif;
ck_assert_int_eq(0, relax_ng_init());
- uri.local = "resources/rrdp/notif-0deltas.xml";
- uri.type = UT_NOTIF;
- uri.references = 1;
+ init_notif_uri(&uri, "https://host/notification.xml", "resources/rrdp/notif-0deltas.xml");
ck_assert_int_eq(0, parse_notification(&uri, ¬if));
ck_assert_str_eq("9df4b597-af9e-4dca-bdda-719cce2c4e28", (char const *)notif.session.session_id);
START_TEST(test_parse_notification_large_serial)
{
- struct rpki_uri uri = { 0 };
+ struct rpki_uri uri;
struct update_notification notif;
ck_assert_int_eq(0, relax_ng_init());
- uri.local = "resources/rrdp/notif-large-serial.xml";
- uri.type = UT_NOTIF;
- uri.references = 1;
+ init_notif_uri(&uri, "https://host/notification.xml", "resources/rrdp/notif-large-serial.xml");
ck_assert_int_eq(0, parse_notification(&uri, ¬if));
ck_assert_str_eq("9df4b597-af9e-4dca-bdda-719cce2c4e28", (char const *)notif.session.session_id);
static void
test_parse_notification_error(char *file)
{
- struct rpki_uri uri = { 0 };
+ struct rpki_uri uri;
struct update_notification notif;
ck_assert_int_eq(0, relax_ng_init());
- uri.local = file;
- uri.type = UT_NOTIF;
- uri.references = 1;
+ init_notif_uri(&uri, "https://host/notification.xml", file);
ck_assert_int_eq(-EINVAL, parse_notification(&uri, ¬if));
relax_ng_cleanup();
ck_assert_int_eq(0, relax_ng_init());
- notif_uri.global = "https://example.com/notification.xml";
- notif_uri.local = "cache/example.com/notification.xml";
- notif_uri.type = UT_NOTIF;
- notif_uri.references = 1;
-
- snapshot_uri.local = "resources/rrdp/snapshot-bad-publish.xml";
- snapshot_uri.references = 1;
+ init_notif_uri(¬if_uri, "https://example.com/notification.xml", "cache/example.com/notification.xml");
+ init_uri(&snapshot_uri, "https://example.com/snapshot.xml", "resources/rrdp/snapshot-bad-publish.xml", UT_TMP);
notif.session.session_id = "9df4b597-af9e-4dca-bdda-719cce2c4e28";
notif.session.serial.str = "2";
}
END_TEST
+static bool
+same_origin(char *g1, char *g2)
+{
+ struct rpki_uri u1 = { .type = UT_NOTIF, .references = 1 };
+ struct rpki_uri u2 = { .type = UT_TMP, .references = 1 };
+ u1.global = g1;
+ u2.global = g2;
+ return uri_same_origin(&u1, &u2);
+}
+
+START_TEST(test_same_origin)
+{
+ ck_assert_int_eq(true, same_origin("https://a.b.c/d/e/f", "https://a.b.c/g/h/i"));
+ ck_assert_int_eq(false, same_origin("https://a.b.cc/d/e/f", "https://a.b.c/g/h/i"));
+ ck_assert_int_eq(false, same_origin("https://a.b.c/d/e/f", "https://a.b.cc/g/h/i"));
+ ck_assert_int_eq(true, same_origin("https://a.b.c", "https://a.b.c"));
+ ck_assert_int_eq(true, same_origin("https://a.b.c/", "https://a.b.c"));
+ ck_assert_int_eq(true, same_origin("https://a.b.c", "https://a.b.c/"));
+ ck_assert_int_eq(true, same_origin("https://", "https://"));
+ ck_assert_int_eq(false, same_origin("https://", "https://a"));
+ ck_assert_int_eq(false, same_origin("https://a", "https://b"));
+
+ /* Undefined, but manhandle the code anyway */
+ ck_assert_int_eq(false, same_origin("", ""));
+ ck_assert_int_eq(false, same_origin("ht", "ht"));
+ ck_assert_int_eq(false, same_origin("https:", "https:"));
+ ck_assert_int_eq(false, same_origin("https:/", "https:/"));
+ ck_assert_int_eq(false, same_origin("https:/a", "https:/a"));
+ ck_assert_int_eq(true, same_origin("https:/a/", "https:/a/"));
+}
+END_TEST
+
static Suite *address_load_suite(void)
{
Suite *suite;
tcase_add_test(core, test_constructor);
tcase_add_test(core, check_validate_current_directory);
tcase_add_test(core, check_caged);
+ tcase_add_test(core, test_same_origin);
suite = suite_create("Encoding checking");
suite_add_tcase(suite, core);