fort_SOURCES += file.h file.c
fort_SOURCES += init.h init.c
fort_SOURCES += json_util.c json_util.h
-fort_SOURCES += line_file.h line_file.c
fort_SOURCES += log.h log.c
fort_SOURCES += nid.h nid.c
fort_SOURCES += output_printer.h output_printer.c
struct file_contents fc;
int error;
- error = file_load(uri_get_local(uri), &fc);
+ error = file_load(uri_get_local(uri), &fc, true);
if (error)
return error;
#include <openssl/buffer.h>
#include <openssl/err.h>
#include <openssl/evp.h>
+
#include "alloc.h"
+#include "log.h"
-/*
- * Reference: openbsd/src/usr.bin/openssl/enc.c
- *
- * @in: The BIO that will stream the base64 encoded string you want to decode.
- * @out: Buffer where this function will write the decoded string.
- * @has_nl: Encoded string has newline char?
- * @out_len: Total allocated size of @out. It's supposed to be the result of
- * EVP_DECODE_LENGTH(<size of the encoded string>).
- * @out_written: This function will write the actual number of decoded bytes
- * here.
- *
- * Returns true on success, false on failure. If the caller wants to print
- * errors, do it with the crypto functions. If not, remember to clean
- * libcrypto's error queue somehow.
- *
- * TODO (fine) Callers always do a bunch of boilerplate; refactor.
- */
+/* Simple decode base64 string. Returns true on success, false on failure. */
bool
-base64_decode(BIO *in, unsigned char *out, bool has_nl, size_t out_len,
- size_t *out_written)
+base64_decode(char *in, size_t in_len, unsigned char **out, size_t *out_len)
{
- BIO *b64;
- size_t offset = 0;
- int written = 0;
- bool success = false;
+ unsigned char *result;
+ EVP_ENCODE_CTX *ctx;
+ int outl;
+ int status;
- /*
- * BTW: The libcrypto API is perplexing.
- * Peeking at the error stack is the only way I found to figure out
- * whether some of the functions error'd.
- * But since it's not documented that it's supposed to work this way,
- * there's no guarantee that it will catch all errors.
- * But it will have to do. It's better than nothing.
- */
-
- /* Assume that the caller took care of handling any previous errors. */
- ERR_clear_error();
+ if (in_len == 0)
+ in_len = strlen(in);
/*
- * BIO_f_base64() cannot fail because it's dead-simple by definition.
- * BIO_new() can, and it will lead to NULL. But only *some* errors will
- * populate the error stack.
+ * Will usually allocate more because of the newlines,
+ * but I'm at peace with it.
*/
- b64 = BIO_new(BIO_f_base64());
- if (b64 == NULL)
- return false;
+ result = pmalloc(EVP_DECODE_LENGTH(in_len));
- /*
- * BIO_push() can technically fail through BIO_ctrl(), but it ignores
- * the error. This will not cause it to revert the push, so we have to
- * do it ourselves.
- *
- * BTW: I'm assigning the result of BIO_push() to @in (instead of @b64
- * or, more logically, throwing it away) because the sample reference in
- * enc.c does it that way.
- * But the writer of enc.c probably overcomplicated things.
- * It shouldn't make a difference. We don't need @in anymore; just
- * assume both @b64 and @in now point to the same BIO, which is @b64.
- */
- in = BIO_push(b64, in);
+ ctx = EVP_ENCODE_CTX_new();
+ if (ctx == NULL)
+ enomem_panic();
- /*
- * Should we ignore this error? BIO_ctrl(BIO_CTRL_PUSH) performs some
- * "internal, used to signify change" thing, whose importance is
- * undefined due to BIO_ctrl()'s callback spaghetti.
- * Let's be strict, I guess.
- */
- if (ERR_peek_last_error() != 0)
- goto end;
+ EVP_DecodeInit(ctx);
- if (!has_nl)
- BIO_set_flags(in, BIO_FLAGS_BASE64_NO_NL); /* Cannot fail */
+ status = EVP_DecodeUpdate(ctx, result, &outl, (unsigned char *)in, in_len);
+ if (status == -1)
+ return false;
- do {
- /*
- * Do not move this after BIO_read().
- * BIO_read() can return negative, which does not necessarily
- * imply error, and which ruins the counter.
- */
- offset += written;
- written = BIO_read(in, out + offset, out_len - offset);
- } while (written > 0);
-
- /* BIO_read() can fail. It does not return status. */
- if (ERR_peek_last_error() != 0)
- goto end;
-
- *out_written = offset;
- success = true;
-
-end:
- /*
- * BIO_pop() can also fail due to BIO_ctrl(), but we will ignore this
- * because whatever "signify change" crap happens, it can't possibly be
- * damaging enough to prevent us from releasing b64. I hope.
- */
- BIO_pop(b64);
- /* Returns 0 on failure, but that's only if b64 is NULL. Meaningless. */
- BIO_free(b64);
+ *out_len = outl;
- return success;
+ status = EVP_DecodeFinal(ctx, result + outl, &outl);
+ if (status != 1)
+ return false;
+
+ *out = result;
+ *out_len += outl;
+ return true;
}
/*
base64url_decode(char const *str_encoded, unsigned char **result,
size_t *result_len)
{
- BIO *encoded; /* base64 encoded. */
char *str_copy;
- size_t encoded_len, alloc_size, dec_len;
- int pad, i;
+ size_t encoded_len;
+ size_t pad;
+ size_t i;
+ bool success;
/*
* Apparently there isn't a base64url decoder, and there isn't
}
/* Now decode as regular base64 */
- encoded = BIO_new_mem_buf(str_copy, -1);
- if (encoded == NULL)
- goto free_copy;
-
- alloc_size = EVP_DECODE_LENGTH(strlen(str_copy));
- *result = pzalloc(alloc_size + 1);
-
- if (!base64_decode(encoded, *result, false, alloc_size, &dec_len))
- goto free_all;
-
- if (dec_len == 0)
- goto free_all;
-
- *result_len = dec_len;
+ success = base64_decode(str_copy, encoded_len + pad, result, result_len);
free(str_copy);
- BIO_free(encoded);
- return true;
-
-free_all:
- free(*result);
- BIO_free(encoded);
-free_copy:
- free(str_copy);
- return false;
+ return success;
}
static char *
#ifndef SRC_BASE64_H_
#define SRC_BASE64_H_
-#include <openssl/bio.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
-bool base64_decode(BIO *, unsigned char *, bool, size_t, size_t *);
-bool base64url_decode(char const *, unsigned char **, size_t *);
+bool base64_decode(char *, size_t, unsigned char **, size_t *);
+bool base64url_decode(char const *, unsigned char **, size_t *);
bool base64url_encode(unsigned char const *, int, char **);
#endif /* SRC_BASE64_H_ */
pr_val_err("fclose() failed: %s", strerror(errno));
}
+/*
+ * If !is_binary, will append a null character. That's all.
+ */
int
-file_load(char const *file_name, struct file_contents *fc)
+file_load(char const *file_name, struct file_contents *fc, bool is_binary)
{
FILE *file;
struct stat stat;
return error;
fc->buffer_size = stat.st_size;
- fc->buffer = pmalloc(fc->buffer_size);
+ fc->buffer = pmalloc(fc->buffer_size + !is_binary);
+
+ if (!is_binary)
+ fc->buffer[stat.st_size] = '\0';
fread_result = fread(fc->buffer, 1, fc->buffer_size, file);
if (fread_result < fc->buffer_size) {
int file_write(char const *, FILE **);
void file_close(FILE *);
-int file_load(char const *, struct file_contents *);
+int file_load(char const *, struct file_contents *, bool);
void file_free(struct file_contents *);
int file_exists(char const *);
+++ /dev/null
-#include "line_file.h"
-
-#include "alloc.h"
-#include "file.h"
-#include "log.h"
-
-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 error;
-
- lfile = pmalloc(sizeof(struct line_file));
-
- lfile->file = fopen(file_name, "r");
- if (lfile->file == NULL) {
- error = errno;
- free(lfile);
- return error;
- }
- lfile->file_name = file_name;
- lfile->offset = 0;
-
- *result = lfile;
- return 0;
-}
-
-void
-lfile_close(struct line_file *lf)
-{
- file_close(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 error;
-
- /*
- * 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.
- * - It includes the newline in the result, which is puzzling. 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 8630
- * 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.)
- *
- * Update: If you remove getline(), consider downgrading _POSIX_C_SOURCE
- * to 200112L. (And _XOPEN_SOURCE to 600.)
- */
-
- string = NULL;
- alloc_len = 0;
- len = getline(&string, &alloc_len, lfile->file);
-
- if (len == -1) {
- error = errno;
- free(string);
- *result = NULL;
- if (ferror(lfile->file)) {
- pr_op_err("Error while reading file: %s",
- strerror(error));
- return error;
- }
- if (feof(lfile->file))
- return 0;
- pr_crit("Supposedly unreachable code reached. ferror:%d feof:%d",
- ferror(lfile->file), feof(lfile->file));
- }
-
- 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') {
- pr_op_err("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;
-}
-
-FILE *
-lfile_fd(struct line_file *lfile)
-{
- return lfile->file;
-}
-
-const char *
-lfile_name(struct line_file *lfile)
-{
- return lfile->file_name;
-}
-
-size_t
-lfile_offset(struct line_file *lfile)
-{
- return lfile->offset;
-}
+++ /dev/null
-#ifndef LINE_FILE_H_
-#define LINE_FILE_H_
-
-/*
- * A "line file" is a text file that you want to read line-by-line.
- *
- * Lines are terminated by either CRLF or LF.
- * (...which is the same as saying "lines are terminated by LF.")
- */
-
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-struct line_file;
-
-int lfile_open(const char *, struct line_file **);
-void lfile_close(struct line_file *lf);
-
-int lfile_read(struct line_file *, char **);
-
-FILE *lfile_fd(struct line_file *);
-const char *lfile_name(struct line_file *);
-size_t lfile_offset(struct line_file *);
-
-#endif /* LINE_FILE_H_ */
#include "object/tal.h"
+#include <ctype.h>
#include <errno.h>
#include <openssl/evp.h>
#include <sys/queue.h>
#include "cert_stack.h"
#include "common.h"
#include "config.h"
-#include "line_file.h"
+#include "file.h"
#include "log.h"
#include "state.h"
#include "thread_var.h"
struct db_table *db;
};
+static char *
+find_newline(char *str)
+{
+ for (; true; str++) {
+ if (str[0] == '\0')
+ return NULL;
+ if (str[0] == '\n')
+ return str;
+ if (str[0] == '\r' && str[1] == '\n')
+ return str;
+ }
+}
+
+static bool
+is_blank(char const *str)
+{
+ for (; str[0] != '\0'; str++)
+ if (!isspace(str[0]))
+ return false;
+ return true;
+}
+
static int
-add_uri(struct uri_list *uris, char const *tal, char *uri)
+add_uri(struct tal *tal, char *uri)
{
struct rpki_uri *new = NULL;
int error;
if (str_starts_with(uri, "rsync://"))
- error = uri_create(&new, tal, UT_RSYNC, false, NULL, uri);
+ error = uri_create(&new, tal->file_name, UT_RSYNC, false, NULL, uri);
else if (str_starts_with(uri, "https://"))
- error = uri_create(&new, tal, UT_HTTPS, false, NULL, uri);
+ error = uri_create(&new, tal->file_name, UT_HTTPS, false, NULL, uri);
else
return pr_op_err("TAL has non-RSYNC/HTTPS URI: %s", uri);
if (error)
return error;
- uris_add(uris, new);
+ uris_add(&tal->uris, new);
return 0;
}
static int
-read_uris(struct line_file *lfile, char const *tal, struct uri_list *uris)
+read_content(char *fc /* File Content */, struct tal *tal)
{
- char *uri;
+ char *nl; /* New Line */
+ bool cr; /* Carriage return */
int error;
- error = lfile_read(lfile, &uri);
- if (error)
- return error;
-
- if (uri == NULL)
- return pr_op_err("TAL file is empty.");
- if (strcmp(uri, "") == 0) {
- free(uri);
- return pr_op_err("There's no URI in the first line of the TAL.");
- } else if (strncmp(uri, "#", 1) == 0) {
- /* More comments expected, or an URI */
- do {
- free(uri); /* Ignore the comment */
- error = lfile_read(lfile, &uri);
- if (error)
- return error;
- if (uri == NULL)
- return pr_op_err("TAL file ended prematurely. (Expected more comments or an URI list.)");
- if (strcmp(uri, "") == 0) {
- free(uri);
- return pr_op_err("TAL file comments syntax error. (Expected more comments or an URI list.)");
- }
- /* Not a comment, probably the URI(s) */
- if (strncmp(uri, "#", 1) != 0)
- break;
- } while (true);
+ /* Comment section */
+ while (fc[0] == '#') {
+ nl = strchr(fc, '\n');
+ if (!nl)
+ goto premature;
+ fc = nl + 1;
}
+ /* URI section */
do {
- error = add_uri(uris, tal, uri);
- free(uri); /* Won't be needed anymore */
- if (error)
- return error;
+ nl = find_newline(fc);
+ if (!nl)
+ goto premature;
- error = lfile_read(lfile, &uri);
+ cr = (nl[0] == '\r');
+ nl[0] = '\0';
+ if (is_blank(fc))
+ break;
+
+ error = add_uri(tal, fc);
if (error)
return error;
- if (uri == NULL)
- return pr_op_err("TAL file ended prematurely. (Expected URI list, blank line and public key.)");
- if (strcmp(uri, "") == 0) {
- free(uri);
- return 0; /* Happy path */
- }
+ fc = nl + cr + 1;
+ if (*fc == '\0')
+ return pr_op_err("The TAL seems to be missing the public key.");
} while (true);
-}
-
-static size_t
-get_spki_orig_size(struct line_file *lfile)
-{
- struct stat st;
- size_t result;
-
- stat(lfile_name(lfile), &st);
- result = st.st_size - lfile_offset(lfile);
- return result;
-}
-
-/*
- * 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)
-{
- return EVP_DECODE_LENGTH(get_spki_orig_size(lfile));
-}
-
-static char *
-locate_char(char *str, size_t len, char find)
-{
- size_t i;
-
- for (i = 0; i < len; i++)
- if (str[i] == find)
- return str + i;
- return NULL;
-}
-
-/*
- * Get the base64 chars from @lfile and allocate to @out with lines no greater
- * than 65 chars (including line feed).
- *
- * Why? LibreSSL doesn't like lines greater than 80 chars, so use a common
- * length per line.
- */
-static int
-base64_sanitize(struct line_file *lfile, char **out)
-{
-#define BUF_SIZE 65
- FILE *fd;
- char *buf, *result, *eol;
- size_t original_size, new_size;
- size_t fread_result, offset;
- int error;
- /*
- * lfile_read() isn't called since the lines aren't returned as needed
- * "sanitized" (a.k.a. each line with a desired length)
- */
- original_size = get_spki_orig_size(lfile);
- new_size = original_size + (original_size / BUF_SIZE);
- result = pmalloc(new_size + 1);
- buf = pmalloc(BUF_SIZE);
-
- fd = lfile_fd(lfile);
- offset = 0;
- while ((fread_result = fread(buf, 1,
- (original_size > BUF_SIZE) ? BUF_SIZE : original_size, fd)) > 0) {
- error = ferror(lfile_fd(lfile));
- if (error) {
- /*
- * The manpage doesn't say that the result is an error
- * code. It literally doesn't say how to get an error
- * code.
- */
- pr_op_err("File reading error. Presumably, the error message is '%s.'",
- strerror(error));
- goto free_result;
- }
-
- original_size -= fread_result;
- eol = locate_char(buf, fread_result, '\n');
- /* Larger than buffer length, add LF and copy last char */
- if (eol == NULL) {
- memcpy(&result[offset], buf, fread_result - 1);
- offset += fread_result - 1;
- result[offset] = '\n';
- result[offset + 1] = buf[fread_result - 1];
- offset += 2;
- continue;
- }
- /* Copy till last LF */
- memcpy(&result[offset], buf, eol - buf + 1);
- offset += eol - buf + 1;
- if (eol - buf + 1 < fread_result) {
- /* And add new line with remaining chars */
- memcpy(&result[offset], eol + 1,
- buf + fread_result - 1 - eol);
- offset += buf + fread_result -1 - eol;
- result[offset] = '\n';
- offset++;
- }
- }
- /* Reallocate to exact size and add nul char */
- if (offset != new_size)
- result = prealloc(result, offset + 1);
- free(buf);
- result[offset] = '\0';
-
- *out = result;
- return 0;
-free_result:
- free(buf);
- free(result);
- return error;
-#undef BUF_SIZE
-}
-
-static int
-read_spki(struct line_file *lfile, struct tal *tal)
-{
- BIO *encoded; /* base64 encoded. */
- char *tmp;
- size_t size;
- int error;
-
- size = get_spki_alloc_size(lfile);
- tal->spki = pmalloc(size);
-
- tmp = NULL;
- error = base64_sanitize(lfile, &tmp);
- if (error)
- goto revert_spki;
+ if (tal->uris.len == 0)
+ return pr_op_err("There seems to be an empty/blank line before the end of the URI section.");
- encoded = BIO_new_mem_buf(tmp, -1);
- if (encoded == NULL) {
- error = op_crypto_err("BIO_new_mem_buf() returned NULL.");
- goto revert_tmp;
- }
-
- if (!base64_decode(encoded, tal->spki, true, size, &tal->spki_len)) {
- error = op_crypto_err("Cannot decode SPKI.");
- goto revert_encoded;
- }
+ /* subjectPublicKeyInfo section */
+ if (!base64_decode(nl + cr + 1, 0, &tal->spki, &tal->spki_len))
+ return pr_op_err("Cannot decode the public key.");
- free(tmp);
- BIO_free(encoded);
return 0;
-revert_encoded:
- BIO_free(encoded);
-revert_tmp:
- free(tmp);
-revert_spki:
- free(tal->spki);
- return error;
+/* This label requires fc to make sense */
+premature:
+ return pr_op_err("The TAL seems to end prematurely at line '%s'.", fc);
}
/**
static int
tal_init(struct tal *tal, char const *file_path)
{
- struct line_file *lfile;
char const *file_name;
+ struct file_contents file;
int error;
- lfile = NULL; /* Warning shutupper */
- error = lfile_open(file_path, &lfile);
- if (error) {
- pr_op_err("Error opening file '%s': %s", file_path,
- strerror(abs(error)));
+ error = file_load(file_path, &file, false);
+ if (error)
return error;
- }
file_name = strrchr(file_path, '/');
file_name = (file_name != NULL) ? (file_name + 1) : file_path;
-
tal->file_name = file_name;
+
uris_init(&tal->uris);
- error = read_uris(lfile, file_name, &tal->uris);
- if (error)
- goto fail;
- error = read_spki(lfile, tal);
- if (error)
- goto fail;
+ error = read_content((char *)file.buffer, tal);
+ if (error) {
+ uris_cleanup(&tal->uris);
+ goto end;
+ }
tal->cache = cache_create(file_name);
- lfile_close(lfile);
- return 0;
-
-fail:
- uris_cleanup(&tal->uris);
- lfile_close(lfile);
+end:
+ file_free(&file);
return error;
}
meta->hash_len);
}
-/* Left trim @from, setting the result at @result pointer */
-static int
-ltrim(char const *from, char const **result, size_t *result_size)
-{
- char const *start;
- size_t tmp_size;
-
- start = from;
- tmp_size = strlen(from);
- while (isspace(*start)) {
- start++;
- tmp_size--;
- }
- if (*start == '\0')
- return pr_val_err("Invalid base64 encoded string (seems to be empty or full of spaces).");
-
- *result = start;
- *result_size = tmp_size;
- return 0;
-}
-
-/*
- * Get the base64 chars from @content and allocate to @out with lines no greater
- * than 65 chars (including line feed).
- *
- * Why? LibreSSL doesn't like lines greater than 80 chars, so use a common
- * length per line.
- */
-static int
-base64_sanitize(char const *content, char **out)
-{
-#define BUF_SIZE 65
- char *result;
- char const *tmp;
- size_t original_size, new_size;
- size_t offset, buf_len;
- int error;
-
- original_size = 0;
- error = ltrim(content, &tmp, &original_size);
- if (error)
- return error;
-
- if (original_size <= BUF_SIZE) {
- *out = pstrdup(content);
- return 0;
- }
-
- new_size = original_size + (original_size / BUF_SIZE);
- result = pmalloc(new_size + 1);
-
- offset = 0;
- while (original_size > 0){
- buf_len = original_size > BUF_SIZE ? BUF_SIZE : original_size;
- memcpy(&result[offset], tmp, buf_len);
- tmp += buf_len;
- offset += buf_len;
- original_size -= buf_len;
-
- if (original_size <= 0)
- break;
- result[offset] = '\n';
- offset++;
- }
-
- /* Reallocate to exact size and add nul char */
- if (offset != new_size + 1)
- result = prealloc(result, offset + 1);
-
- result[offset] = '\0';
- *out = result;
- return 0;
-#undef BUF_SIZE
-}
-
-static int
-base64_read(char const *content, unsigned char **out, size_t *out_len)
-{
- BIO *encoded; /* base64 encoded. */
- unsigned char *result;
- char *sanitized;
- size_t alloc_size;
- size_t result_len;
- int error;
-
- sanitized = NULL;
- error = base64_sanitize(content, &sanitized);
- if (error)
- return error;
-
- encoded = BIO_new_mem_buf(sanitized, -1);
- if (encoded == NULL) {
- error = val_crypto_err("BIO_new_mem_buf() returned NULL");
- goto release_sanitized;
- }
-
- alloc_size = EVP_DECODE_LENGTH(strlen(content));
- result = pmalloc(alloc_size);
-
- if (!base64_decode(encoded, result, true, alloc_size, &result_len)) {
- error = val_crypto_err("Cannot decode publish tag's base64.");
- goto release_result;
- }
-
- free(sanitized);
- BIO_free(encoded);
-
- (*out) = result;
- (*out_len) = result_len;
- return 0;
-
-release_result:
- free(result);
- BIO_free(encoded);
-release_sanitized:
- free(sanitized);
- return error;
-}
-
static int
parse_ulong(xmlTextReaderPtr reader, char const *attr, unsigned long *result)
{
base64_str = parse_string(reader, NULL);
if (base64_str == NULL)
return -EINVAL;
- error = base64_read((char const *)base64_str, &tag->content,
- &tag->content_len);
+ if (!base64_decode((char *)base64_str, 0, &tag->content, &tag->content_len))
+ error = pr_val_err("Cannot decode publish tag's base64.");
xmlFree(base64_str);
if (error)
return error;
/* rfc8181#section-2.2 but considering optional hash */
if (tag->meta.hash_len > 0)
- error = validate_hash(&tag->meta);
+ return validate_hash(&tag->meta);
- return error;
+ return 0;
}
static int
return error;
if (!base64url_decode(str_encoded, &result->ski, &ski_len))
- return op_crypto_err("The " SKI " could not be decoded.");
+ return pr_op_err("The " SKI " could not be decoded.");
/* Validate that's at least 20 octects long */
if (ski_len != RK_SKI_LEN) {
return error;
if (!base64url_decode(encoded, &result->router_public_key, &spk_len))
- return op_crypto_err("The " ROUTER_PUBLIC_KEY " could not be decoded.");
+ return pr_op_err("The " ROUTER_PUBLIC_KEY " could not be decoded.");
/*
* Validate that "is the full ASN.1 DER encoding of the
MY_LDADD = ${CHECK_LIBS}
check_PROGRAMS = address.test
+check_PROGRAMS += base64.test
check_PROGRAMS += cache.test
check_PROGRAMS += db_table.test
check_PROGRAMS += deltas_array.test
check_PROGRAMS += hash.test
-check_PROGRAMS += line_file.test
check_PROGRAMS += pb.test
check_PROGRAMS += pdu_handler.test
check_PROGRAMS += pdu_stream.test
address_test_SOURCES = types/address_test.c
address_test_LDADD = ${MY_LDADD}
+base64_test_SOURCES = crypto/base64_test.c
+base64_test_LDADD = ${MY_LDADD}
+
cache_test_SOURCES = cache/local_cache_test.c
cache_test_LDADD = ${MY_LDADD} ${JANSSON_LIBS}
hash_test_SOURCES = crypto/hash_test.c
hash_test_LDADD = ${MY_LDADD}
-line_file_test_SOURCES = line_file_test.c
-line_file_test_LDADD = ${MY_LDADD}
-
pb_test_SOURCES = data_structure/path_builder_test.c
pb_test_LDADD = ${MY_LDADD}
--- /dev/null
+#include <check.h>
+
+#include "alloc.c"
+#include "common.h"
+#include "mock.c"
+#include "crypto/base64.c"
+
+static void
+ck_uchar_array(unsigned char *expected, size_t expected_len,
+ unsigned char *actual, size_t actual_len)
+{
+ size_t i;
+ ck_assert_uint_eq(expected_len, actual_len);
+ for (i = 0; i < expected_len; i++)
+ ck_assert_uint_eq(expected[i], actual[i]);
+}
+
+
+static void
+ck_char_array(char *expected, unsigned char *actual, size_t actual_len)
+{
+ ck_uchar_array((unsigned char *)expected, strlen(expected), actual,
+ actual_len);
+}
+
+START_TEST(test_base64_decode)
+{
+ static char *fort = "Fort";
+ static char *potato = "potato";
+ static unsigned char emojis[] = { 0xf0, 0x9f, 0x98, 0x80, 0xf0, 0x9f, 0xab, 0xa0 };
+ static char *lorem_ipsum = "Lorem ipsum dolor sit amet, consectetur "
+ "adipiscing elit. In a malesuada neque. Nunc efficitur at leo ac "
+ "feugiat. Aliquam velit erat, molestie nec nulla vitae, accumsan "
+ "accumsan ipsum. Nunc mattis quam sit amet turpis sollicitudin "
+ "fringilla. Sed id ante finibus, finibus erat in, vestibulum "
+ "lectus. Aenean sed massa ut lacus efficitur sollicitudin. Mauris "
+ "at imperdiet augue. Maecenas tempus ornare odio, egestas faucibus "
+ "ante commodo id. Morbi at urna nisl. Phasellus gravida felis non "
+ "erat ornare, at mattis magna venenatis. In ac lorem vel est "
+ "euismod finibus. Nam mauris felis, laoreet id eros sed, suscipit "
+ "gravida justo. In a dictum erat. Pellentesque habitant morbi "
+ "tristique senectus et netus et malesuada fames ac turpis egestas.";
+ unsigned char *dec;
+ size_t declen;
+
+ /* Empty */
+ ck_assert_int_eq(true, base64_decode("", 0, &dec, &declen));
+ ck_assert_uint_eq(0, declen);
+ free(dec);
+
+ /* With padding */
+ ck_assert_int_eq(true, base64_decode("Rm9ydA==", 0, &dec, &declen));
+ ck_char_array(fort, dec, declen);
+ free(dec);
+
+ /* No padding */
+ ck_assert_int_eq(true, base64_decode("cG90YXRv", 0, &dec, &declen));
+ ck_char_array(potato, dec, declen);
+ free(dec);
+
+ /* Not ASCII */
+ ck_assert_int_eq(true, base64_decode("8J+YgPCfq6A=", 0, &dec, &declen));
+ ck_uchar_array(emojis, ARRAY_LEN(emojis), dec, declen);
+ free(dec);
+
+ /* Illegal character */
+ ck_assert_int_eq(false, base64_decode("R!m9ydA=", 0, &dec, &declen));
+ /* Length not multiple of 4 */
+ ck_assert_int_eq(false, base64_decode("Rm9ydA=", 0, &dec, &declen));
+
+ /* Long, no whitespace */
+ ck_assert_int_eq(true, base64_decode("TG9yZW0gaXBzdW0gZG9sb3Igc2l0I"
+ "GFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4gSW4gYSBtYWxlc"
+ "3VhZGEgbmVxdWUuIE51bmMgZWZmaWNpdHVyIGF0IGxlbyBhYyBmZXVnaWF0L"
+ "iBBbGlxdWFtIHZlbGl0IGVyYXQsIG1vbGVzdGllIG5lYyBudWxsYSB2aX"
+ "RhZSwgYWNjdW1zYW4gYWNjdW1zYW4gaXBzdW0uIE51bmMgbWF0dGlzIHF1YW0gc2"
+ "l0IGFtZXQgdHVycGlzIHNvbGxpY2l0dWRpbiBmcmluZ2lsbGEuIFNlZCBpZCBhbn"
+ "RlIGZpbmlidXMsIGZpbmlidXMgZXJhdCBpbiwgdmVzdGlidWx1bSBsZWN0dXMuIE"
+ "FlbmVhbiBzZWQgbWFzc2EgdXQgbGFjdXMgZWZmaWNpdHVyIHNvbGxpY2l0dWRpbi"
+ "4gTWF1cmlzIGF0IGltcGVyZGlldCBhdWd1ZS4gTWFlY2VuYXMgdGVtcHVzIG9ybm"
+ "FyZSBvZGlvLCBlZ2VzdGFzIGZhdWNpYnVzIGFudGUgY29tbW9kbyBpZC4gTW9yYm"
+ "kgYXQgdXJuYSBuaXNsLiBQaGFzZWxsdXMgZ3JhdmlkYSBmZWxpcyBub24gZXJhdC"
+ "Bvcm5hcmUsIGF0IG1hdHRpcyBtYWduYSB2ZW5lbmF0aXMuIEluIGFjIGxvcmVtIH"
+ "ZlbCBlc3QgZXVpc21vZCBmaW5pYnVzLiBOYW0gbWF1cmlzIGZlbGlzLCBsYW9yZW"
+ "V0IGlkIGVyb3Mgc2VkLCBzdXNjaXBpdCBncmF2aWRhIGp1c3RvLiBJbiBhIGRpY3"
+ "R1bSBlcmF0LiBQZWxsZW50ZXNxdWUgaGFiaXRhbnQgbW9yYmkgdHJpc3RpcXVlIH"
+ "NlbmVjdHVzIGV0IG5ldHVzIGV0IG1hbGVzdWFkYSBmYW1lcyBhYyB0dXJwaXMgZW"
+ "dlc3Rhcy4=", 0, &dec, &declen));
+ ck_char_array(lorem_ipsum, dec, declen);
+ free(dec);
+
+ /* Long, whitespace */
+ ck_assert_int_eq(true, base64_decode(" TG9yZW0gaXBzdW0gZG9sb3Igc2l0I\n"
+ " GFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4gSW4gYSBtYWxlc\n"
+ "3VhZGEgbmVxdWUuIE51bmMgZWZmaWNpdHVyIGF0IGxlbyBhYyBmZXVnaWF0L\n\n\n"
+ "iBBbGlxdWFtIHZlbGl0I GVyYXQsIG1vbGVzdGllIG5lYyBudWxsYSB2aX\n"
+ "RhZSwgYWNjdW1zYW4gYWNjdW1zYW4gaXBzdW0uIE51bmMgbWF0dGlzIHF1YW0gc2\n"
+ "l0IGFtZXQgdHVycGlzIHNvbGxpY2l0dWRpbiBmcmluZ2lsbGEuIFNlZCBpZCBhbn\n"
+ "RlIGZpbmlidXMsIGZpbmlidXMgZXJhdCBpbiwgdmVzdGlidWx1bSBsZWN0dXMuIE\n"
+ "FlbmVhbiBzZWQgbWFzc2EgdXQgbGFjdXMgZWZmaWNpdHVyIHNvbGxpY2l0dWRpbi\n"
+ "4gTWF1cmlzIGF0IGltcGVyZGlldCBhdWd1ZS4gTWFlY2VuYXMgdGVtcHVzIG9ybm\n"
+ "FyZSBvZGlvLCBlZ2VzdGFzIGZhdWNpYnVzIGFudGUgY29tbW9kbyBpZC4gTW9yYm\n"
+ "kgYXQgdXJuYSBuaXNsLiBQaGFzZWxsdXMgZ3JhdmlkYSBmZWxpcyBub24gZXJhdC\n"
+ "Bvcm5hcmUsIGF0IG1hdHRpcyBtYWduYSB2ZW5lbmF0aXMuIEluIGFjIGxvcmVtIH\n"
+ "ZlbCBlc3QgZXVpc21vZCBmaW5pYnVzLiBOYW0gbWF1cmlzIGZlbGlzLCBsYW9yZW\n"
+ "V0IGlkIGVyb3Mgc2VkLCBzdXNjaXBpdCBncmF2aWRhIGp1c3RvLiBJbiBhIGRpY3\n"
+ "R1bSBlcmF0LiBQZWxsZW50ZXNxdWUgaGFiaXRhbnQgbW9yYmkgdHJpc3RpcXVlIH\n"
+ "NlbmVjdHVzIGV0IG5ldHVzIGV0IG1hbGVzdWFkYSBmYW1lcyBhYyB0dXJwaXMgZW\n"
+ "dlc3Rhcy4=\n\n\n", 0, &dec, &declen));
+ ck_char_array(lorem_ipsum, dec, declen);
+ free(dec);
+}
+END_TEST
+
+static Suite *
+pdu_suite(void)
+{
+ Suite *suite;
+ TCase *core;
+
+ core = tcase_create("core");
+ tcase_add_test(core, test_base64_decode);
+
+ suite = suite_create("base64");
+ suite_add_tcase(suite, core);
+ return suite;
+}
+
+int
+main(int argc, char **argv)
+{
+ Suite *suite;
+ SRunner *runner;
+ int tests_failed;
+
+ suite = pdu_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;
+}
hash_setup();
+ uri.global = "https://example.com/resources/lorem-ipsum.txt";
+ uri.global_len = strlen(uri.global);
uri.local = "resources/lorem-ipsum.txt";
+ uri.type = UT_HTTPS;
+ uri.is_notif = false;
+ uri.references = 1;
ha = hash_get_sha1();
ck_assert_uint_eq(20, hash_get_size(ha));
+++ /dev/null
-#include <check.h>
-#include <errno.h>
-#include <stdlib.h>
-
-#include "alloc.c"
-#include "file.c"
-#include "line_file.c"
-#include "mock.c"
-
-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("resources/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("resources/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("resources/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
-
-static Suite *ghostbusters_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 = ghostbusters_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;
-}
+++ /dev/null
-This is a normal line.
-This is also a normal line, but the following one is empty.
-
-This one ends with \r\n.\r
-This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This is a very long line. This 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
-rsync://repository.lacnic.net/rpki/lacnic/rta-lacnic-rpki.cer
-https://potato
-rsync://potato
-
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqZEzhYK0+PtDOPfub/KR
-c3MeWx3neXx4/wbnJWGbNAtbYqXg3uU5J4HFzPgk/VIppgSKAhlO0H60DRP48by9
-gr5/yDHu2KXhOmnMg46sYsUIpfgtBS9+VtrqWziJfb+pkGtuOWeTnj6zBmBNZKK+
-5AlMCW1WPhrylIcB+XSZx8tk9GS/3SMQ+YfMVwwAyYjsex14Uzto4GjONALE5oh1
-M3+glRQduD6vzSwOD+WahMbc9vCOTED+2McLHRKgNaQf0YJ9a1jG9oJIvDkKXEqd
-fqDRktwyoD74cV57bW3tBAexB7GglITbInyQAsmdngtfg2LUMrcROHHP86QPZINj
-DQIDAQAB
+rsync://example.com/rpki/ta.cer\r
+\r
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqZEzhYK0+PtDOPfub/KR\r
+c3MeWx3neXx4/wbnJWGbNAtbYqXg3uU5J4HFzPgk/VIppgSKAhlO0H60DRP48by9\r
+gr5/yDHu2KXhOmnMg46sYsUIpfgtBS9+VtrqWziJfb+pkGtuOWeTnj6zBmBNZKK+\r
+5AlMCW1WPhrylIcB+XSZx8tk9GS/3SMQ+YfMVwwAyYjsex14Uzto4GjONALE5oh1\r
+M3+glRQduD6vzSwOD+WahMbc9vCOTED+2McLHRKgNaQf0YJ9a1jG9oJIvDkKXEqd\r
+fqDRktwyoD74cV57bW3tBAexB7GglITbInyQAsmdngtfg2LUMrcROHHP86QPZINj\r
+DQIDAQAB\r
--- /dev/null
+rsync://example.com/rpki/ta.cer
+
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqZEzhYK0+PtDOPfub/KR
+c3MeWx3neXx4/wbnJWGbNAtbYqXg3uU5J4HFzPgk/VIppgSKAhlO0H60DRP48by9
+gr5/yDHu2KXhOmnMg46sYsUIpfgtBS9+VtrqWziJfb+pkGtuOWeTnj6zBmBNZKK+
+5AlMCW1WPhrylIcB+XSZx8tk9GS/3SMQ+YfMVwwAyYjsex14Uzto4GjONALE5oh1
+M3+glRQduD6vzSwOD+WahMbc9vCOTED+2McLHRKgNaQf0YJ9a1jG9oJIvDkKXEqd
+fqDRktwyoD74cV57bW3tBAexB7GglITbInyQAsmdngtfg2LUMrcROHHP86QPZINj
+DQIDAQAB
--- /dev/null
+rsync://example.com/rpki/ta.cer\r
+https://example.com/rpki/ta.cer\r
+rsync://www.example.com/potato/ta.cer\r
+https://wx3.example.com/tomato/ta.cer\r
+\r
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqZEzhYK0+PtDOPfub/KR\r
+c3MeWx3neXx4/wbnJWGbNAtbYqXg3uU5J4HFzPgk/VIppgSKAhlO0H60DRP48by9\r
+gr5/yDHu2KXhOmnMg46sYsUIpfgtBS9+VtrqWziJfb+pkGtuOWeTnj6zBmBNZKK+\r
+5AlMCW1WPhrylIcB+XSZx8tk9GS/3SMQ+YfMVwwAyYjsex14Uzto4GjONALE5oh1\r
+M3+glRQduD6vzSwOD+WahMbc9vCOTED+2McLHRKgNaQf0YJ9a1jG9oJIvDkKXEqd\r
+fqDRktwyoD74cV57bW3tBAexB7GglITbInyQAsmdngtfg2LUMrcROHHP86QPZINj\r
+DQIDAQAB\r
--- /dev/null
+
+rsync://example.com/rpki/ta.cer
+https://example.com/rpki/ta.cer
+
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqZEzhYK0+PtDOPfub/KR
+c3MeWx3neXx4/wbnJWGbNAtbYqXg3uU5J4HFzPgk/VIppgSKAhlO0H60DRP48by9
+gr5/yDHu2KXhOmnMg46sYsUIpfgtBS9+VtrqWziJfb+pkGtuOWeTnj6zBmBNZKK+
+5AlMCW1WPhrylIcB+XSZx8tk9GS/3SMQ+YfMVwwAyYjsex14Uzto4GjONALE5oh1
+M3+glRQduD6vzSwOD+WahMbc9vCOTED+2McLHRKgNaQf0YJ9a1jG9oJIvDkKXEqd
+fqDRktwyoD74cV57bW3tBAexB7GglITbInyQAsmdngtfg2LUMrcROHHP86QPZINj
+DQIDAQAB
--- /dev/null
+
+# Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eu sapien
+#facilisis, sagittis elit quis, lobortis odio. Morbi feugiat congue bibendum.
+# Vivamus eu quam.
+rsync://example.com/rpki/ta.cer
+https://example.com/rpki/ta.cer
+
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqZEzhYK0+PtDOPfub/KR
+c3MeWx3neXx4/wbnJWGbNAtbYqXg3uU5J4HFzPgk/VIppgSKAhlO0H60DRP48by9
+gr5/yDHu2KXhOmnMg46sYsUIpfgtBS9+VtrqWziJfb+pkGtuOWeTnj6zBmBNZKK+
+5AlMCW1WPhrylIcB+XSZx8tk9GS/3SMQ+YfMVwwAyYjsex14Uzto4GjONALE5oh1
+M3+glRQduD6vzSwOD+WahMbc9vCOTED+2McLHRKgNaQf0YJ9a1jG9oJIvDkKXEqd
+fqDRktwyoD74cV57bW3tBAexB7GglITbInyQAsmdngtfg2LUMrcROHHP86QPZINj
+DQIDAQAB
--- /dev/null
+# Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eu sapien
+#facilisis, sagittis elit quis, lobortis odio. Morbi feugiat congue bibendum.
+
+# Vivamus eu quam.
+rsync://example.com/rpki/ta.cer
+https://example.com/rpki/ta.cer
+
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqZEzhYK0+PtDOPfub/KR
+c3MeWx3neXx4/wbnJWGbNAtbYqXg3uU5J4HFzPgk/VIppgSKAhlO0H60DRP48by9
+gr5/yDHu2KXhOmnMg46sYsUIpfgtBS9+VtrqWziJfb+pkGtuOWeTnj6zBmBNZKK+
+5AlMCW1WPhrylIcB+XSZx8tk9GS/3SMQ+YfMVwwAyYjsex14Uzto4GjONALE5oh1
+M3+glRQduD6vzSwOD+WahMbc9vCOTED+2McLHRKgNaQf0YJ9a1jG9oJIvDkKXEqd
+fqDRktwyoD74cV57bW3tBAexB7GglITbInyQAsmdngtfg2LUMrcROHHP86QPZINj
+DQIDAQAB
--- /dev/null
+# Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eu sapien
+#facilisis, sagittis elit quis, lobortis odio. Morbi feugiat congue bibendum.
+# Vivamus eu quam.
+
+rsync://example.com/rpki/ta.cer
+https://example.com/rpki/ta.cer
+
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqZEzhYK0+PtDOPfub/KR
+c3MeWx3neXx4/wbnJWGbNAtbYqXg3uU5J4HFzPgk/VIppgSKAhlO0H60DRP48by9
+gr5/yDHu2KXhOmnMg46sYsUIpfgtBS9+VtrqWziJfb+pkGtuOWeTnj6zBmBNZKK+
+5AlMCW1WPhrylIcB+XSZx8tk9GS/3SMQ+YfMVwwAyYjsex14Uzto4GjONALE5oh1
+M3+glRQduD6vzSwOD+WahMbc9vCOTED+2McLHRKgNaQf0YJ9a1jG9oJIvDkKXEqd
+fqDRktwyoD74cV57bW3tBAexB7GglITbInyQAsmdngtfg2LUMrcROHHP86QPZINj
+DQIDAQAB
--- /dev/null
+# Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eu sapien
+# facilisis, αβγδϵζηθικλμνξoπρστυϕχψω. Morbi feugiat congue bibendum.
+# Vivamus eu quam.
+rsync://example.com/rpki/ta.cer
+https://example.com/rpki/ta.cer
+rsync://www.example.com/potato/ta.cer
+https://wx3.example.com/tomato/ta.cer
+
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqZEzhYK0+PtDOPfub/KR
+c3MeWx3neXx4/wbnJWGbNAtbYqXg3uU5J4HFzPgk/VIppgSKAhlO0H60DRP48by9
+gr5/yDHu2KXhOmnMg46sYsUIpfgtBS9+VtrqWziJfb+pkGtuOWeTnj6zBmBNZKK+
+5AlMCW1WPhrylIcB+XSZx8tk9GS/3SMQ+YfMVwwAyYjsex14Uzto4GjONALE5oh1
+M3+glRQduD6vzSwOD+WahMbc9vCOTED+2McLHRKgNaQf0YJ9a1jG9oJIvDkKXEqd
+fqDRktwyoD74cV57bW3tBAexB7GglITbInyQAsmdngtfg2LUMrcROHHP86QPZINj
+DQIDAQAB
--- /dev/null
+# Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eu sapien
+#facilisis, sagittis elit quis, lobortis odio. Morbi feugiat congue bibendum.
+# Vivamus eu quam.
+rsync://example.com/rpki/ta.cer
+https://example.com/rpki/ta.cer
+rsync://www.example.com/potato/ta.cer
+https://wx3.example.com/tomato/ta.cer
+
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqZEzhYK0+PtDOPfub/KR
+c3MeWx3neXx4/wbnJWGbNAtbYqXg3uU5J4HFzPgk/VIppgSKAhlO0H60DRP48by9
+gr5/yDHu2KXhOmnMg46sYsUIpfgtBS9+VtrqWziJfb+pkGtuOWeTnj6zBmBNZKK+
+5AlMCW1WPhrylIcB+XSZx8tk9GS/3SMQ+YfMVwwAyYjsex14Uzto4GjONALE5oh1
+M3+glRQduD6vzSwOD+WahMbc9vCOTED+2McLHRKgNaQf0YJ9a1jG9oJIvDkKXEqd
+fqDRktwyoD74cV57bW3tBAexB7GglITbInyQAsmdngtfg2LUMrcROHHP86QPZINj
+DQIDAQAB
--- /dev/null
+rsync://example.com/rpki/ta.cer
+https://example.com/rpki/ta.cer
+rsync://www.example.com/potato/ta.cer
+https://wx3.example.com/tomato/ta.cer
+
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqZEzhYK0+PtDOPfub/KR
+c3MeWx3neXx4/wbnJWGbNAtbYqXg3uU5J4HFzPgk/VIppgSKAhlO0H60DRP48by9
+gr5/yDHu2KXhOmnMg46sYsUIpfgtBS9+VtrqWziJfb+pkGtuOWeTnj6zBmBNZKK+
+5AlMCW1WPhrylIcB+XSZx8tk9GS/3SMQ+YfMVwwAyYjsex14Uzto4GjONALE5oh1
+M3+glRQduD6vzSwOD+WahMbc9vCOTED+2McLHRKgNaQf0YJ9a1jG9oJIvDkKXEqd
+fqDRktwyoD74cV57bW3tBAexB7GglITbInyQAsmdngtfg2LUMrcROHHP86QPZINj
+DQIDAQAB
MOCK_ABORT_INT(__uri_create, struct rpki_uri **result, char const *tal,
enum uri_type type, bool is_notif, struct rpki_uri *notif, void const *guri,
size_t guri_len)
-__MOCK_ABORT(base64_decode, bool, false, BIO *in, unsigned char *out,
- bool has_nl, size_t out_len, size_t *out_written)
+__MOCK_ABORT(base64_decode, bool, false, char *in, size_t inl,
+ unsigned char **out, size_t *outl)
MOCK_ABORT_INT(cache_download, struct rpki_cache *cache, struct rpki_uri *uri,
bool *changed)
MOCK_ABORT_VOID(file_close, FILE *file)
#include "alloc.c"
#include "common.c"
#include "file.c"
-#include "line_file.c"
#include "mock.c"
#include "data_structure/path_builder.c"
#include "types/uri.c"
/* Tests */
-START_TEST(tal_load_normal)
+static void
+check_spki(struct tal *tal)
{
- struct tal tal;
- unsigned int i;
/* Got this by feeding the subjectPublicKeyInfo to `base64 -d`. */
- unsigned char decoded[] = {
+ static unsigned char spki_raw[] = {
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,
0xD4, 0x32, 0xB7, 0x11, 0x38, 0x71, 0xCF, 0xF3, 0xA4, 0x0F, 0x64,
0x83, 0x63, 0x0D, 0x02, 0x03, 0x01, 0x00, 0x01
};
+ unsigned int i;
+
+ ck_assert_uint_eq(ARRAY_LEN(spki_raw), tal->spki_len);
+ for (i = 0; i < ARRAY_LEN(spki_raw); i++)
+ ck_assert_uint_eq(tal->spki[i], spki_raw[i]);
+}
- ck_assert_int_eq(tal_init(&tal, "tal/lacnic.tal"), 0);
+static void
+test_1url(char const *file)
+{
+ struct tal tal;
- ck_assert_uint_eq(tal.uris.len, 3);
- ck_assert_str_eq(tal.uris.array[0]->global,
- "rsync://repository.lacnic.net/rpki/lacnic/rta-lacnic-rpki.cer");
- ck_assert_str_eq(tal.uris.array[1]->global, "https://potato");
- ck_assert_str_eq(tal.uris.array[2]->global, "rsync://potato");
+ ck_assert_int_eq(0, tal_init(&tal, file));
- ck_assert_uint_eq(ARRAY_LEN(decoded), tal.spki_len);
- for (i = 0; i < ARRAY_LEN(decoded); i++)
- ck_assert_uint_eq(tal.spki[i], decoded[i]);
+ ck_assert_uint_eq(1, tal.uris.len);
+ ck_assert_str_eq("rsync://example.com/rpki/ta.cer", tal.uris.array[0]->global);
+ check_spki(&tal);
tal_cleanup(&tal);
}
+
+START_TEST(test_tal_load_1url)
+{
+ test_1url("resources/tal/1url-lf.tal");
+ test_1url("resources/tal/1url-crlf.tal");
+}
+END_TEST
+
+static void
+test_4urls(char const *file)
+{
+ struct tal tal;
+
+ ck_assert_int_eq(0, tal_init(&tal, file));
+
+ ck_assert_uint_eq(4, tal.uris.len);
+ ck_assert_str_eq("rsync://example.com/rpki/ta.cer", tal.uris.array[0]->global);
+ ck_assert_str_eq("https://example.com/rpki/ta.cer", tal.uris.array[1]->global);
+ ck_assert_str_eq("rsync://www.example.com/potato/ta.cer", tal.uris.array[2]->global);
+ ck_assert_str_eq("https://wx3.example.com/tomato/ta.cer", tal.uris.array[3]->global);
+
+ check_spki(&tal);
+
+ tal_cleanup(&tal);
+}
+
+START_TEST(test_tal_load_4urls)
+{
+ test_4urls("resources/tal/4urls-lf.tal");
+ test_4urls("resources/tal/4urls-crlf.tal");
+ test_4urls("resources/tal/4urls-lf-comment.tal");
+ test_4urls("resources/tal/4urls-lf-comment-utf8.tal");
+}
+END_TEST
+
+START_TEST(test_tal_load_error)
+{
+ struct tal tal;
+
+ ck_assert_int_eq(-EINVAL, tal_init(&tal, "resources/tal/4urls-lf-comment-space-1.tal"));
+ ck_assert_int_eq(-EINVAL, tal_init(&tal, "resources/tal/4urls-lf-comment-space-2.tal"));
+ ck_assert_int_eq(-EINVAL, tal_init(&tal, "resources/tal/4urls-lf-comment-space-3.tal"));
+ ck_assert_int_eq(-EINVAL, tal_init(&tal, "resources/tal/4urls-lf-comment-space-4.tal"));
+}
END_TEST
static Suite *tal_load_suite(void)
TCase *core;
core = tcase_create("Core");
- tcase_add_test(core, tal_load_normal);
+ tcase_add_test(core, test_tal_load_1url);
+ tcase_add_test(core, test_tal_load_4urls);
+ tcase_add_test(core, test_tal_load_error);
suite = suite_create("tal_load()");
suite_add_tcase(suite, core);