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
--- /dev/null
+#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--;
+}
--- /dev/null
+#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_ */
#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;
// __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)
{
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
#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
}
#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
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.
*/
{
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");
}
/**
{
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;
}
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);
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_ */
#include "common.h"
#include "debug.h"
#include "log.h"
+#include "filename_stack.h"
#include "object/certificate.h"
#include "object/tal.h"
goto end2;
}
+ fnstack_push(uri);
error = certificate_traverse(state, validation_peek_cert(state));
+ fnstack_pop();
end2:
pr_debug_rm("}");
}
add_rpki_oids();
+ fnstack_init();
+ fnstack_store();
+ fnstack_push(argv[2]);
repository = argv[1];
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;
}
#include <libcmscodec/GeneralizedTime.h>
#include <libcmscodec/Manifest.h>
+#include "filename_stack.h"
#include "log.h"
#include "asn1/oid.h"
#include "object/certificate.h"
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
int error = 0;
pr_debug_add("Certificate {");
+ fnstack_push(file);
/*
* Errors on some of these functions should not interrupt the tree
X509_free(cert);
end:
pr_debug_rm("}");
+ fnstack_pop();
return error;
}
int error;
pr_debug_add("Manifest %s {", file_path);
+ fnstack_push(file_path);
mft.file_path = file_path;
ASN_STRUCT_FREE(asn_DEF_Manifest, mft.obj);
end:
pr_debug_rm("}");
+ fnstack_pop();
return error;
}
#include <arpa/inet.h>
#include <libcmscodec/RouteOriginAttestation.h>
+#include "filename_stack.h"
#include "log.h"
#include "asn1/oid.h"
#include "object/signed_object.h"
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;
}
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) {
resources_destroy(cert_resources);
end1:
pr_debug_rm("}");
+ fnstack_pop();
return error;
}
#include <errno.h>
#include "log.h"
+#include "filename_stack.h"
#include "object/certificate.h"
/**
* seemingly not intended to be used outside of its library.)
*/
struct restack *rsrcs;
+
+ struct filename_stack *files;
};
/*
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;
}
if (resources == NULL)
goto abort6;
+ fnstack_push(root);
error = certificate_get_resources(result, validation_peek_cert(result),
resources);
+ fnstack_pop();
if (error)
goto abort7;