From: Alberto Leiva Popper Date: Tue, 4 Sep 2018 21:17:34 +0000 (-0500) Subject: Implement RFC 7730 (TALs) X-Git-Tag: v0.0.2~128 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=72a350962b79b82eba62c151e107d171be90a22d;p=thirdparty%2FFORT-validator.git Implement RFC 7730 (TALs) --- diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 00000000..ef5e8ee5 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,3 @@ +AUTOMAKE_OPTIONS = foreign + +SUBDIRS = src test diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 00000000..042d19df --- /dev/null +++ b/autogen.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +# Hello. +# Run this file to generate the configure script. +# You'll need Autoconf and Automake installed! + +aclocal && automake --add-missing --copy && autoconf diff --git a/configure.ac b/configure.ac new file mode 100644 index 00000000..d65fdfb2 --- /dev/null +++ b/configure.ac @@ -0,0 +1,33 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ([2.69]) +# TODO change the bug report address +AC_INIT([rpki-validator], [0.0.1], [ydahhrk@gmail.com]) +AC_CONFIG_SRCDIR([src/main.c]) +AM_INIT_AUTOMAKE([subdir-objects]) + +# Checks for programs. +AC_PROG_CC + +# Checks for libraries. + +# Checks for header files. +AC_CHECK_HEADERS([netinet/in.h stdlib.h string.h unistd.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_TYPE_SIZE_T +AC_TYPE_SSIZE_T +AC_CHECK_HEADER_STDBOOL + +# Checks for library functions. +AC_FUNC_MALLOC +AC_CHECK_FUNCS([memset socket]) +AC_SEARCH_LIBS([pthread_create], [pthread]) + +# Check dependencies. +PKG_CHECK_MODULES([CHECK], [check]) +PKG_CHECK_MODULES([GLIB], [glib-2.0]) + +# Spit out the makefiles. +AC_OUTPUT(Makefile src/Makefile test/Makefile) diff --git a/deconf.sh b/deconf.sh new file mode 100755 index 00000000..6b3dba9e --- /dev/null +++ b/deconf.sh @@ -0,0 +1,13 @@ +make distclean +rm -frv \ + Makefile.in \ + aclocal.m4 \ + autom4te.cache \ + compile \ + configure \ + depcomp \ + install-sh \ + missing \ + man/Makefile.in \ + src/Makefile.in + diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 00000000..36722ef6 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,11 @@ +bin_PROGRAMS = rpki_validator + +rpki_validator_SOURCES = main.c +rpki_validator_SOURCES += common.h +rpki_validator_SOURCES += line_file.h +rpki_validator_SOURCES += line_file.c +rpki_validator_SOURCES += tal.h +rpki_validator_SOURCES += tal.c + +rpki_validator_CFLAGS = -pedantic -Wall -std=gnu11 -O3 ${GLIB_CFLAGS} +rpki_validator_LDADD = ${GLIB_LIBS} diff --git a/src/common.h b/src/common.h new file mode 100644 index 00000000..9c266206 --- /dev/null +++ b/src/common.h @@ -0,0 +1,6 @@ +#ifndef SRC_RTR_COMMON_H_ +#define SRC_RTR_COMMON_H_ + +#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) + +#endif /* SRC_RTR_COMMON_H_ */ diff --git a/src/line_file.c b/src/line_file.c new file mode 100644 index 00000000..59cb6660 --- /dev/null +++ b/src/line_file.c @@ -0,0 +1,152 @@ +#include "line_file.h" + +#include +#include +#include +#include + +struct line_file { + FILE *file; + const char *file_name; + size_t offset; +}; + +/* + * @file_name is expected to outlive the lfile. + */ +int +lfile_open(const char *file_name, struct line_file **result) +{ + struct line_file *lfile; + int err; + + lfile = malloc(sizeof(struct line_file)); + if (lfile == NULL) + return -ENOMEM; + + lfile->file = fopen(file_name, "r"); + if (lfile->file == NULL) { + err = errno; + free(lfile); + return err; + } + lfile->file_name = file_name; + lfile->offset = 0; + + *result = lfile; + return 0; +} + +void +lfile_close(struct line_file *lf) +{ + fclose(lf->file); + free(lf); +} + +/* + * On success, places the string in *result. + * On failure, returns error code. + * On EOF reached, returns zero but nullifies result. + * + * @result is allocated in the heap. + */ +int +lfile_read(struct line_file *lfile, char **result) +{ + char *string; + size_t alloc_len; + ssize_t len; + ssize_t i; + int err; + + /* + * Note to myself: + * + * getline() is very convoluted. I really don't like it. I'm actually + * considering getting rid of it and pulling off something that doesn't + * seem like it was designed by an alien, but it doesn't warrant going + * that far yet. Do not read its Linux man page; it didn't answer my + * questions. Go straight to POSIX instead. + * + * - If the file is empty, or all that's left is an empty line, it + * (confusingly) returns -1. errno will be 0, feof() should return + * 1, ferror() should return 0. + * - The fact that it returns the newline in the buffer is puzzling, + * because who the fuck wants that nonsense. You will want to remove + * it, BUT DON'T SWEAT IT IF IT'S NOT THERE, because the last line of + * the file might not be newline-terminated. + * - The string WILL be NULL-terminated, but the NULL chara will not be + * included in the returned length. BUT IT'S THERE. Don't worry about + * writing past the allocated space on the last line. + * - Newline is `\n` according to POSIX, which is good, because RFC 7730 + * agrees. You will have to worry about `\r`, though. + * + * Also, the Linux man page claims the following: + * + * [The out] buffer should be freed by the user program even if + * getline() failed. + * + * This... does not exist in the POSIX spec. But it does make sense + * because getline is normally meant to be used repeatedly with a + * recycled buffer. (free() is a no-op if its argument is NULL so go + * nuts.) + */ + + string = NULL; + alloc_len = 0; + len = getline(&string, &alloc_len, lfile->file); + + if (len == -1) { + err = errno; + free(string); + *result = NULL; + if (ferror(lfile->file)) + return err; + if (feof(lfile->file)) + return 0; + warnx("Supposedly unreachable code reached. ferror:%d feof:%d", + ferror(lfile->file), feof(lfile->file)); + return -EINVAL; + } + + lfile->offset += len; + + /* + * Make sure that strlen() matches len. + * We should make the best out of the fact that we didn't use fgets(), + * after all. + */ + for (i = 0; i < len; i++) { + if (string[i] == '\0') { + warnx("File %s has an illegal null character in its body. Please remove it.", + lfile_name(lfile)); + free(string); + return -EINVAL; + } + } + + if (len >= 2) { + if (string[len - 2] == '\r' && string[len - 1] == '\n') + string[len - 2] = '\0'; + } + if (len >= 1) { + if (string[len - 1] == '\n') + string[len - 1] = '\0'; + } + + *result = string; + return 0; +} + +const char * +lfile_name(struct line_file *lfile) +{ + return lfile->file_name; +} + +size_t +lfile_offset(struct line_file *lfile) +{ + return lfile->offset; +} diff --git a/src/line_file.h b/src/line_file.h new file mode 100644 index 00000000..ef882ac6 --- /dev/null +++ b/src/line_file.h @@ -0,0 +1,24 @@ +#ifndef LINE_FILE_H_ +#define LINE_FILE_H_ + +/* + * A "line file" is a text file that you want to read line-by-line. + * + * As defined by RFC7730 (the only current user of this code), lines are + * terminated by either CRLF or LF. + * (...which is the same as saying "lines are terminated by LF.") + */ + +#include + +struct line_file; + +int lfile_open(const char *, struct line_file **); +void lfile_close(); + +int lfile_read(struct line_file *, char **); + +const char *lfile_name(struct line_file *); +size_t lfile_offset(struct line_file *); + +#endif /* LINE_FILE_H_ */ diff --git a/src/main.c b/src/main.c new file mode 100644 index 00000000..94f713be --- /dev/null +++ b/src/main.c @@ -0,0 +1,7 @@ +#include + +int +main(void) +{ + return EXIT_SUCCESS; +} diff --git a/src/tal.c b/src/tal.c new file mode 100644 index 00000000..1c751aa6 --- /dev/null +++ b/src/tal.c @@ -0,0 +1,204 @@ +#include "tal.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "common.h" +#include "line_file.h" + +struct uri { + char *string; + SLIST_ENTRY(uri) next; +}; + +SLIST_HEAD(uri_list, uri); + +struct tal { + struct uri_list uris; + /* Decoded; not base64. */ + guchar *spki; + size_t spki_size; +}; + +static void +uri_destroy(struct uri *uri) +{ + free(uri->string); + free(uri); +} + +static void +uris_destroy(struct uri_list *uris) +{ + struct uri *uri; + + while (!SLIST_EMPTY(uris)) { + uri = SLIST_FIRST(uris); + SLIST_REMOVE_HEAD(uris, next); + uri_destroy(uri); + } +} + +static int +read_uri(struct line_file *lfile, struct uri **result) +{ + struct uri *uri; + int err; + + uri = malloc(sizeof(struct uri)); + if (uri == NULL) { + warnx("Out of memory"); + return -ENOMEM; + } + + err = lfile_read(lfile, &uri->string); + if (err) { + /* TODO have lfile_read print error msg */ + free(uri); + return err; + } + + *result = uri; + return 0; +} + +static int +read_uris(struct line_file *lfile, struct uri_list *uris) +{ + struct uri *previous, *uri; + int err; + + err = read_uri(lfile, &uri); + if (err) + return err; + + if (strcmp(uri->string, "") == 0) { + uri_destroy(uri); + warnx("TAL file %s contains no URIs", lfile_name(lfile)); + return -EINVAL; + } + + SLIST_INIT(uris); + SLIST_INSERT_HEAD(uris, uri, next); + + do { + previous = uri; + + err = read_uri(lfile, &uri); + if (err) + return err; + + if (strcmp(uri->string, "") == 0) { + uri_destroy(uri); + return 0; /* Happy path */ + } + + SLIST_INSERT_AFTER(previous, uri, next); + } while (true); +} + +/* + * Will usually allocate slightly more because of the newlines, but I'm fine + * with it. + */ +static size_t +get_spki_alloc_size(struct line_file *lfile) +{ + struct stat st; + size_t result; + + stat(lfile_name(lfile), &st); + result = st.st_size - lfile_offset(lfile); + + /* + * See the documentation for g_base64_decode_step(). + * I added `+ 1`. It's because `result / 4` truncates, and I'm not sure + * if the original equation meant to round up. + */ + return (result / 4 + 1) * 3 + 3; +} + +static int +read_spki(struct line_file *lfile, struct tal *tal) +{ + char *line; + gint state = 0; + guint save = 0; + int err; + + tal->spki = malloc(get_spki_alloc_size(lfile)); + if (tal->spki == NULL) + return -ENOMEM; + tal->spki_size = 0; + + do { + err = lfile_read(lfile, &line); + if (err) { + free(tal->spki); + return err; + } + + if (line == NULL) + return 0; + + tal->spki_size += g_base64_decode_step(line, strlen(line), + tal->spki + tal->spki_size, &state, &save); + free(line); + } while (true); +} + +int +tal_load(const char *file_name, struct tal **result) +{ + struct line_file *lfile; + struct tal *tal; + int err; + + err = lfile_open(file_name, &lfile); + if (err) + return err; + + tal = malloc(sizeof(struct tal)); + if (tal == NULL) { + lfile_close(lfile); + return -ENOMEM; + } + + err = read_uris(lfile, &tal->uris); + if (err) { + free(tal); + lfile_close(lfile); + return err; + } + + err = read_spki(lfile, tal); + if (err) { + uris_destroy(&tal->uris); + free(tal); + lfile_close(lfile); + return err; + } + + lfile_close(lfile); + *result = tal; + return 0; +} + +void tal_destroy(struct tal *tal) +{ + if (tal == NULL) + return; + + uris_destroy(&tal->uris); + free(tal->spki); + free(tal); +} diff --git a/src/tal.h b/src/tal.h new file mode 100644 index 00000000..9dfa869b --- /dev/null +++ b/src/tal.h @@ -0,0 +1,9 @@ +#ifndef TAL_H_ +#define TAL_H_ + +struct tal; + +int tal_load(const char *, struct tal **); +void tal_destroy(struct tal *); + +#endif /* TAL_H_ */ diff --git a/test/Makefile.am b/test/Makefile.am new file mode 100644 index 00000000..adbd3c72 --- /dev/null +++ b/test/Makefile.am @@ -0,0 +1,12 @@ +AM_CFLAGS = -pedantic -Wall -std=gnu11 -I../src ${CHECK_CFLAGS} +MY_LDADD = ${CHECK_LIBS} + +check_PROGRAMS = line_file.test tal.test +TESTS = ${check_PROGRAMS} + +line_file_test_SOURCES = line_file_test.c ../src/line_file.c ../src/line_file.h +line_file_test_LDADD = ${MY_LDADD} + +tal_test_SOURCES = tal_test.c ../src/line_file.c ../src/line_file.h +tal_test_CFLAGS = ${AM_CFLAGS} ${GLIB_CFLAGS} +tal_test_LDADD = ${MY_LDADD} ${GLIB_LIBS} diff --git a/test/line_file/core.txt b/test/line_file/core.txt new file mode 100644 index 00000000..211243da --- /dev/null +++ b/test/line_file/core.txt @@ -0,0 +1,6 @@ +This is a normal line. +This is also a normal line, but the following one is empty. + +This one ends with \r\n. +This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. +This line does not end with a newline. \ No newline at end of file diff --git a/test/line_file/empty.txt b/test/line_file/empty.txt new file mode 100644 index 00000000..e69de29b diff --git a/test/line_file/error.txt b/test/line_file/error.txt new file mode 100644 index 00000000..f6578627 Binary files /dev/null and b/test/line_file/error.txt differ diff --git a/test/line_file_test.c b/test/line_file_test.c new file mode 100644 index 00000000..ed8004a7 --- /dev/null +++ b/test/line_file_test.c @@ -0,0 +1,121 @@ +#include "line_file.h" + +#include +#include +#include + +START_TEST(file_line_normal) +{ + struct line_file *lfile; + char *string, *long_string; + char *SENTENCE; + size_t SENTENCE_LEN; + unsigned int i; + + ck_assert_int_eq(lfile_open("line_file/core.txt", &lfile), 0); + + ck_assert_int_eq(lfile_read(lfile, &string), 0); + ck_assert_str_eq(string, "This is a normal line."); + free(string); + + ck_assert_int_eq(lfile_read(lfile, &string), 0); + ck_assert_str_eq(string, "This is also a normal line, but the following one is empty."); + free(string); + + ck_assert_int_eq(lfile_read(lfile, &string), 0); + ck_assert_str_eq(string, ""); + free(string); + + ck_assert_int_eq(lfile_read(lfile, &string), 0); + ck_assert_str_eq(string, "This one ends with \\r\\n."); + free(string); + + SENTENCE = "This is a very long line. "; + SENTENCE_LEN = strlen(SENTENCE); + long_string = malloc(316 * SENTENCE_LEN + 1); + ck_assert(long_string); + for (i = 0; i < 316; i++) + strcpy(long_string + i * SENTENCE_LEN, SENTENCE); + ck_assert_int_eq(lfile_read(lfile, &string), 0); + ck_assert_str_eq(string, long_string); + free(long_string); + free(string); + + ck_assert_int_eq(lfile_read(lfile, &string), 0); + ck_assert_str_eq(string, "This line does not end with a newline."); + free(string); + + ck_assert_int_eq(lfile_read(lfile, &string), 0); + ck_assert(string == NULL); + + lfile_close(lfile); +} +END_TEST + +START_TEST(file_line_empty) +{ + struct line_file *lfile; + char *string; + + ck_assert_int_eq(lfile_open("line_file/empty.txt", &lfile), 0); + + ck_assert_int_eq(lfile_read(lfile, &string), 0); + ck_assert(string == NULL); + + lfile_close(lfile); +} +END_TEST + +START_TEST(file_line_null_chara) +{ + struct line_file *lfile; + char *string; + + ck_assert_int_eq(lfile_open("line_file/error.txt", &lfile), 0); + + ck_assert_int_eq(lfile_read(lfile, &string), 0); + ck_assert_str_eq(string, "This is a normal line."); + free(string); + + ck_assert_int_eq(lfile_read(lfile, &string), -EINVAL); + + lfile_close(lfile); +} +END_TEST + +Suite *lfile_read_suite(void) +{ + Suite *suite; + TCase *core, *limits, *errors; + + core = tcase_create("Core"); + tcase_add_test(core, file_line_normal); + + limits = tcase_create("Limits"); + tcase_add_test(limits, file_line_empty); + + errors = tcase_create("Errors"); + tcase_add_test(errors, file_line_null_chara); + + suite = suite_create("lfile_read()"); + suite_add_tcase(suite, core); + suite_add_tcase(suite, limits); + suite_add_tcase(suite, errors); + return suite; +} + +int main(void) +{ + Suite *suite; + SRunner *runner; + int tests_failed; + + suite = lfile_read_suite(); + + runner = srunner_create(suite); + srunner_run_all(runner, CK_NORMAL); + tests_failed = srunner_ntests_failed(runner); + srunner_free(runner); + + return (tests_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/test/tal/lacnic.tal b/test/tal/lacnic.tal new file mode 100644 index 00000000..62bda32d --- /dev/null +++ b/test/tal/lacnic.tal @@ -0,0 +1,11 @@ +rsync://repository.lacnic.net/rpki/lacnic/rta-lacnic-rpki.cer +http://potato +rsync://potato + +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqZEzhYK0+PtDOPfub/KR +c3MeWx3neXx4/wbnJWGbNAtbYqXg3uU5J4HFzPgk/VIppgSKAhlO0H60DRP48by9 +gr5/yDHu2KXhOmnMg46sYsUIpfgtBS9+VtrqWziJfb+pkGtuOWeTnj6zBmBNZKK+ +5AlMCW1WPhrylIcB+XSZx8tk9GS/3SMQ+YfMVwwAyYjsex14Uzto4GjONALE5oh1 +M3+glRQduD6vzSwOD+WahMbc9vCOTED+2McLHRKgNaQf0YJ9a1jG9oJIvDkKXEqd +fqDRktwyoD74cV57bW3tBAexB7GglITbInyQAsmdngtfg2LUMrcROHHP86QPZINj +DQIDAQAB diff --git a/test/tal_test.c b/test/tal_test.c new file mode 100644 index 00000000..b6015de7 --- /dev/null +++ b/test/tal_test.c @@ -0,0 +1,89 @@ +#include "tal.c" + +#include +#include +#include + +START_TEST(tal_load_normal) +{ + struct tal *tal; + struct uri *uri; + unsigned int i; + /* Got this by feeding the subjectPublicKeyInfo to `base64 -d`. */ + unsigned char decoded[] = { + 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, + 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, + 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, + 0xA9, 0x91, 0x33, 0x85, 0x82, 0xB4, 0xF8, 0xFB, 0x43, 0x38, 0xF7, + 0xEE, 0x6F, 0xF2, 0x91, 0x73, 0x73, 0x1E, 0x5B, 0x1D, 0xE7, 0x79, + 0x7C, 0x78, 0xFF, 0x06, 0xE7, 0x25, 0x61, 0x9B, 0x34, 0x0B, 0x5B, + 0x62, 0xA5, 0xE0, 0xDE, 0xE5, 0x39, 0x27, 0x81, 0xC5, 0xCC, 0xF8, + 0x24, 0xFD, 0x52, 0x29, 0xA6, 0x04, 0x8A, 0x02, 0x19, 0x4E, 0xD0, + 0x7E, 0xB4, 0x0D, 0x13, 0xF8, 0xF1, 0xBC, 0xBD, 0x82, 0xBE, 0x7F, + 0xC8, 0x31, 0xEE, 0xD8, 0xA5, 0xE1, 0x3A, 0x69, 0xCC, 0x83, 0x8E, + 0xAC, 0x62, 0xC5, 0x08, 0xA5, 0xF8, 0x2D, 0x05, 0x2F, 0x7E, 0x56, + 0xDA, 0xEA, 0x5B, 0x38, 0x89, 0x7D, 0xBF, 0xA9, 0x90, 0x6B, 0x6E, + 0x39, 0x67, 0x93, 0x9E, 0x3E, 0xB3, 0x06, 0x60, 0x4D, 0x64, 0xA2, + 0xBE, 0xE4, 0x09, 0x4C, 0x09, 0x6D, 0x56, 0x3E, 0x1A, 0xF2, 0x94, + 0x87, 0x01, 0xF9, 0x74, 0x99, 0xC7, 0xCB, 0x64, 0xF4, 0x64, 0xBF, + 0xDD, 0x23, 0x10, 0xF9, 0x87, 0xCC, 0x57, 0x0C, 0x00, 0xC9, 0x88, + 0xEC, 0x7B, 0x1D, 0x78, 0x53, 0x3B, 0x68, 0xE0, 0x68, 0xCE, 0x34, + 0x02, 0xC4, 0xE6, 0x88, 0x75, 0x33, 0x7F, 0xA0, 0x95, 0x14, 0x1D, + 0xB8, 0x3E, 0xAF, 0xCD, 0x2C, 0x0E, 0x0F, 0xE5, 0x9A, 0x84, 0xC6, + 0xDC, 0xF6, 0xF0, 0x8E, 0x4C, 0x40, 0xFE, 0xD8, 0xC7, 0x0B, 0x1D, + 0x12, 0xA0, 0x35, 0xA4, 0x1F, 0xD1, 0x82, 0x7D, 0x6B, 0x58, 0xC6, + 0xF6, 0x82, 0x48, 0xBC, 0x39, 0x0A, 0x5C, 0x4A, 0x9D, 0x7E, 0xA0, + 0xD1, 0x92, 0xDC, 0x32, 0xA0, 0x3E, 0xF8, 0x71, 0x5E, 0x7B, 0x6D, + 0x6D, 0xED, 0x04, 0x07, 0xB1, 0x07, 0xB1, 0xA0, 0x94, 0x84, 0xDB, + 0x22, 0x7C, 0x90, 0x02, 0xC9, 0x9D, 0x9E, 0x0B, 0x5F, 0x83, 0x62, + 0xD4, 0x32, 0xB7, 0x11, 0x38, 0x71, 0xCF, 0xF3, 0xA4, 0x0F, 0x64, + 0x83, 0x63, 0x0D, 0x02, 0x03, 0x01, 0x00, 0x01 + }; + + ck_assert_int_eq(tal_load("tal/lacnic.tal", &tal), 0); + + uri = SLIST_FIRST(&tal->uris); + ck_assert_str_eq(uri->string, "rsync://repository.lacnic.net/rpki/lacnic/rta-lacnic-rpki.cer"); + uri = SLIST_NEXT(uri, next); + ck_assert_str_eq(uri->string, "http://potato"); + uri = SLIST_NEXT(uri, next); + ck_assert_str_eq(uri->string, "rsync://potato"); + uri = SLIST_NEXT(uri, next); + ck_assert(uri == NULL); + + ck_assert_uint_eq(ARRAY_SIZE(decoded), tal->spki_size); + for (i = 0; i < ARRAY_SIZE(decoded); i++) + ck_assert_uint_eq(tal->spki[i], decoded[i]); + + tal_destroy(tal); +} +END_TEST + +Suite *tal_load_suite(void) +{ + Suite *suite; + TCase *core; + + core = tcase_create("Core"); + tcase_add_test(core, tal_load_normal); + + suite = suite_create("lfile_read()"); + suite_add_tcase(suite, core); + return suite; +} + +int main(void) +{ + Suite *suite; + SRunner *runner; + int tests_failed; + + suite = tal_load_suite(); + + runner = srunner_create(suite); + srunner_run_all(runner, CK_NORMAL); + tests_failed = srunner_ntests_failed(runner); + srunner_free(runner); + + return (tests_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +}