]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Automatically print offending files' names on errors
authorAlberto Leiva Popper <ydahhrk@gmail.com>
Tue, 11 Dec 2018 15:12:20 +0000 (09:12 -0600)
committerAlberto Leiva Popper <ydahhrk@gmail.com>
Tue, 11 Dec 2018 15:12:20 +0000 (09:12 -0600)
src/Makefile.am
src/filename_stack.c [new file with mode: 0644]
src/filename_stack.h [new file with mode: 0644]
src/log.c
src/log.h
src/main.c
src/object/certificate.c
src/object/manifest.c
src/object/roa.c
src/state.c

index f43b7314cdc835b980e2ca11326ca9f68e10da5e..d2f525784204de6b5ff032e4c5aac0f2eb93498b 100644 (file)
@@ -10,6 +10,7 @@ rpki_validator_SOURCES += address.h address.c
 rpki_validator_SOURCES += common.h common.c
 rpki_validator_SOURCES += debug.h debug.c
 rpki_validator_SOURCES += file.h file.c
+rpki_validator_SOURCES += filename_stack.h filename_stack.c
 rpki_validator_SOURCES += line_file.h line_file.c
 rpki_validator_SOURCES += log.h log.c
 rpki_validator_SOURCES += resource.h resource.c
diff --git a/src/filename_stack.c b/src/filename_stack.c
new file mode 100644 (file)
index 0000000..74308f5
--- /dev/null
@@ -0,0 +1,138 @@
+#include "filename_stack.h"
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static pthread_key_t filenames_key;
+
+struct filename_stack {
+       /* This can be NULL. Abort all operations if this is the case. */
+       char const **filenames;
+       unsigned int len;
+       unsigned int size;
+};
+
+static void
+fnstack_discard(void *arg)
+{
+       struct filename_stack *files = arg;
+       free(files->filenames);
+       free(files);
+}
+
+/** Initializes this module. Call once per runtime lifetime. */
+void
+fnstack_init(void)
+{
+       int error;
+
+       error = pthread_key_create(&filenames_key, fnstack_discard);
+       if (error) {
+               fprintf(stderr,
+                   "Fatal: Errcode %d while attempting to initialize thread variable.\n",
+                   error);
+               exit(error);
+       }
+}
+
+/** Initializes the current thread's fnstack. Call once per thread. */
+void
+fnstack_store(void)
+{
+       struct filename_stack *files;
+       int error;
+
+       files = malloc(sizeof(struct filename_stack));
+       if (files == NULL)
+               return;
+
+       files->filenames = malloc(32 * sizeof(char *));
+       if (files->filenames == NULL) {
+               free(files);
+               return;
+       }
+
+       files->len = 0;
+       files->size = 32;
+
+       error = pthread_setspecific(filenames_key, files);
+       if (error)
+               fprintf(stderr, "pthread_setspecific() returned %d.", error);
+}
+
+static struct filename_stack *
+get_file_stack(void)
+{
+       struct filename_stack *files;
+
+       files = pthread_getspecific(filenames_key);
+       if (files == NULL)
+               fprintf(stderr, "This thread lacks a files stack.\n");
+
+       return files;
+}
+
+static char const *
+get_filename(char const *file_path)
+{
+       char *slash = strrchr(file_path, '/');
+       return (slash != NULL) ? (slash + 1) : file_path;
+}
+
+/**
+ * Call this function every time you're about to start processing a new file.
+ * Any pr_err()s and friends will now include the new file name.
+ * Use fnstack_pop() to revert back to the previously stacked file name.
+ */
+void
+fnstack_push(char const *file_path)
+{
+       struct filename_stack *files;
+       char const **tmp;
+
+       files = get_file_stack();
+       if (files == NULL || files->filenames == NULL)
+               return;
+
+       if (files->len >= files->size) {
+               tmp = realloc(files->filenames, 2 * files->size * sizeof(char *));
+               if (tmp == NULL) {
+                       /* Oh noes */
+                       free(files->filenames);
+                       files->filenames = NULL;
+                       return;
+               }
+
+               files->filenames = tmp;
+               files->size *= 2;
+       }
+
+       files->filenames[files->len++] = get_filename(file_path);
+}
+
+char const *
+fnstack_peek(void)
+{
+       struct filename_stack *files;
+
+       files = get_file_stack();
+       if (files == NULL || files->filenames == NULL || files->len == 0)
+               return NULL;
+
+       return files->filenames[files->len - 1];
+}
+
+void
+fnstack_pop(void)
+{
+       struct filename_stack *files;
+
+       files = get_file_stack();
+       if (files == NULL || files->filenames == NULL || files->len == 0)
+               return;
+
+       files->len--;
+}
diff --git a/src/filename_stack.h b/src/filename_stack.h
new file mode 100644 (file)
index 0000000..8c93ab8
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef SRC_FILENAME_STACK_H_
+#define SRC_FILENAME_STACK_H_
+
+void fnstack_init(void);
+void fnstack_store(void);
+
+void fnstack_push(char const *);
+char const *fnstack_peek(void);
+void fnstack_pop(void);
+
+#endif /* SRC_FILENAME_STACK_H_ */
index 23254c38c6e8b420aa4ea33b6ece5388057b5423..1aa2d9bfe0c55c128a6b56b62f51703b42c23e3b 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -3,13 +3,16 @@
 #include <openssl/bio.h>
 #include <openssl/err.h>
 
-#ifdef DEBUG
+#include "filename_stack.h"
+
+#define STDOUT stdout
+#define STDERR stderr
 
 #define INDENT_MAX 10
 static unsigned int indent;
 
 static void
-pr_indent(void)
+pr_indent(FILE *stream)
 {
        unsigned int __indent = indent;
        unsigned int i;
@@ -18,9 +21,18 @@ pr_indent(void)
 //             __indent = INDENT_MAX;
 
        for (i = 0; i < __indent; i++)
-               printf("  ");
+               fprintf(stream, "  ");
+}
+
+static void
+pr_file_name(FILE *stream)
+{
+       char const *file = fnstack_peek();
+       fprintf(stream, "%s: ", (file != NULL) ? file : "(Unknown file)");
 }
 
+#ifdef DEBUG
+
 static void
 pr_add_indent(void)
 {
@@ -33,14 +45,14 @@ pr_rm_indent(void)
        if (indent > 0)
                indent--;
        else
-               fprintf(stderr, "Programming error: Too many pr_rm_indent()s.\n");
+               fprintf(STDERR, "Programming error: Too many pr_rm_indent()s.\n");
 }
 
 static void
-print_debug_prefix(void)
+pr_debug_prefix(void)
 {
-       printf("DBG: ");
-       pr_indent();
+       fprintf(STDOUT, "DBG: ");
+       pr_indent(STDOUT);
 }
 
 #endif
@@ -51,12 +63,12 @@ pr_debug(const char *format, ...)
 #ifdef DEBUG
        va_list args;
 
-       print_debug_prefix();
+       pr_debug_prefix();
 
        va_start(args, format);
-       vprintf(format, args);
+       vfprintf(STDOUT, format, args);
        va_end(args);
-       printf("\n");
+       fprintf(STDOUT, "\n");
 #endif
 }
 
@@ -66,12 +78,12 @@ pr_debug_add(const char *format, ...)
 #ifdef DEBUG
        va_list args;
 
-       print_debug_prefix();
+       pr_debug_prefix();
 
        va_start(args, format);
-       vprintf(format, args);
+       vfprintf(STDOUT, format, args);
        va_end(args);
-       printf("\n");
+       fprintf(STDOUT, "\n");
 
        pr_add_indent();
 #endif
@@ -85,15 +97,22 @@ pr_debug_rm(const char *format, ...)
 
        pr_rm_indent();
 
-       print_debug_prefix();
+       pr_debug_prefix();
 
        va_start(args, format);
-       vprintf(format, args);
+       vfprintf(STDOUT, format, args);
        va_end(args);
-       printf("\n");
+       fprintf(STDOUT, "\n");
 #endif
 }
 
+static void
+pr_err_prefix(void)
+{
+       fprintf(STDERR, "ERR: ");
+       pr_indent(STDERR);
+}
+
 /**
  * Always appends a newline at the end.
  */
@@ -102,10 +121,13 @@ pr_err(const char *format, ...)
 {
        va_list args;
 
+       pr_err_prefix();
+       pr_file_name(STDERR);
+
        va_start(args, format);
-       vfprintf(stderr, format, args);
+       vfprintf(STDERR, format, args);
        va_end(args);
-       fprintf(stderr, "\n");
+       fprintf(STDERR, "\n");
 }
 
 /**
@@ -127,18 +149,21 @@ pr_errno(int error, const char *format, ...)
 {
        va_list args;
 
+       pr_err_prefix();
+       pr_file_name(STDERR);
+
        va_start(args, format);
-       vfprintf(stderr, format, args);
+       vfprintf(STDERR, format, args);
        va_end(args);
 
        if (error) {
-               fprintf(stderr, ": %s", strerror(error));
+               fprintf(STDERR, ": %s", strerror(error));
        } else {
                /* We should assume that there WAS an error; go generic. */
                error = -EINVAL;
        }
 
