From: Alberto Leiva Popper Date: Tue, 11 Dec 2018 15:12:20 +0000 (-0600) Subject: Automatically print offending files' names on errors X-Git-Tag: v0.0.2~119 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=81b03407ef479b2287f51154cf1c80a18bcfdf8b;p=thirdparty%2FFORT-validator.git Automatically print offending files' names on errors --- diff --git a/src/Makefile.am b/src/Makefile.am index f43b7314..d2f52578 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 index 00000000..74308f5a --- /dev/null +++ b/src/filename_stack.c @@ -0,0 +1,138 @@ +#include "filename_stack.h" + +#include +#include +#include +#include +#include + +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 index 00000000..8c93ab84 --- /dev/null +++ b/src/filename_stack.h @@ -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_ */ diff --git a/src/log.c b/src/log.c index 23254c38..1aa2d9bf 100644 --- a/src/log.c +++ b/src/log.c @@ -3,13 +3,16 @@ #include #include -#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); diff --git a/src/log.h b/src/log.h index be279275..7d6af24b 100644 --- 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_ */ diff --git a/src/main.c b/src/main.c index 201f9139..57025329 100644 --- a/src/main.c +++ b/src/main.c @@ -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]; diff --git a/src/object/certificate.c b/src/object/certificate.c index 9247af9d..a10de9f1 100644 --- a/src/object/certificate.c +++ b/src/object/certificate.c @@ -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; } diff --git a/src/object/manifest.c b/src/object/manifest.c index d1d3b2d9..8f7e5040 100644 --- a/src/object/manifest.c +++ b/src/object/manifest.c @@ -4,6 +4,7 @@ #include #include +#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; } diff --git a/src/object/roa.c b/src/object/roa.c index 32b24e4b..6018ac7e 100644 --- a/src/object/roa.c +++ b/src/object/roa.c @@ -4,6 +4,7 @@ #include #include +#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; } diff --git a/src/state.c b/src/state.c index 52815fdc..19f6cb8f 100644 --- a/src/state.c +++ b/src/state.c @@ -2,6 +2,7 @@ #include #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;