-       fprintf(stderr, "\n");
+       fprintf(STDERR, "\n");
 
        return error;
 }
@@ -159,10 +184,16 @@ pr_errno(int error, const char *format, ...)
 int
 crypto_err(struct validation *state, const char *format, ...)
 {
-       BIO *bio = validation_stderr(state);
+       BIO *bio;
+       char const *file;
        va_list args;
        int error;
 
+       bio = validation_stderr(state);
+
+       file = fnstack_peek();
+       BIO_printf(bio, "%s: ", (file != NULL) ? file : "(Unknown file)");
+
        error = ERR_GET_REASON(ERR_peek_last_error());
 
        va_start(args, format);
index be2792758848df37691426497fcfab909083ab38..7d6af24b23a1d239dc8f6e67c2b2abee4ad823ab 100644 (file)
--- a/src/log.h
+++ b/src/log.h
@@ -12,5 +12,7 @@ int pr_errno(int, const char *, ...);
 int crypto_err(struct validation *, const char *, ...);
 
 #define PR_DEBUG printf("%s:%d (%s())\n", __FILE__, __LINE__, __func__)
+#define PR_DEBUG_MSG(msg, ...) printf("%s:%d (%s()): " msg "\n", \
+    __FILE__, __LINE__, __func__, ##__VA_ARGS__)
 
 #endif /* SRC_LOG_H_ */
index 201f9139b0bfded5fb168b243cf48b3321802fdc..5702532963cfc39e05b1c923216024fd76f2204c 100644 (file)
@@ -5,6 +5,7 @@
 #include "common.h"
 #include "debug.h"
 #include "log.h"
+#include "filename_stack.h"
 #include "object/certificate.h"
 #include "object/tal.h"
 
@@ -54,7 +55,9 @@ handle_tal_uri(char const *uri)
                goto end2;
        }
 
+       fnstack_push(uri);
        error = certificate_traverse(state, validation_peek_cert(state));
+       fnstack_pop();
 
 end2:
        pr_debug_rm("}");
@@ -78,6 +81,9 @@ main(int argc, char **argv)
        }
 
        add_rpki_oids();
+       fnstack_init();
+       fnstack_store();
+       fnstack_push(argv[2]);
 
        repository = argv[1];
 
index 9247af9d564553f0d6acc0bba4ffc363171bffb6..a10de9f150386a7b26eaffa63bb9c181ba5a9ea8 100644 (file)
@@ -176,13 +176,13 @@ certificate_load(struct validation *state, const char *file, X509 **result)
        if (bio == NULL)
                return crypto_err(state, "BIO_new(BIO_s_file()) returned NULL");
        if (BIO_read_filename(bio, file) <= 0) {
-               error = crypto_err(state, "Error reading certificate '%s'", file);
+               error = crypto_err(state, "Error reading certificate");
                goto abort1;
        }
 
        cert = d2i_X509_bio(bio, NULL);
        if (cert == NULL) {
-               error = crypto_err(state, "Error parsing certificate '%s'", file);
+               error = crypto_err(state, "Error parsing certificate");
                goto abort1;
        }
 
index d1d3b2d9f84dcc27230f74277eff8a9de50d3cb5..8f7e5040bb869b22a7854029646d4a2c048d4195 100644 (file)
@@ -4,6 +4,7 @@
 #include <libcmscodec/GeneralizedTime.h>
 #include <libcmscodec/Manifest.h>
 
+#include "filename_stack.h"
 #include "log.h"
 #include "asn1/oid.h"
 #include "object/certificate.h"
@@ -194,18 +195,22 @@ pile_crls(struct validation *state, char *file, void *crls)
        int error;
        int idx;
 
+       fnstack_push(file);
+
        error = crl_load(state, file, &crl);
        if (error)
-               return error;
+               goto end;
 
        idx = sk_X509_CRL_push(crls, crl);
        if (idx <= 0) {
                error = crypto_err(state, "Could not add CRL to a CRL stack");
                X509_CRL_free(crl);
-               return error;
+               goto end;
        }
 
-       return 0;
+end:
+       fnstack_pop();
+       return error;
 }
 
 static int
@@ -217,6 +222,7 @@ pile_addr_ranges(struct validation *state, char *file, void *__args)
        int error = 0;
 
        pr_debug_add("Certificate {");
+       fnstack_push(file);
 
        /*
         * Errors on some of these functions should not interrupt the tree
@@ -259,6 +265,7 @@ revert:
        X509_free(cert);
 end:
        pr_debug_rm("}");
+       fnstack_pop();
        return error;
 }
 
@@ -323,6 +330,7 @@ handle_manifest(struct validation *state, char const *file_path)
        int error;
 
        pr_debug_add("Manifest %s {", file_path);
+       fnstack_push(file_path);
 
        mft.file_path = file_path;
 
@@ -342,5 +350,6 @@ handle_manifest(struct validation *state, char const *file_path)
        ASN_STRUCT_FREE(asn_DEF_Manifest, mft.obj);
 end:
        pr_debug_rm("}");
+       fnstack_pop();
        return error;
 }
index 32b24e4bf447d5d6bca2ac2d80f48fb3fe3f20e1..6018ac7e1da215b2dc035bf065a2228204811676 100644 (file)
@@ -4,6 +4,7 @@
 #include <arpa/inet.h>
 #include <libcmscodec/RouteOriginAttestation.h>
 
+#include "filename_stack.h"
 #include "log.h"
 #include "asn1/oid.h"
 #include "object/signed_object.h"
@@ -101,13 +102,17 @@ __handle_roa(struct RouteOriginAttestation *roa, struct resources *parent)
                return -EINVAL;
        }
 
-       /* rfc6482#section-3.2 */
-       if (roa->ipAddrBlocks.list.array == NULL)
+       /* rfc6482#section-3.2 (more or less.) */
+       if (!resources_contains_asn(parent, roa->asID)) {
+               pr_err("ROA is not allowed to attest for AS %d",
+                   roa->asID);
                return -EINVAL;
+       }
 
        /* rfc6482#section-3.3 */
-       if (!resources_contains_asn(parent, roa->asID)) {
-               pr_err("ROA is not allowed to attest for AS %d", roa->asID);
+
+       if (roa->ipAddrBlocks.list.array == NULL) {
+               pr_err("Programming error: ipAddrBlocks array is NULL.");
                return -EINVAL;
        }
 
@@ -155,7 +160,8 @@ int handle_roa(struct validation *state, char const *file)
        struct resources *cert_resources;
        int error;
 
-       pr_debug_add("ROA {");
+       pr_debug_add("ROA %s {", file);
+       fnstack_push(file);
 
        cert_resources = resources_create();
        if (cert_resources == NULL) {
@@ -176,5 +182,6 @@ end2:
        resources_destroy(cert_resources);
 end1:
        pr_debug_rm("}");
+       fnstack_pop();
        return error;
 }
index 52815fdc97d2b8a8f9d9846f2d742f793ee93f69..19f6cb8ffbb7982d3121d2b113797fd670b4e14f 100644 (file)
@@ -2,6 +2,7 @@
 
 #include <errno.h>
 #include "log.h"
+#include "filename_stack.h"
 #include "object/certificate.h"
 
 /**
@@ -41,6 +42,8 @@ struct validation {
         * seemingly not intended to be used outside of its library.)
         */
        struct restack *rsrcs;
+
+       struct filename_stack *files;
 };
 
 /*
@@ -85,29 +88,34 @@ init_trusted(struct validation *result, char *root)
        int ok;
        int error;
 
+       fnstack_push(root);
+
        error = certificate_load(result, root, &cert);
        if (error)
-               return error;
+               goto abort1;
 
        result->trusted = sk_X509_new_null();
        if (result->trusted == NULL) {
                error = -EINVAL;
-               goto abort1;
+               goto abort2;
        }
 
        ok = sk_X509_push(result->trusted, cert);
        if (ok <= 0) {
                error = crypto_err(result,
                    "Could not add certificate to trusted stack: %d", ok);
-               goto abort2;
+               goto abort3;
        }
 
+       fnstack_pop();
        return 0;
 
-abort2:
+abort3:
        sk_X509_free(result->trusted);
-abort1:
+abort2:
        X509_free(cert);
+abort1:
+       fnstack_pop();
        return error;
 }
 
@@ -153,8 +161,10 @@ validation_create(struct validation **out, char *root)
        if (resources == NULL)
                goto abort6;
 
+       fnstack_push(root);
        error = certificate_get_resources(result, validation_peek_cert(result),
            resources);
+       fnstack_pop();
        if (error)
                goto abort7;