aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2011-05-25 18:41:25 +0000
committerRob Austein <sra@hactrn.net>2011-05-25 18:41:25 +0000
commit6d820903da15263b6cd32396d112e1622d931930 (patch)
treec06ec2874003849e75517449c7a4ee6bf031d27b
parent7cbcb564d976d5b273e6954d77a1085a875afca1 (diff)
Type-safe wrappers around common string types.
svn path=/rcynic-ng/rcynic.c; revision=3836
-rw-r--r--rcynic-ng/rcynic.c938
1 files changed, 503 insertions, 435 deletions
diff --git a/rcynic-ng/rcynic.c b/rcynic-ng/rcynic.c
index fdf45dd4..45a53cd4 100644
--- a/rcynic-ng/rcynic.c
+++ b/rcynic-ng/rcynic.c
@@ -95,8 +95,8 @@
*/
#define KILL_MAX 10
-#ifndef HOST_NAME_MAX
-#define HOST_NAME_MAX 256
+#ifndef HOSTNAME_MAX
+#define HOSTNAME_MAX 256
#endif
/**
@@ -264,6 +264,7 @@ static const struct {
QB(manifest_mismatch, "Manifest doesn't match SIA") \
QB(trust_anchor_with_crldp, "Trust anchor can't have CRLDP") \
QW(object_not_in_manifest, "Object not in manifest") \
+ QB(hash_too_long, "Hash value is too long") \
MIB_COUNTERS_FROM_OPENSSL
#define QV(x) QB(mib_openssl_##x, 0)
@@ -306,11 +307,31 @@ static const long mib_counter_openssl[] = { MIB_COUNTERS 0 };
#undef QQ
/**
+ * Type-safe string wrapper for URIs.
+ */
+typedef struct { char s[URI_MAX]; } uri_t;
+
+/**
+ * Type-safe string wrapper for filename paths.
+ */
+typedef struct { char s[FILENAME_MAX]; } path_t;
+
+/**
+ * Type-safe string wrapper for hostnames.
+ */
+typedef struct { char s[HOSTNAME_MAX]; } hostname_t;
+
+/**
+ * Type-safe wrapper for hash buffers.
+ */
+typedef struct { unsigned char h[EVP_MAX_MD_SIZE]; } hashbuf_t;
+
+/**
* Per-host MIB counter object.
* hostname[] must be first element.
*/
typedef struct host_mib_counter {
- char hostname[URI_MAX];
+ path_t hostname; /* uri_to_filename() wants path_t */
unsigned long counters[MIB_COUNTER_T_MAX];
} HOST_MIB_COUNTER;
@@ -320,7 +341,7 @@ DECLARE_STACK_OF(HOST_MIB_COUNTER)
* Per-URI validation status object.
*/
typedef struct validation_status {
- char uri[URI_MAX];
+ uri_t uri;
time_t timestamp;
mib_counter_t code;
} VALIDATION_STATUS;
@@ -332,14 +353,14 @@ DECLARE_STACK_OF(VALIDATION_STATUS)
*/
typedef struct certinfo {
int ca, ta;
- char uri[URI_MAX], sia[URI_MAX], aia[URI_MAX], crldp[URI_MAX], manifest[URI_MAX];
+ uri_t uri, sia, aia, crldp, manifest;
} certinfo_t;
/**
* Program context that would otherwise be a mess of global variables.
*/
typedef struct rcynic_ctx {
- char *authenticated, *old_authenticated, *unauthenticated;
+ path_t authenticated, old_authenticated, unauthenticated;
char *jane, *rsync_program;
STACK_OF(OPENSSL_STRING) *rsync_cache, *backup_cache, *stale_cache;
STACK_OF(HOST_MIB_COUNTER) *host_counters;
@@ -391,6 +412,8 @@ typedef struct rcynic_x509_store_ctx {
const certinfo_t *subject;
} rcynic_x509_store_ctx_t;
+
+
/**
* Subversion ID data.
*/
@@ -498,6 +521,25 @@ static void VALIDATION_STATUS_free(VALIDATION_STATUS *v)
+/*
+ * GCC attributes to help catch format string errors.
+ */
+
+#ifdef __GNUC__
+
+static void logmsg(const rcynic_ctx_t *rc,
+ const log_level_t level,
+ const char *fmt, ...)
+ __attribute__ ((format (printf, 3, 4)));
+
+static void reject(const rcynic_ctx_t *rc,
+ const uri_t *uri,
+ const mib_counter_t code,
+ const char *fmt, ...)
+ __attribute__ ((format (printf, 4, 5)));
+
+#endif
+
/**
* Logging.
*/
@@ -558,9 +600,9 @@ static void log_openssl_errors(const rcynic_ctx_t *rc)
while ((code = ERR_get_error_line_data(&file, &line, &data, &flags))) {
ERR_error_string_n(code, error, sizeof(error));
if (data && (flags & ERR_TXT_STRING))
- logmsg(rc, log_sys_err, "OpenSSL error %s:%d: %s", file, line, error, data);
+ logmsg(rc, log_sys_err, "OpenSSL error %s:%d: %s: %s", file, line, error, data);
else
- logmsg(rc, log_sys_err, "OpenSSL error %s:%d", file, line, error);
+ logmsg(rc, log_sys_err, "OpenSSL error %s:%d: %s", file, line, error);
}
}
@@ -656,28 +698,29 @@ static int configure_integer(const rcynic_ctx_t *rc,
/**
* Make a directory if it doesn't already exist.
*/
-static int mkdir_maybe(const rcynic_ctx_t *rc, const char *name)
+static int mkdir_maybe(const rcynic_ctx_t *rc, const path_t *name)
{
- char *b, buffer[FILENAME_MAX];
+ path_t path;
+ char *s;
assert(name != NULL);
- if (strlen(name) >= sizeof(buffer)) {
- logmsg(rc, log_data_err, "Pathname %s too long", name);
+ if (strlen(name->s) >= sizeof(path.s)) {
+ logmsg(rc, log_data_err, "Pathname %s too long", name->s);
return 0;
}
- strcpy(buffer, name);
- b = buffer[0] == '/' ? buffer + 1 : buffer;
- if ((b = strrchr(b, '/')) == NULL)
+ strcpy(path.s, name->s);
+ s = path.s[0] == '/' ? path.s + 1 : path.s;
+ if ((s = strrchr(s, '/')) == NULL)
return 1;
- *b = '\0';
- if (!mkdir_maybe(rc, buffer)) {
- logmsg(rc, log_sys_err, "Failed to make directory %s", buffer);
+ *s = '\0';
+ if (!mkdir_maybe(rc, &path)) {
+ logmsg(rc, log_sys_err, "Failed to make directory %s", path.s);
return 0;
}
- if (!access(buffer, F_OK))
+ if (!access(path.s, F_OK))
return 1;
- logmsg(rc, log_verbose, "Creating directory %s", buffer);
- return mkdir(buffer, 0777) == 0;
+ logmsg(rc, log_verbose, "Creating directory %s", path.s);
+ return mkdir(path.s, 0777) == 0;
}
/**
@@ -718,43 +761,42 @@ static int is_rsync(const char *uri)
* the log, not the MIB.
*/
static int uri_to_filename(const rcynic_ctx_t *rc,
- const char *uri,
- char *buffer,
- const size_t buflen,
- const char *prefix)
+ const uri_t *uri,
+ path_t *path,
+ const path_t *prefix)
{
const char *u;
size_t n;
- buffer[0] = '\0';
+ path->s[0] = '\0';
- if (!is_rsync(uri)) {
- logmsg(rc, log_telemetry, "%s is not an rsync URI, not converting to filename", uri);
+ if (!is_rsync(uri->s)) {
+ logmsg(rc, log_telemetry, "%s is not an rsync URI, not converting to filename", uri->s);
return 0;
}
- u = uri + SIZEOF_RSYNC;
+ u = uri->s + SIZEOF_RSYNC;
n = strlen(u);
if (u[0] == '/' || u[0] == '.' || strstr(u, "/../") ||
(n >= 3 && !strcmp(u + n - 3, "/.."))) {
- logmsg(rc, log_data_err, "Dangerous URI %s, not converting to filename", uri);
+ logmsg(rc, log_data_err, "Dangerous URI %s, not converting to filename", uri->s);
return 0;
}
if (prefix)
- n += strlen(prefix);
+ n += strlen(prefix->s);
- if (n >= buflen) {
- logmsg(rc, log_data_err, "URI %s too long, not converting to filename", uri);
+ if (n >= sizeof(path->s)) {
+ logmsg(rc, log_data_err, "URI %s too long, not converting to filename", uri->s);
return 0;
}
if (prefix) {
- strcpy(buffer, prefix);
- strcat(buffer, u);
+ strcpy(path->s, prefix->s);
+ strcat(path->s, u);
} else {
- strcpy(buffer, u);
+ strcpy(path->s, u);
}
return 1;
@@ -777,32 +819,32 @@ static int oid_cmp(const ASN1_OBJECT *obj, const unsigned char *oid, const size_
*/
static int host_mib_counter_cmp(const HOST_MIB_COUNTER * const *a, const HOST_MIB_COUNTER * const *b)
{
- return strcasecmp((*a)->hostname, (*b)->hostname);
+ return strcasecmp((*a)->hostname.s, (*b)->hostname.s);
}
/**
* MIB counter manipulation.
*/
static void mib_increment(const rcynic_ctx_t *rc,
- const char *uri,
+ const uri_t *uri,
const mib_counter_t counter)
{
HOST_MIB_COUNTER *h = NULL, hn;
char *s;
- assert(rc && uri && strlen(uri) < URI_MAX);
+ assert(rc && uri);
if (!rc->host_counters)
return;
memset(&hn, 0, sizeof(hn));
- if (!uri_to_filename(rc, uri, hn.hostname, sizeof(hn.hostname), NULL)) {
- logmsg(rc, log_data_err, "Couldn't convert URI %s to hostname", uri);
+ if (!uri_to_filename(rc, uri, &hn.hostname, NULL)) {
+ logmsg(rc, log_data_err, "Couldn't convert URI %s to hostname", uri->s);
return;
}
- if ((s = strchr(hn.hostname, '/')) != NULL)
+ if ((s = strchr(hn.hostname.s, '/')) != NULL)
*s = '\0';
h = sk_HOST_MIB_COUNTER_value(rc->host_counters,
@@ -810,12 +852,12 @@ static void mib_increment(const rcynic_ctx_t *rc,
&hn));
if (!h) {
if ((h = HOST_MIB_COUNTER_new()) == NULL) {
- logmsg(rc, log_sys_err, "Couldn't allocate MIB counters for %s", uri);
+ logmsg(rc, log_sys_err, "Couldn't allocate MIB counters for %s", uri->s);
return;
}
- strcpy(h->hostname, hn.hostname);
+ strcpy(h->hostname.s, hn.hostname.s);
if (!sk_HOST_MIB_COUNTER_push(rc->host_counters, h)) {
- logmsg(rc, log_sys_err, "Couldn't store MIB counters for %s", uri);
+ logmsg(rc, log_sys_err, "Couldn't store MIB counters for %s", uri->s);
free(h);
return;
}
@@ -828,27 +870,27 @@ static void mib_increment(const rcynic_ctx_t *rc,
* Add a validation status entry to internal log.
*/
static void log_validation_status(const rcynic_ctx_t *rc,
- const char *uri,
+ const uri_t *uri,
const mib_counter_t code)
{
VALIDATION_STATUS *v = NULL;
- assert(rc && uri && strlen(uri) < URI_MAX);
+ assert(rc && uri);
if (!rc->validation_status)
return;
if ((v = VALIDATION_STATUS_new()) == NULL) {
- logmsg(rc, log_sys_err, "Couldn't allocate validation status entry for %s", uri);
+ logmsg(rc, log_sys_err, "Couldn't allocate validation status entry for %s", uri->s);
goto punt;
}
- strcpy(v->uri, uri);
+ strcpy(v->uri.s, uri->s);
v->timestamp = time(0);
v->code = code;
if (!sk_VALIDATION_STATUS_push(rc->validation_status, v)) {
- logmsg(rc, log_sys_err, "Couldn't store validation status entry for %s", uri);
+ logmsg(rc, log_sys_err, "Couldn't store validation status entry for %s", uri->s);
goto punt;
}
@@ -863,7 +905,7 @@ static void log_validation_status(const rcynic_ctx_t *rc,
* Reject an object.
*/
static void reject(const rcynic_ctx_t *rc,
- const char *uri,
+ const uri_t *uri,
const mib_counter_t code,
const char *fmt, ...)
{
@@ -871,7 +913,7 @@ static void reject(const rcynic_ctx_t *rc,
va_list ap;
assert(fmt && strlen(fmt) + sizeof("Rejected %s") < sizeof(format));
- snprintf(format, sizeof(format), "Rejected %s %s", uri, fmt);
+ snprintf(format, sizeof(format), "Rejected %s %s", uri->s, fmt);
log_validation_status(rc, uri, code);
va_start(ap, fmt);
vlogmsg(rc, log_data_err, format, ap);
@@ -881,13 +923,13 @@ static void reject(const rcynic_ctx_t *rc,
/**
* Copy a file
*/
-static int cp(const char *source, const char *target)
+static int cp(const path_t *source, const path_t *target)
{
FILE *in = NULL, *out = NULL;
int c, ret = 0;
- if ((in = fopen(source, "rb")) == NULL ||
- (out = fopen(target, "wb")) == NULL)
+ if ((in = fopen(source->s, "rb")) == NULL ||
+ (out = fopen(target->s, "wb")) == NULL)
goto done;
while ((c = getc(in)) != EOF)
@@ -905,10 +947,10 @@ static int cp(const char *source, const char *target)
/**
* Link a file
*/
-static int ln(const char *source, const char *target)
+static int ln(const path_t *source, const path_t *target)
{
- unlink(target);
- return link(source, target) == 0;
+ unlink(target->s);
+ return link(source->s, target->s) == 0;
}
/**
@@ -921,28 +963,28 @@ static int ln(const char *source, const char *target)
* So we now make copy vs link a configuration choice.
*/
static int install_object(const rcynic_ctx_t *rc,
- const char *uri,
- const char *source)
+ const uri_t *uri,
+ const path_t *source)
{
- char target[FILENAME_MAX];
+ path_t target;
- if (!uri_to_filename(rc, uri, target, sizeof(target), rc->authenticated)) {
- logmsg(rc, log_data_err, "Couldn't generate installation name for %s", uri);
+ if (!uri_to_filename(rc, uri, &target, &rc->authenticated)) {
+ logmsg(rc, log_data_err, "Couldn't generate installation name for %s", uri->s);
return 0;
}
- if (!mkdir_maybe(rc, target)) {
- logmsg(rc, log_sys_err, "Couldn't create directory for %s", target);
+ if (!mkdir_maybe(rc, &target)) {
+ logmsg(rc, log_sys_err, "Couldn't create directory for %s", target.s);
return 0;
}
- if (rc->use_links ? !ln(source, target) : !cp(source, target)) {
+ if (rc->use_links ? !ln(source, &target) : !cp(source, &target)) {
logmsg(rc, log_sys_err, "Couldn't %s %s to %s",
- (rc->use_links ? "link" : "copy"), source, target);
+ (rc->use_links ? "link" : "copy"), source->s, target.s);
return 0;
}
log_validation_status(rc, uri, validation_ok);
- logmsg(rc, log_telemetry, "Accepted %s", uri);
+ logmsg(rc, log_telemetry, "Accepted %s", uri->s);
return 1;
}
@@ -975,43 +1017,44 @@ static int startswith(const char *str, const char *prefix)
* Set a directory name, making sure it has the trailing slash we
* require in various other routines.
*/
-static void set_directory(char **out, const char *in)
+static int set_directory(const rcynic_ctx_t *rc, path_t *out, const char *in)
{
int need_slash;
size_t n;
- char *s;
- assert(in && out);
+ assert(rc && in && out);
n = strlen(in);
assert(n > 0);
need_slash = in[n - 1] != '/';
- s = malloc(n + need_slash + 1);
- assert(s != NULL);
- strcpy(s, in);
+
+ if (n + need_slash + 1 > sizeof(out->s)) {
+ logmsg(rc, log_usage_err, "Path \"%s\" too long", in);
+ return 0;
+ }
+
+ strcpy(out->s, in);
if (need_slash)
- strcat(s, "/");
- if (*out)
- free(*out);
- *out = s;
+ strcat(out->s, "/");
+ return 1;
}
/**
* Remove a directory tree, like rm -rf.
*/
-static int rm_rf(const char *name)
+static int rm_rf(const path_t *name)
{
- char path[FILENAME_MAX];
+ path_t path;
struct dirent *d;
size_t len;
DIR *dir;
int ret = 0, need_slash;
assert(name);
- len = strlen(name);
- assert(len > 0 && len < sizeof(path));
- need_slash = name[len - 1] != '/';
+ len = strlen(name->s);
+ assert(len > 0 && len < sizeof(path.s));
+ need_slash = name->s[len - 1] != '/';
- if (rmdir(name) == 0)
+ if (rmdir(name->s) == 0)
return 1;
switch (errno) {
@@ -1023,31 +1066,31 @@ static int rm_rf(const char *name)
return 0;
}
- if ((dir = opendir(name)) == NULL)
+ if ((dir = opendir(name->s)) == NULL)
return 0;
while ((d = readdir(dir)) != NULL) {
if (d->d_name[0] == '.' && (d->d_name[1] == '\0' || (d->d_name[1] == '.' && d->d_name[2] == '\0')))
continue;
- if (len + strlen(d->d_name) + need_slash >= sizeof(path))
+ if (len + strlen(d->d_name) + need_slash >= sizeof(path.s))
goto done;
- strcpy(path, name);
+ strcpy(path.s, name->s);
if (need_slash)
- strcat(path, "/");
- strcat(path, d->d_name);
+ strcat(path.s, "/");
+ strcat(path.s, d->d_name);
switch (d->d_type) {
case DT_DIR:
- if (!rm_rf(path))
+ if (!rm_rf(&path))
goto done;
continue;
default:
- if (unlink(path) < 0)
+ if (unlink(path.s) < 0)
goto done;
continue;
}
}
- ret = rmdir(name) == 0;
+ ret = rmdir(name->s) == 0;
done:
closedir(dir);
@@ -1062,11 +1105,11 @@ static int rm_rf(const char *name)
*/
static STACK_OF(OPENSSL_STRING) *directory_filenames(const rcynic_ctx_t *rc,
const walk_pass_t pass,
- const char *uri)
+ const uri_t *uri)
{
STACK_OF(OPENSSL_STRING) *result = NULL;
- char path[FILENAME_MAX];
- const char *prefix = NULL;
+ path_t path;
+ const path_t *prefix = NULL;
DIR *dir = NULL;
struct dirent *d;
int ok = 0;
@@ -1075,17 +1118,17 @@ static STACK_OF(OPENSSL_STRING) *directory_filenames(const rcynic_ctx_t *rc,
switch (pass) {
case walk_pass_current:
- prefix = rc->unauthenticated;
+ prefix = &rc->unauthenticated;
break;
case walk_pass_backup:
- prefix = rc->old_authenticated;
+ prefix = &rc->old_authenticated;
break;
default:
goto done;
}
- if (!uri_to_filename(rc, uri, path, sizeof(path), prefix) ||
- (dir = opendir(path)) == NULL ||
+ if (!uri_to_filename(rc, uri, &path, prefix) ||
+ (dir = opendir(path.s)) == NULL ||
(result = sk_OPENSSL_STRING_new(uri_cmp)) == NULL)
goto done;
@@ -1198,7 +1241,7 @@ static int walk_ctx_loop_next(const rcynic_ctx_t *rc, walk_ctx_t *w)
w->manifest_iteration = 0;
w->filename_iteration = 0;
sk_OPENSSL_STRING_pop_free(w->filenames, OPENSSL_STRING_free);
- w->filenames = directory_filenames(rc, w->pass, w->certinfo.sia);
+ w->filenames = directory_filenames(rc, w->pass, &w->certinfo.sia);
}
return !walk_ctx_loop_done(w);
@@ -1210,7 +1253,7 @@ static int walk_ctx_loop_next(const rcynic_ctx_t *rc, walk_ctx_t *w)
static int walk_ctx_loop_init(const rcynic_ctx_t *rc, walk_ctx_t *w)
{
assert(w->pass == walk_pass_current && w->manifest_iteration == 0 && w->filename_iteration == 0 && w->filenames == NULL);
- w->filenames = directory_filenames(rc, w->pass, w->certinfo.sia);
+ w->filenames = directory_filenames(rc, w->pass, &w->certinfo.sia);
if ((w->manifest && w->manifest_iteration < sk_FileAndHash_num(w->manifest->fileList)) ||
(w->filenames && w->filename_iteration < sk_OPENSSL_STRING_num(w->filenames)))
return 1;
@@ -1333,9 +1376,9 @@ static int rsync_cached_string(const rcynic_ctx_t *rc,
* Check whether a particular URI has been cached.
*/
static int rsync_cached_uri(const rcynic_ctx_t *rc,
- const char *uri)
+ const uri_t *uri)
{
- return is_rsync(uri) && rsync_cached_string(rc, uri + SIZEOF_RSYNC);
+ return is_rsync(uri->s) && rsync_cached_string(rc, uri->s + SIZEOF_RSYNC);
}
@@ -1360,14 +1403,15 @@ static int rsync_cached_uri(const rcynic_ctx_t *rc,
*/
static int rsync(const rcynic_ctx_t *rc,
const char * const *args,
- const char *uri)
+ const uri_t *uri)
{
static const char *rsync_cmd[] = {
"rsync", "--update", "--times", "--copy-links", "--itemize-changes", NULL
};
const char *argv[100];
- char *s, *b, buffer[URI_MAX * 4], path[FILENAME_MAX];
+ char *s, *b, buffer[URI_MAX * 4];
+ path_t path;
int i, n, ret, pipe_fds[2], argc = 0, pid_status = -1;
time_t now, deadline;
struct timeval tv;
@@ -1392,29 +1436,29 @@ static int rsync(const rcynic_ctx_t *rc,
if (rc->rsync_program)
argv[0] = rc->rsync_program;
- if (!uri_to_filename(rc, uri, path, sizeof(path), rc->unauthenticated)) {
- logmsg(rc, log_data_err, "Couldn't extract filename from URI: %s", uri);
+ if (!uri_to_filename(rc, uri, &path, &rc->unauthenticated)) {
+ logmsg(rc, log_data_err, "Couldn't extract filename from URI: %s", uri->s);
return 0;
}
assert(argc < sizeof(argv)/sizeof(*argv));
- argv[argc++] = uri;
+ argv[argc++] = uri->s;
assert(argc < sizeof(argv)/sizeof(*argv));
- argv[argc++] = path;
+ argv[argc++] = path.s;
- assert(strlen(uri) > SIZEOF_RSYNC);
+ assert(strlen(uri->s) > SIZEOF_RSYNC);
if (rsync_cached_uri(rc, uri)) {
- logmsg(rc, log_verbose, "rsync cache hit for %s", uri);
+ logmsg(rc, log_verbose, "rsync cache hit for %s", uri->s);
return 1;
}
- if (!mkdir_maybe(rc, path)) {
- logmsg(rc, log_sys_err, "Couldn't make target directory: %s", path);
+ if (!mkdir_maybe(rc, &path)) {
+ logmsg(rc, log_sys_err, "Couldn't make target directory: %s", path.s);
return 0;
}
- logmsg(rc, log_telemetry, "Fetching %s", uri);
+ logmsg(rc, log_telemetry, "Fetching %s", uri->s);
for (i = 0; i < argc; i++)
logmsg(rc, log_verbose, "rsync argv[%d]: %s", i, argv[i]);
@@ -1515,7 +1559,7 @@ static int rsync(const rcynic_ctx_t *rc,
if (rc->rsync_timeout && now >= deadline)
logmsg(rc, log_data_err,
"Fetch of %s took longer than %d seconds, terminating fetch",
- uri, rc->rsync_timeout);
+ uri->s, rc->rsync_timeout);
assert(pid > 0);
for (i = 0; i < KILL_MAX && wpid == 0; i++) {
@@ -1526,7 +1570,7 @@ static int rsync(const rcynic_ctx_t *rc,
if (WEXITSTATUS(pid_status)) {
logmsg(rc, log_data_err, "rsync exited with status %d fetching %s",
- WEXITSTATUS(pid_status), uri);
+ WEXITSTATUS(pid_status), uri->s);
ret = 0;
mib_increment(rc, uri, (rc->rsync_timeout && now >= deadline
? rsync_timed_out
@@ -1536,12 +1580,12 @@ static int rsync(const rcynic_ctx_t *rc,
mib_increment(rc, uri, rsync_succeeded);
}
- assert(strlen(uri) > SIZEOF_RSYNC);
- strcpy(buffer, uri + SIZEOF_RSYNC);
+ assert(strlen(uri->s) > SIZEOF_RSYNC);
+ strcpy(buffer, uri->s + SIZEOF_RSYNC);
if ((s = strrchr(buffer, '/')) != NULL && s[1] == '\0')
*s = '\0';
if (!sk_OPENSSL_STRING_push_strdup(rc->rsync_cache, buffer))
- logmsg(rc, log_sys_err, "Couldn't cache URI %s, blundering onward", uri);
+ logmsg(rc, log_sys_err, "Couldn't cache URI %s, blundering onward", uri->s);
return ret;
}
@@ -1549,7 +1593,7 @@ static int rsync(const rcynic_ctx_t *rc,
/**
* rsync a single file (CRL, manifest, ROA, whatever).
*/
-static int rsync_file(const rcynic_ctx_t *rc, const char *uri)
+static int rsync_file(const rcynic_ctx_t *rc, const uri_t *uri)
{
return rsync(rc, NULL, uri);
}
@@ -1557,7 +1601,7 @@ static int rsync_file(const rcynic_ctx_t *rc, const char *uri)
/**
* rsync an entire subtree, generally rooted at a SIA collection.
*/
-static int rsync_tree(const rcynic_ctx_t *rc, const char *uri)
+static int rsync_tree(const rcynic_ctx_t *rc, const uri_t *uri)
{
static const char * const rsync_args[] = { "--recursive", "--delete", NULL };
return rsync(rc, rsync_args, uri);
@@ -1570,76 +1614,76 @@ static int rsync_tree(const rcynic_ctx_t *rc, const char *uri)
* if the URI changes and we never visit the old URI again.
*/
static int prune_unauthenticated(const rcynic_ctx_t *rc,
- const char *name,
+ const path_t *name,
const size_t baselen)
{
- char path[FILENAME_MAX];
+ path_t path;
struct dirent *d;
size_t len;
DIR *dir;
int need_slash;
assert(rc && name && baselen > 0);
- len = strlen(name);
- assert(len >= baselen && len < sizeof(path));
- need_slash = name[len - 1] != '/';
+ len = strlen(name->s);
+ assert(len >= baselen && len < sizeof(path.s));
+ need_slash = name->s[len - 1] != '/';
- if (rsync_cached_string(rc, name + baselen)) {
- logmsg(rc, log_debug, "prune: cache hit for %s, not cleaning", name);
+ if (rsync_cached_string(rc, name->s + baselen)) {
+ logmsg(rc, log_debug, "prune: cache hit for %s, not cleaning", name->s);
return 1;
}
- if (rmdir(name) == 0) {
- logmsg(rc, log_debug, "prune: removed %s", name);
+ if (rmdir(name->s) == 0) {
+ logmsg(rc, log_debug, "prune: removed %s", name->s);
return 1;
}
switch (errno) {
case ENOENT:
- logmsg(rc, log_debug, "prune: nonexistant %s", name);
+ logmsg(rc, log_debug, "prune: nonexistant %s", name->s);
return 1;
case ENOTEMPTY:
break;
default:
- logmsg(rc, log_debug, "prune: other error %s: %s", name, strerror(errno));
+ logmsg(rc, log_debug, "prune: other error %s: %s", name->s, strerror(errno));
return 0;
}
- if ((dir = opendir(name)) == NULL)
+ if ((dir = opendir(name->s)) == NULL)
return 0;
while ((d = readdir(dir)) != NULL) {
if (d->d_name[0] == '.' && (d->d_name[1] == '\0' || (d->d_name[1] == '.' && d->d_name[2] == '\0')))
continue;
if (len + strlen(d->d_name) + need_slash >= sizeof(path)) {
- logmsg(rc, log_debug, "prune: %s%s%s too long", name, (need_slash ? "/" : ""), d->d_name);
+ logmsg(rc, log_debug, "prune: %s%s%s too long", name->s, (need_slash ? "/" : ""), d->d_name);
goto done;
}
- strcpy(path, name);
+ strcpy(path.s, name->s);
if (need_slash)
- strcat(path, "/");
- strcat(path, d->d_name);
+ strcat(path.s, "/");
+ strcat(path.s, d->d_name);
switch (d->d_type) {
case DT_DIR:
- if (!prune_unauthenticated(rc, path, baselen))
+ if (!prune_unauthenticated(rc, &path, baselen))
goto done;
continue;
default:
- if (rsync_cached_string(rc, path + baselen)) {
- logmsg(rc, log_debug, "prune: cache hit %s", path);
+ if (rsync_cached_string(rc, path.s + baselen)) {
+ logmsg(rc, log_debug, "prune: cache hit %s", path.s);
continue;
}
- if (unlink(path) < 0) {
- logmsg(rc, log_debug, "prune: removing %s failed: %s", path, strerror(errno));
+ if (unlink(path.s) < 0) {
+ logmsg(rc, log_debug, "prune: removing %s failed: %s", path.s, strerror(errno));
goto done;
}
- logmsg(rc, log_debug, "prune: removed %s", path);
+ logmsg(rc, log_debug, "prune: removed %s", path.s);
continue;
}
}
- if (rmdir(name) < 0 && errno != ENOTEMPTY)
- logmsg(rc, log_debug, "prune: couldn't remove %s: %s", name, strerror(errno));
+ if (rmdir(name->s) < 0 && errno != ENOTEMPTY)
+ logmsg(rc, log_debug, "prune: couldn't remove %s: %s", name->s, strerror(errno));
done:
closedir(dir);
@@ -1654,16 +1698,15 @@ static int prune_unauthenticated(const rcynic_ctx_t *rc,
* sets the hash buffer (if specified) as a side effect. The default
* hash algorithm is SHA-256.
*/
-static void *read_file_with_hash(const char *filename,
+static void *read_file_with_hash(const path_t *filename,
const ASN1_ITEM *it,
const EVP_MD *md,
- unsigned char *hash,
- const size_t hashlen)
+ hashbuf_t *hash)
{
void *result = NULL;
BIO *b;
- if ((b = BIO_new_file(filename, "rb")) == NULL)
+ if ((b = BIO_new_file(filename->s, "rb")) == NULL)
goto error;
if (hash != NULL) {
@@ -1684,8 +1727,8 @@ static void *read_file_with_hash(const char *filename,
goto error;
if (hash != NULL) {
- memset(hash, 0, hashlen);
- BIO_gets(b, (char *) hash, hashlen);
+ memset(hash, 0, sizeof(*hash));
+ BIO_gets(b, (char *) hash, sizeof(hash->h));
}
error:
@@ -1696,25 +1739,25 @@ static void *read_file_with_hash(const char *filename,
/**
* Read and hash a certificate.
*/
-static X509 *read_cert(const char *filename, unsigned char *hash, const size_t hashlen)
+static X509 *read_cert(const path_t *filename, hashbuf_t *hash)
{
- return read_file_with_hash(filename, ASN1_ITEM_rptr(X509), NULL, hash, hashlen);
+ return read_file_with_hash(filename, ASN1_ITEM_rptr(X509), NULL, hash);
}
/**
* Read and hash a CRL.
*/
-static X509_CRL *read_crl(const char *filename, unsigned char *hash, const size_t hashlen)
+static X509_CRL *read_crl(const path_t *filename, hashbuf_t *hash)
{
- return read_file_with_hash(filename, ASN1_ITEM_rptr(X509_CRL), NULL, hash, hashlen);
+ return read_file_with_hash(filename, ASN1_ITEM_rptr(X509_CRL), NULL, hash);
}
/**
* Read and hash a CMS message.
*/
-static CMS_ContentInfo *read_cms(const char *filename, unsigned char *hash, const size_t hashlen)
+static CMS_ContentInfo *read_cms(const path_t *filename, hashbuf_t *hash)
{
- return read_file_with_hash(filename, ASN1_ITEM_rptr(CMS_ContentInfo), NULL, hash, hashlen);
+ return read_file_with_hash(filename, ASN1_ITEM_rptr(CMS_ContentInfo), NULL, hash);
}
@@ -1723,10 +1766,9 @@ static CMS_ContentInfo *read_cms(const char *filename, unsigned char *hash, cons
* Extract CRLDP data from a certificate.
*/
static void extract_crldp_uri(const rcynic_ctx_t *rc,
- const char *uri,
+ const uri_t *uri,
const STACK_OF(DIST_POINT) *crldp,
- char *result,
- const int resultlen)
+ uri_t *result)
{
DIST_POINT *d;
int i;
@@ -1735,7 +1777,7 @@ static void extract_crldp_uri(const rcynic_ctx_t *rc,
if (sk_DIST_POINT_num(crldp) != 1) {
logmsg(rc, log_data_err, "CRLDistributionPoints sequence length is %d (should be 1) for %s",
- sk_DIST_POINT_num(crldp), uri);
+ sk_DIST_POINT_num(crldp), uri->s);
mib_increment(rc, uri, malformed_crldp);
return;
}
@@ -1743,7 +1785,7 @@ static void extract_crldp_uri(const rcynic_ctx_t *rc,
d = sk_DIST_POINT_value(crldp, 0);
if (d->reasons || d->CRLissuer || !d->distpoint || d->distpoint->type != 0) {
- logmsg(rc, log_data_err, "CRLDP does not match RPKI certificate profile for %s", uri);
+ logmsg(rc, log_data_err, "CRLDP does not match RPKI certificate profile for %s", uri->s);
mib_increment(rc, uri, malformed_crldp);
return;
}
@@ -1752,22 +1794,22 @@ static void extract_crldp_uri(const rcynic_ctx_t *rc,
GENERAL_NAME *n = sk_GENERAL_NAME_value(d->distpoint->name.fullname, i);
assert(n != NULL);
if (n->type != GEN_URI) {
- logmsg(rc, log_data_err, "CRLDP contains non-URI GeneralName for %s", uri);
+ logmsg(rc, log_data_err, "CRLDP contains non-URI GeneralName for %s", uri->s);
mib_increment(rc, uri, malformed_crldp);
return;
}
if (!is_rsync((char *) n->d.uniformResourceIdentifier->data)) {
logmsg(rc, log_verbose, "Skipping non-rsync URI %s for %s",
- (char *) n->d.uniformResourceIdentifier->data, uri);
+ (char *) n->d.uniformResourceIdentifier->data, uri->s);
continue;
}
- if (resultlen <= n->d.uniformResourceIdentifier->length) {
+ if (sizeof(result->s) <= n->d.uniformResourceIdentifier->length) {
logmsg(rc, log_data_err, "Skipping improbably long URI %s for %s",
- (char *) n->d.uniformResourceIdentifier->data, uri);
+ (char *) n->d.uniformResourceIdentifier->data, uri->s);
mib_increment(rc, uri, uri_too_long);
continue;
}
- strcpy(result, (char *) n->d.uniformResourceIdentifier->data);
+ strcpy(result->s, (char *) n->d.uniformResourceIdentifier->data);
return;
}
}
@@ -1776,12 +1818,11 @@ static void extract_crldp_uri(const rcynic_ctx_t *rc,
* Extract SIA or AIA data from a certificate.
*/
static void extract_access_uri(const rcynic_ctx_t *rc,
- const char *uri,
+ const uri_t *uri,
const AUTHORITY_INFO_ACCESS *xia,
const unsigned char *oid,
const int oidlen,
- char *result,
- const int resultlen)
+ uri_t *result)
{
int i;
@@ -1797,16 +1838,16 @@ static void extract_access_uri(const rcynic_ctx_t *rc,
continue;
if (!is_rsync((char *) a->location->d.uniformResourceIdentifier->data)) {
logmsg(rc, log_verbose, "Skipping non-rsync URI %s for %s",
- a->location->d.uniformResourceIdentifier->data, uri);
+ a->location->d.uniformResourceIdentifier->data, uri->s);
continue;
}
- if (resultlen <= a->location->d.uniformResourceIdentifier->length) {
+ if (sizeof(result->s) <= a->location->d.uniformResourceIdentifier->length) {
logmsg(rc, log_data_err, "Skipping improbably long URI %s for %s",
- a->location->d.uniformResourceIdentifier->data, uri);
+ a->location->d.uniformResourceIdentifier->data, uri->s);
mib_increment(rc, uri, uri_too_long);
continue;
}
- strcpy(result, (char *) a->location->d.uniformResourceIdentifier->data);
+ strcpy(result->s, (char *) a->location->d.uniformResourceIdentifier->data);
return;
}
}
@@ -1814,7 +1855,7 @@ static void extract_access_uri(const rcynic_ctx_t *rc,
/**
* Parse interesting stuff from a certificate.
*/
-static void parse_cert(const rcynic_ctx_t *rc, X509 *x, certinfo_t *c, const char *uri)
+static void parse_cert(const rcynic_ctx_t *rc, X509 *x, certinfo_t *c, const uri_t *uri)
{
STACK_OF(DIST_POINT) *crldp;
AUTHORITY_INFO_ACCESS *xia;
@@ -1824,22 +1865,22 @@ static void parse_cert(const rcynic_ctx_t *rc, X509 *x, certinfo_t *c, const cha
c->ca = X509_check_ca(x) == 1;
- assert(strlen(uri) < sizeof(c->uri));
- strcpy(c->uri, uri);
+ assert(strlen(uri->s) < sizeof(c->uri));
+ strcpy(c->uri.s, uri->s);
if ((xia = X509_get_ext_d2i(x, NID_info_access, NULL, NULL)) != NULL) {
- extract_access_uri(rc, uri, xia, id_ad_caIssuers, sizeof(id_ad_caIssuers), c->aia, sizeof(c->aia));
+ extract_access_uri(rc, uri, xia, id_ad_caIssuers, sizeof(id_ad_caIssuers), &c->aia);
sk_ACCESS_DESCRIPTION_pop_free(xia, ACCESS_DESCRIPTION_free);
}
if ((xia = X509_get_ext_d2i(x, NID_sinfo_access, NULL, NULL)) != NULL) {
- extract_access_uri(rc, uri, xia, id_ad_caRepository, sizeof(id_ad_caRepository), c->sia, sizeof(c->sia));
- extract_access_uri(rc, uri, xia, id_ad_rpkiManifest, sizeof(id_ad_rpkiManifest), c->manifest, sizeof(c->manifest));
+ extract_access_uri(rc, uri, xia, id_ad_caRepository, sizeof(id_ad_caRepository), &c->sia);
+ extract_access_uri(rc, uri, xia, id_ad_rpkiManifest, sizeof(id_ad_rpkiManifest), &c->manifest);
sk_ACCESS_DESCRIPTION_pop_free(xia, ACCESS_DESCRIPTION_free);
}
if ((crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL)) != NULL) {
- extract_crldp_uri(rc, uri, crldp, c->crldp, sizeof(c->crldp));
+ extract_crldp_uri(rc, uri, crldp, &c->crldp);
sk_DIST_POINT_pop_free(crldp, DIST_POINT_free);
}
}
@@ -1851,32 +1892,39 @@ static void parse_cert(const rcynic_ctx_t *rc, X509 *x, certinfo_t *c, const cha
*/
static X509_CRL *check_crl_1(const rcynic_ctx_t *rc,
- const char *uri,
- char *path, const int pathlen,
- const char *prefix,
+ const uri_t *uri,
+ path_t *path,
+ const path_t *prefix,
X509 *issuer,
const unsigned char *hash,
const size_t hashlen)
{
- unsigned char hashbuf[EVP_MAX_MD_SIZE];
+ hashbuf_t hashbuf;
X509_CRL *crl = NULL;
EVP_PKEY *pkey;
int ret;
- assert(uri && path && issuer && hashlen <= sizeof(hashbuf));
+ assert(uri && path && issuer);
- if (!uri_to_filename(rc, uri, path, pathlen, prefix))
+ if (!uri_to_filename(rc, uri, path, prefix))
goto punt;
+ if (hashlen > sizeof(hashbuf.h)) {
+ reject(rc, uri, hash_too_long,
+ "because supplied hash is too long (%lu, our max is %lu)",
+ (unsigned long) hashlen, (unsigned long) sizeof(hashbuf.h));
+ goto punt;
+ }
+
if (hash)
- crl = read_crl(path, hashbuf, sizeof(hashbuf));
+ crl = read_crl(path, &hashbuf);
else
- crl = read_crl(path, NULL, 0);
+ crl = read_crl(path, NULL);
if (!crl)
goto punt;
- if (hash && memcmp(hashbuf, hash, hashlen)) {
+ if (hash && memcmp(hashbuf.h, hash, hashlen)) {
reject(rc, uri, crl_digest_mismatch,
"because digest of CRL did not match value from manifest");
goto punt;
@@ -1900,37 +1948,37 @@ static X509_CRL *check_crl_1(const rcynic_ctx_t *rc,
* and check issuer's signature if we don't.
*/
static X509_CRL *check_crl(const rcynic_ctx_t *rc,
- const char *uri,
+ const uri_t *uri,
X509 *issuer,
const unsigned char *hash,
const size_t hashlen)
{
- char path[FILENAME_MAX];
+ path_t path;
X509_CRL *crl;
- if (uri_to_filename(rc, uri, path, sizeof(path), rc->authenticated) &&
- (crl = read_crl(path, NULL, 0)) != NULL)
+ if (uri_to_filename(rc, uri, &path, &rc->authenticated) &&
+ (crl = read_crl(&path, NULL)) != NULL)
return crl;
- logmsg(rc, log_telemetry, "Checking CRL %s", uri);
+ logmsg(rc, log_telemetry, "Checking CRL %s", uri->s);
assert(rsync_cached_uri(rc, uri));
- if ((crl = check_crl_1(rc, uri, path, sizeof(path), rc->unauthenticated,
+ if ((crl = check_crl_1(rc, uri, &path, &rc->unauthenticated,
issuer, hash, hashlen))) {
- install_object(rc, uri, path);
+ install_object(rc, uri, &path);
mib_increment(rc, uri, current_crl_accepted);
return crl;
- } else if (!access(path, F_OK)) {
+ } else if (!access(path.s, F_OK)) {
mib_increment(rc, uri, current_crl_rejected);
}
- if ((crl = check_crl_1(rc, uri, path, sizeof(path), rc->old_authenticated,
+ if ((crl = check_crl_1(rc, uri, &path, &rc->old_authenticated,
issuer, hash, hashlen))) {
- install_object(rc, uri, path);
+ install_object(rc, uri, &path);
mib_increment(rc, uri, backup_crl_accepted);
return crl;
- } else if (!access(path, F_OK)) {
+ } else if (!access(path.s, F_OK)) {
mib_increment(rc, uri, backup_crl_rejected);
}
@@ -2012,17 +2060,17 @@ static int check_x509_cb(int ok, X509_STORE_CTX *ctx)
*/
if (rctx->rc->allow_stale_crl) {
ok = 1;
- if (sk_OPENSSL_STRING_find(rctx->rc->stale_cache, rctx->subject->crldp) >= 0)
+ if (sk_OPENSSL_STRING_find(rctx->rc->stale_cache, rctx->subject->crldp.s) >= 0)
return ok;
- if (!sk_OPENSSL_STRING_push_strdup(rctx->rc->stale_cache, rctx->subject->crldp))
+ if (!sk_OPENSSL_STRING_push_strdup(rctx->rc->stale_cache, rctx->subject->crldp.s))
logmsg(rctx->rc, log_sys_err,
- "Couldn't cache stale CRLDP %s, blundering onward", rctx->subject->crldp);
+ "Couldn't cache stale CRLDP %s, blundering onward", rctx->subject->crldp.s);
}
- logmsg(rctx->rc, log_data_err, "Stale CRL %s", rctx->subject->crldp);
+ logmsg(rctx->rc, log_data_err, "Stale CRL %s", rctx->subject->crldp.s);
if (ok)
- mib_increment(rctx->rc, rctx->subject->uri, stale_crl);
+ mib_increment(rctx->rc, &rctx->subject->uri, stale_crl);
else
- reject(rctx->rc, rctx->subject->uri, stale_crl, "due to stale CRL %s", rctx->subject->crldp);
+ reject(rctx->rc, &rctx->subject->uri, stale_crl, "due to stale CRL %s", rctx->subject->crldp.s);
return ok;
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
@@ -2042,9 +2090,9 @@ static int check_x509_cb(int ok, X509_STORE_CTX *ctx)
if (rctx->rc->allow_non_self_signed_trust_anchor)
ok = 1;
if (ok)
- mib_increment(rctx->rc, rctx->subject->uri, trust_anchor_not_self_signed);
+ mib_increment(rctx->rc, &rctx->subject->uri, trust_anchor_not_self_signed);
else
- reject(rctx->rc, rctx->subject->uri, trust_anchor_not_self_signed,
+ reject(rctx->rc, &rctx->subject->uri, trust_anchor_not_self_signed,
"because trust anchor was not self-signed");
return ok;
@@ -2066,9 +2114,9 @@ static int check_x509_cb(int ok, X509_STORE_CTX *ctx)
}
if (ok)
- mib_increment(rctx->rc, rctx->subject->uri, counter);
+ mib_increment(rctx->rc, &rctx->subject->uri, counter);
else
- reject(rctx->rc, rctx->subject->uri, counter,
+ reject(rctx->rc, &rctx->subject->uri, counter,
"due to validation failure at depth %d: %s",
ctx->error_depth,
X509_verify_cert_error_string(ctx->error));
@@ -2104,81 +2152,81 @@ static int check_x509(const rcynic_ctx_t *rc,
issuer = sk_X509_value(certs, sk_X509_num(certs) - 1);
assert(issuer != NULL);
- if (subject->sia[0] && subject->sia[strlen(subject->sia) - 1] != '/') {
- reject(rc, subject->uri, malformed_sia,
- "due to malformed SIA %s", subject->sia);
+ if (subject->sia.s[0] && subject->sia.s[strlen(subject->sia.s) - 1] != '/') {
+ reject(rc, &subject->uri, malformed_sia,
+ "due to malformed SIA %s", subject->sia.s);
goto done;
}
- if (!subject->ta && !subject->aia[0]) {
- reject(rc, subject->uri, aia_missing, "due to missing AIA extension");
+ if (!subject->ta && !subject->aia.s[0]) {
+ reject(rc, &subject->uri, aia_missing, "due to missing AIA extension");
goto done;
}
- if (!issuer_certinfo->ta && strcmp(issuer_certinfo->uri, subject->aia)) {
- reject(rc, subject->uri, aia_mismatch,
- "because AIA %s doesn't match parent", subject->aia);
+ if (!issuer_certinfo->ta && strcmp(issuer_certinfo->uri.s, subject->aia.s)) {
+ reject(rc, &subject->uri, aia_mismatch,
+ "because AIA %s doesn't match parent", subject->aia.s);
goto done;
}
- if (subject->ca && !subject->sia[0]) {
- reject(rc, subject->uri, sia_missing,
+ if (subject->ca && !subject->sia.s[0]) {
+ reject(rc, &subject->uri, sia_missing,
"because SIA extension repository pointer is missing");
goto done;
}
- if (subject->ca && !subject->manifest[0]) {
- reject(rc, subject->uri, manifest_missing,
+ if (subject->ca && !subject->manifest.s[0]) {
+ reject(rc, &subject->uri, manifest_missing,
"because SIA extension manifest pointer is missing");
goto done;
}
- if (subject->ca && !startswith(subject->manifest, subject->sia)) {
- reject(rc, subject->uri, manifest_mismatch,
+ if (subject->ca && !startswith(subject->manifest.s, subject->sia.s)) {
+ reject(rc, &subject->uri, manifest_mismatch,
"because SIA manifest %s points outside publication point %s",
- subject->manifest, subject->sia);
+ subject->manifest.s, subject->sia.s);
goto done;
}
if (!check_allowed_extensions(x, !subject->ca)) {
- reject(rc, subject->uri, disallowed_extension,
+ reject(rc, &subject->uri, disallowed_extension,
"due to disallowed X.509v3 extension");
goto done;
}
if (subject->ta) {
- if (subject->crldp[0]) {
- reject(rc, subject->uri, trust_anchor_with_crldp,
+ if (subject->crldp.s[0]) {
+ reject(rc, &subject->uri, trust_anchor_with_crldp,
"because it's a trust anchor but has a CRLDP extension");
goto done;
}
} else {
- if (!subject->crldp[0]) {
- reject(rc, subject->uri, crldp_missing, "because CRLDP extension is missing");
+ if (!subject->crldp.s[0]) {
+ reject(rc, &subject->uri, crldp_missing, "because CRLDP extension is missing");
goto done;
}
- if (!subject->ca && !startswith(subject->crldp, issuer_certinfo->sia)) {
- reject(rc, subject->uri, crldp_mismatch,
+ if (!subject->ca && !startswith(subject->crldp.s, issuer_certinfo->sia.s)) {
+ reject(rc, &subject->uri, crldp_mismatch,
"because CRLDP %s points outside issuer's publication point %s",
- subject->crldp, issuer_certinfo->sia);
+ subject->crldp.s, issuer_certinfo->sia.s);
goto done;
}
flags |= X509_V_FLAG_CRL_CHECK;
if ((pkey = X509_get_pubkey(issuer)) == NULL || X509_verify(x, pkey) <= 0) {
- reject(rc, subject->uri, certificate_bad_signature,
+ reject(rc, &subject->uri, certificate_bad_signature,
"because it failed signature check prior to CRL fetch");
goto done;
}
- if ((crl = check_crl(rc, subject->crldp, issuer, NULL, 0)) == NULL) {
- reject(rc, subject->uri, certificate_bad_crl,
- "due to bad CRL %s", subject->crldp);
+ if ((crl = check_crl(rc, &subject->crldp, issuer, NULL, 0)) == NULL) {
+ reject(rc, &subject->uri, certificate_bad_crl,
+ "due to bad CRL %s", subject->crldp.s);
goto done;
}
@@ -2205,7 +2253,7 @@ static int check_x509(const rcynic_ctx_t *rc,
* Redundant error message?
*/
logmsg(rc, log_data_err, "Validation failure for %s",
- subject->uri[0] ? subject->uri : subject->ta ? "[Trust anchor]" : "[???]");
+ subject->uri.s[0] ? subject->uri.s : subject->ta ? "[Trust anchor]" : "[???]");
goto done;
}
@@ -2241,40 +2289,44 @@ static int check_ta(const rcynic_ctx_t *rc,
* the check_x509() tests.
*/
static X509 *check_cert_1(const rcynic_ctx_t *rc,
- const char *uri,
- char *path,
- const int pathlen,
- const char *prefix,
+ const uri_t *uri,
+ path_t *path,
+ const path_t *prefix,
STACK_OF(X509) *certs,
const certinfo_t *issuer,
certinfo_t *subject,
const unsigned char *hash,
const size_t hashlen)
{
- unsigned char hashbuf[EVP_MAX_MD_SIZE];
+ hashbuf_t hashbuf;
X509 *x = NULL;
assert(uri && path && certs && issuer && subject);
- if (!uri_to_filename(rc, uri, path, pathlen, prefix)) {
- logmsg(rc, log_data_err, "Can't convert URI %s to filename", uri);
+ if (!uri_to_filename(rc, uri, path, prefix))
return NULL;
- }
- if (access(path, R_OK))
+ if (access(path->s, R_OK))
return NULL;
+ if (hashlen > sizeof(hashbuf.h)) {
+ reject(rc, uri, hash_too_long,
+ "because supplied hash is too long (%lu, our max is %lu)",
+ (unsigned long) hashlen, (unsigned long) sizeof(hashbuf.h));
+ goto punt;
+ }
+
if (hash)
- x = read_cert(path, hashbuf, sizeof(hashbuf));
+ x = read_cert(path, &hashbuf);
else
- x = read_cert(path, NULL, 0);
+ x = read_cert(path, NULL);
if (!x) {
- logmsg(rc, log_sys_err, "Can't read certificate %s", path);
+ logmsg(rc, log_sys_err, "Can't read certificate %s", path->s);
goto punt;
}
- if (hash && memcmp(hashbuf, hash, hashlen)) {
+ if (hash && memcmp(hashbuf.h, hash, hashlen)) {
reject(rc, uri, certificate_digest_mismatch,
"because digest did not match value in manifest");
goto punt;
@@ -2295,7 +2347,7 @@ static X509 *check_cert_1(const rcynic_ctx_t *rc,
* backup data from a previous run of this program.
*/
static X509 *check_cert(rcynic_ctx_t *rc,
- char *uri,
+ uri_t *uri,
STACK_OF(X509) *certs,
const certinfo_t *issuer,
certinfo_t *subject,
@@ -2304,20 +2356,20 @@ static X509 *check_cert(rcynic_ctx_t *rc,
const size_t hashlen)
{
mib_counter_t accept_code, reject_code;
- const char *prefix = NULL;
- char path[FILENAME_MAX];
+ const path_t *prefix = NULL;
+ path_t path;
X509 *x;
assert(rc && uri && certs && issuer && subject);
switch (pass) {
case walk_pass_current:
- prefix = rc->unauthenticated;
+ prefix = &rc->unauthenticated;
accept_code = current_cert_accepted;
reject_code = current_cert_rejected;
break;
case walk_pass_backup:
- prefix = rc->old_authenticated;
+ prefix = &rc->old_authenticated;
accept_code = backup_cert_accepted;
reject_code = backup_cert_rejected;
break;
@@ -2330,28 +2382,27 @@ static X509 *check_cert(rcynic_ctx_t *rc,
* better data, just get out now.
*/
- if (uri_to_filename(rc, uri, path, sizeof(path), rc->authenticated) &&
- !access(path, R_OK)) {
- if (pass == walk_pass_backup || sk_OPENSSL_STRING_find(rc->backup_cache, uri) < 0)
+ if (uri_to_filename(rc, uri, &path, &rc->authenticated) &&
+ !access(path.s, R_OK)) {
+ if (pass == walk_pass_backup || sk_OPENSSL_STRING_find(rc->backup_cache, uri->s) < 0)
return NULL;
mib_increment(rc, uri, current_cert_recheck);
- logmsg(rc, log_telemetry, "Rechecking %s", uri);
+ logmsg(rc, log_telemetry, "Rechecking %s", uri->s);
} else {
- logmsg(rc, log_telemetry, "Checking %s", uri);
+ logmsg(rc, log_telemetry, "Checking %s", uri->s);
}
rc->indent++;
- if ((x = check_cert_1(rc, uri, path, sizeof(path), prefix,
- certs, issuer, subject, hash, hashlen)) != NULL) {
- install_object(rc, uri, path);
+ if ((x = check_cert_1(rc, uri, &path, prefix, certs, issuer, subject, hash, hashlen)) != NULL) {
+ install_object(rc, uri, &path);
mib_increment(rc, uri, accept_code);
if (pass == walk_pass_current)
- sk_OPENSSL_STRING_remove(rc->backup_cache, uri);
- else if (!sk_OPENSSL_STRING_push_strdup(rc->backup_cache, uri))
- logmsg(rc, log_sys_err, "Couldn't cache URI %s, blundering onward", uri);
+ sk_OPENSSL_STRING_remove(rc->backup_cache, uri->s);
+ else if (!sk_OPENSSL_STRING_push_strdup(rc->backup_cache, uri->s))
+ logmsg(rc, log_sys_err, "Couldn't cache URI %s, blundering onward", uri->s);
- } else if (!access(path, F_OK)) {
+ } else if (!access(path.s, F_OK)) {
mib_increment(rc, uri, reject_code);
}
@@ -2366,10 +2417,9 @@ static X509 *check_cert(rcynic_ctx_t *rc,
* Read and check one manifest from disk.
*/
static Manifest *check_manifest_1(const rcynic_ctx_t *rc,
- const char *uri,
- char *path,
- const int pathlen,
- const char *prefix,
+ const uri_t *uri,
+ path_t *path,
+ const path_t *prefix,
STACK_OF(X509) *certs)
{
CMS_ContentInfo *cms = NULL;
@@ -2387,8 +2437,8 @@ static Manifest *check_manifest_1(const rcynic_ctx_t *rc,
assert(rc && uri && path && prefix && certs && sk_X509_num(certs));
- if (!uri_to_filename(rc, uri, path, pathlen, prefix) ||
- (cms = read_cms(path, NULL, 0)) == NULL)
+ if (!uri_to_filename(rc, uri, path, prefix) ||
+ (cms = read_cms(path, NULL)) == NULL)
goto done;
if ((eContentType = CMS_get0_eContentType(cms)) == NULL ||
@@ -2399,7 +2449,7 @@ static Manifest *check_manifest_1(const rcynic_ctx_t *rc,
}
if ((bio = BIO_new(BIO_s_mem())) == NULL) {
- logmsg(rc, log_sys_err, "Couldn't allocate BIO for manifest %s", uri);
+ logmsg(rc, log_sys_err, "Couldn't allocate BIO for manifest %s", uri->s);
goto done;
}
@@ -2417,16 +2467,16 @@ static Manifest *check_manifest_1(const rcynic_ctx_t *rc,
parse_cert(rc, sk_X509_value(signers, 0), &certinfo, uri);
- if (!certinfo.crldp[0]) {
+ if (!certinfo.crldp.s[0]) {
reject(rc, uri, manifest_missing_crldp,
"due to missing CRLDP in manifest EE certificate");
goto done;
}
- if ((crl_tail = strrchr(certinfo.crldp, '/')) == NULL) {
+ if ((crl_tail = strrchr(certinfo.crldp.s, '/')) == NULL) {
reject(rc, uri, manifest_malformed_crldp,
"due to malformed CRLDP %s in manifest EE certificate",
- certinfo.crldp);
+ certinfo.crldp.s);
goto done;
}
crl_tail++;
@@ -2449,15 +2499,15 @@ static Manifest *check_manifest_1(const rcynic_ctx_t *rc,
}
if (X509_cmp_current_time(manifest->nextUpdate) < 0 &&
- sk_OPENSSL_STRING_find(rc->stale_cache, uri) < 0) {
- if (!sk_OPENSSL_STRING_push_strdup(rc->stale_cache, uri))
- logmsg(rc, log_sys_err, "Couldn't cache stale manifest %s, blundering onward", uri);
+ sk_OPENSSL_STRING_find(rc->stale_cache, uri->s) < 0) {
+ if (!sk_OPENSSL_STRING_push_strdup(rc->stale_cache, uri->s))
+ logmsg(rc, log_sys_err, "Couldn't cache stale manifest %s, blundering onward", uri->s);
if (!rc->allow_stale_manifest) {
reject(rc, uri, stale_manifest,
"because it is a stale manifest");
goto done;
}
- logmsg(rc, log_data_err, "Stale manifest %s", uri);
+ logmsg(rc, log_data_err, "Stale manifest %s", uri->s);
mib_increment(rc, uri, stale_manifest);
}
@@ -2470,21 +2520,23 @@ static Manifest *check_manifest_1(const rcynic_ctx_t *rc,
break;
if (fah) {
- crl = check_crl(rc, certinfo.crldp, sk_X509_value(certs, sk_X509_num(certs) - 1),
+ crl = check_crl(rc, &certinfo.crldp,
+ sk_X509_value(certs, sk_X509_num(certs) - 1),
fah->hash->data, fah->hash->length);
} else if (rc->require_crl_in_manifest) {
reject(rc, uri, crl_not_in_manifest,
- "because CRL %s missing from manifest", certinfo.crldp);
+ "because CRL %s missing from manifest", certinfo.crldp.s);
goto done;
} else {
- logmsg(rc, log_data_err, "Manifest %s is missing entry for CRL %s", uri, certinfo.crldp);
+ logmsg(rc, log_data_err, "Manifest %s is missing entry for CRL %s", uri->s, certinfo.crldp.s);
mib_increment(rc, uri, crl_not_in_manifest);
- crl = check_crl(rc, certinfo.crldp,
- sk_X509_value(certs, sk_X509_num(certs) - 1), NULL, 0);
+ crl = check_crl(rc, &certinfo.crldp,
+ sk_X509_value(certs, sk_X509_num(certs) - 1),
+ NULL, 0);
}
if (!crl) {
- reject(rc, uri, manifest_bad_crl, "due to bad manifest CRL %s", certinfo.crldp);
+ reject(rc, uri, manifest_bad_crl, "due to bad manifest CRL %s", certinfo.crldp.s);
goto done;
}
@@ -2514,7 +2566,7 @@ static Manifest *check_manifest_1(const rcynic_ctx_t *rc,
/*
* Redundant error message?
*/
- logmsg(rc, log_data_err, "Validation failure for manifest %s EE certificate",uri);
+ logmsg(rc, log_data_err, "Validation failure for manifest %s EE certificate", uri->s);
mib_increment(rc, uri, manifest_invalid_ee);
goto done;
}
@@ -2539,16 +2591,16 @@ static Manifest *check_manifest_1(const rcynic_ctx_t *rc,
* and check issuer's signature if we don't.
*/
static Manifest *check_manifest(const rcynic_ctx_t *rc,
- const char *uri,
+ const uri_t *uri,
STACK_OF(X509) *certs)
{
CMS_ContentInfo *cms = NULL;
Manifest *manifest = NULL;
- char path[FILENAME_MAX];
+ path_t path;
BIO *bio = NULL;
- if (uri_to_filename(rc, uri, path, sizeof(path), rc->authenticated) &&
- (cms = read_cms(path, NULL, 0)) != NULL &&
+ if (uri_to_filename(rc, uri, &path, &rc->authenticated) &&
+ (cms = read_cms(&path, NULL)) != NULL &&
(bio = BIO_new(BIO_s_mem()))!= NULL &&
CMS_verify(cms, NULL, NULL, NULL, bio,
CMS_NO_SIGNER_CERT_VERIFY |
@@ -2562,25 +2614,25 @@ static Manifest *check_manifest(const rcynic_ctx_t *rc,
if (manifest != NULL)
return manifest;
- logmsg(rc, log_telemetry, "Checking manifest %s", uri);
+ logmsg(rc, log_telemetry, "Checking manifest %s", uri->s);
assert(rsync_cached_uri(rc, uri));
- if ((manifest = check_manifest_1(rc, uri, path, sizeof(path),
- rc->unauthenticated, certs))) {
- install_object(rc, uri, path);
+ if ((manifest = check_manifest_1(rc, uri, &path,
+ &rc->unauthenticated, certs))) {
+ install_object(rc, uri, &path);
mib_increment(rc, uri, current_manifest_accepted);
return manifest;
- } else if (!access(path, F_OK)) {
+ } else if (!access(path.s, F_OK)) {
mib_increment(rc, uri, current_manifest_rejected);
}
- if ((manifest = check_manifest_1(rc, uri, path, sizeof(path),
- rc->old_authenticated, certs))) {
- install_object(rc, uri, path);
+ if ((manifest = check_manifest_1(rc, uri, &path,
+ &rc->old_authenticated, certs))) {
+ install_object(rc, uri, &path);
mib_increment(rc, uri, backup_manifest_accepted);
return manifest;
- } else if (!access(path, F_OK)) {
+ } else if (!access(path.s, F_OK)) {
mib_increment(rc, uri, backup_manifest_rejected);
}
@@ -2627,21 +2679,21 @@ static int extract_roa_prefix(unsigned char *addr,
* Read and check one ROA from disk.
*/
static int check_roa_1(const rcynic_ctx_t *rc,
- const char *uri,
- char *path,
- const int pathlen,
- const char *prefix,
+ const uri_t *uri,
+ path_t *path,
+ const path_t *prefix,
STACK_OF(X509) *certs,
const unsigned char *hash,
const size_t hashlen)
{
- unsigned char hashbuf[EVP_MAX_MD_SIZE], addrbuf[ADDR_RAW_BUF_LEN];
+ unsigned char addrbuf[ADDR_RAW_BUF_LEN];
const ASN1_OBJECT *eContentType = NULL;
STACK_OF(IPAddressFamily) *roa_resources = NULL, *ee_resources = NULL;
STACK_OF(X509_CRL) *crls = NULL;
STACK_OF(X509) *signers = NULL;
CMS_ContentInfo *cms = NULL;
X509_CRL *crl = NULL;
+ hashbuf_t hashbuf;
ROA *roa = NULL;
BIO *bio = NULL;
rcynic_x509_store_ctx_t rctx;
@@ -2653,18 +2705,25 @@ static int check_roa_1(const rcynic_ctx_t *rc,
assert(rc && uri && path && prefix && certs && sk_X509_num(certs));
- if (!uri_to_filename(rc, uri, path, pathlen, prefix))
+ if (!uri_to_filename(rc, uri, path, prefix))
goto error;
+ if (hashlen > sizeof(hashbuf.h)) {
+ reject(rc, uri, hash_too_long,
+ "because supplied hash is too long (%lu, our max is %lu)",
+ (unsigned long) hashlen, (unsigned long) sizeof(hashbuf.h));
+ goto error;
+ }
+
if (hash)
- cms = read_cms(path, hashbuf, sizeof(hashbuf));
+ cms = read_cms(path, &hashbuf);
else
- cms = read_cms(path, NULL, 0);
+ cms = read_cms(path, NULL);
if (!cms)
goto error;
- if (hash && memcmp(hashbuf, hash, hashlen)) {
+ if (hash && memcmp(hashbuf.h, hash, hashlen)) {
reject(rc, uri, roa_digest_mismatch,
"because ROA does not match manifest digest");
goto error;
@@ -2679,7 +2738,7 @@ static int check_roa_1(const rcynic_ctx_t *rc,
}
if ((bio = BIO_new(BIO_s_mem())) == NULL) {
- logmsg(rc, log_sys_err, "Couldn't allocate BIO for ROA %s", uri);
+ logmsg(rc, log_sys_err, "Couldn't allocate BIO for ROA %s", uri->s);
goto error;
}
@@ -2802,8 +2861,8 @@ static int check_roa_1(const rcynic_ctx_t *rc,
goto error;
}
- if (!(crl = check_crl(rc, certinfo.crldp, sk_X509_value(certs, sk_X509_num(certs) - 1), NULL, 0))) {
- reject(rc, uri, roa_bad_crl, "because ROA EE certificate has bad CRL %s", certinfo.crldp);
+ if (!(crl = check_crl(rc, &certinfo.crldp, sk_X509_value(certs, sk_X509_num(certs) - 1), NULL, 0))) {
+ reject(rc, uri, roa_bad_crl, "because ROA EE certificate has bad CRL %s", certinfo.crldp.s);
goto error;
}
@@ -2833,7 +2892,7 @@ static int check_roa_1(const rcynic_ctx_t *rc,
/*
* Redundant error message?
*/
- logmsg(rc, log_data_err, "Validation failure for ROA %s EE certificate",uri);
+ logmsg(rc, log_data_err, "Validation failure for ROA %s EE certificate", uri->s);
mib_increment(rc, uri, roa_invalid_ee);
goto error;
}
@@ -2859,36 +2918,36 @@ static int check_roa_1(const rcynic_ctx_t *rc,
* and check issuer's signature if we don't.
*/
static void check_roa(const rcynic_ctx_t *rc,
- const char *uri,
+ const uri_t *uri,
STACK_OF(X509) *certs,
const unsigned char *hash,
const size_t hashlen)
{
- char path[FILENAME_MAX];
+ path_t path;
- if (uri_to_filename(rc, uri, path, sizeof(path), rc->authenticated) &&
- !access(path, F_OK))
+ if (uri_to_filename(rc, uri, &path, &rc->authenticated) &&
+ !access(path.s, F_OK))
return;
- logmsg(rc, log_telemetry, "Checking ROA %s", uri);
+ logmsg(rc, log_telemetry, "Checking ROA %s", uri->s);
assert(rsync_cached_uri(rc, uri));
- if (check_roa_1(rc, uri, path, sizeof(path), rc->unauthenticated,
+ if (check_roa_1(rc, uri, &path, &rc->unauthenticated,
certs, hash, hashlen)) {
- install_object(rc, uri, path);
+ install_object(rc, uri, &path);
mib_increment(rc, uri, current_roa_accepted);
return;
- } else if (!access(path, F_OK)) {
+ } else if (!access(path.s, F_OK)) {
mib_increment(rc, uri, current_roa_rejected);
}
- if (check_roa_1(rc, uri, path, sizeof(path), rc->old_authenticated,
+ if (check_roa_1(rc, uri, &path, &rc->old_authenticated,
certs, hash, hashlen)) {
- install_object(rc, uri, path);
+ install_object(rc, uri, &path);
mib_increment(rc, uri, backup_roa_accepted);
return;
- } else if (!access(path, F_OK)) {
+ } else if (!access(path.s, F_OK)) {
mib_increment(rc, uri, backup_roa_rejected);
}
}
@@ -2899,20 +2958,19 @@ static void check_roa(const rcynic_ctx_t *rc,
* Read and check one Ghostbuster record from disk.
*/
static int check_ghostbuster_1(const rcynic_ctx_t *rc,
- const char *uri,
- char *path,
- const int pathlen,
- const char *prefix,
+ const uri_t *uri,
+ path_t *path,
+ const path_t *prefix,
STACK_OF(X509) *certs,
const unsigned char *hash,
const size_t hashlen)
{
- unsigned char hashbuf[EVP_MAX_MD_SIZE];
const ASN1_OBJECT *eContentType = NULL;
STACK_OF(X509_CRL) *crls = NULL;
STACK_OF(X509) *signers = NULL;
CMS_ContentInfo *cms = NULL;
X509_CRL *crl = NULL;
+ hashbuf_t hashbuf;
BIO *bio = NULL;
rcynic_x509_store_ctx_t rctx;
certinfo_t certinfo;
@@ -2920,18 +2978,25 @@ static int check_ghostbuster_1(const rcynic_ctx_t *rc,
assert(rc && uri && path && prefix && certs && sk_X509_num(certs));
- if (!uri_to_filename(rc, uri, path, pathlen, prefix))
+ if (!uri_to_filename(rc, uri, path, prefix))
goto error;
+ if (hashlen > sizeof(hashbuf.h)) {
+ reject(rc, uri, hash_too_long,
+ "because supplied hash is too long (%lu, our max is %lu)",
+ (unsigned long) hashlen, (unsigned long) sizeof(hashbuf.h));
+ goto error;
+ }
+
if (hash)
- cms = read_cms(path, hashbuf, sizeof(hashbuf));
+ cms = read_cms(path, &hashbuf);
else
- cms = read_cms(path, NULL, 0);
+ cms = read_cms(path, NULL);
if (!cms)
goto error;
- if (hash && memcmp(hashbuf, hash, hashlen)) {
+ if (hash && memcmp(hashbuf.h, hash, hashlen)) {
reject(rc, uri, ghostbuster_digest_mismatch,
"because Ghostbuster record does not match manifest digest");
goto error;
@@ -2951,7 +3016,7 @@ static int check_ghostbuster_1(const rcynic_ctx_t *rc,
* just leave this NULL and the right thing should happen.
*/
if ((bio = BIO_new(BIO_s_mem())) == NULL) {
- logmsg(rc, log_sys_err, "Couldn't allocate BIO for Ghostbuster record %s", uri);
+ logmsg(rc, log_sys_err, "Couldn't allocate BIO for Ghostbuster record %s", uri->s);
goto error;
}
#endif
@@ -2976,8 +3041,8 @@ static int check_ghostbuster_1(const rcynic_ctx_t *rc,
*/
#endif
- if (!(crl = check_crl(rc, certinfo.crldp, sk_X509_value(certs, sk_X509_num(certs) - 1), NULL, 0))) {
- reject(rc, uri, ghostbuster_bad_crl, "because Ghostbuster record EE certificate has bad CRL %s", certinfo.crldp);
+ if (!(crl = check_crl(rc, &certinfo.crldp, sk_X509_value(certs, sk_X509_num(certs) - 1), NULL, 0))) {
+ reject(rc, uri, ghostbuster_bad_crl, "because Ghostbuster record EE certificate has bad CRL %s", certinfo.crldp.s);
goto error;
}
@@ -3007,7 +3072,7 @@ static int check_ghostbuster_1(const rcynic_ctx_t *rc,
/*
* Redundant error message?
*/
- logmsg(rc, log_data_err, "Validation failure for Ghostbuster record %s EE certificate", uri);
+ logmsg(rc, log_data_err, "Validation failure for Ghostbuster record %s EE certificate", uri->s);
mib_increment(rc, uri, ghostbuster_invalid_ee);
goto error;
}
@@ -3030,36 +3095,36 @@ static int check_ghostbuster_1(const rcynic_ctx_t *rc,
* attempt to fetch it and check issuer's signature if we don't.
*/
static void check_ghostbuster(const rcynic_ctx_t *rc,
- const char *uri,
+ const uri_t *uri,
STACK_OF(X509) *certs,
const unsigned char *hash,
const size_t hashlen)
{
- char path[FILENAME_MAX];
+ path_t path;
- if (uri_to_filename(rc, uri, path, sizeof(path), rc->authenticated) &&
- !access(path, F_OK))
+ if (uri_to_filename(rc, uri, &path, &rc->authenticated) &&
+ !access(path.s, F_OK))
return;
- logmsg(rc, log_telemetry, "Checking Ghostbuster record %s", uri);
+ logmsg(rc, log_telemetry, "Checking Ghostbuster record %s", uri->s);
assert(rsync_cached_uri(rc, uri));
- if (check_ghostbuster_1(rc, uri, path, sizeof(path), rc->unauthenticated,
+ if (check_ghostbuster_1(rc, uri, &path, &rc->unauthenticated,
certs, hash, hashlen)) {
- install_object(rc, uri, path);
+ install_object(rc, uri, &path);
mib_increment(rc, uri, current_ghostbuster_accepted);
return;
- } else if (!access(path, F_OK)) {
+ } else if (!access(path.s, F_OK)) {
mib_increment(rc, uri, current_ghostbuster_rejected);
}
- if (check_ghostbuster_1(rc, uri, path, sizeof(path), rc->old_authenticated,
+ if (check_ghostbuster_1(rc, uri, &path, &rc->old_authenticated,
certs, hash, hashlen)) {
- install_object(rc, uri, path);
+ install_object(rc, uri, &path);
mib_increment(rc, uri, backup_ghostbuster_accepted);
return;
- } else if (!access(path, F_OK)) {
+ } else if (!access(path.s, F_OK)) {
mib_increment(rc, uri, backup_ghostbuster_rejected);
}
}
@@ -3084,7 +3149,7 @@ static void walk_cert(rcynic_ctx_t *rc, STACK_OF(walk_ctx_t) *wsk);
*/
static void walk_cert_1(rcynic_ctx_t *rc,
STACK_OF(walk_ctx_t) *wsk,
- char *uri,
+ uri_t *uri,
const unsigned char *hash,
const size_t hashlen,
STACK_OF(X509) *certs)
@@ -3128,7 +3193,7 @@ static void walk_cert_1(rcynic_ctx_t *rc,
*/
static void walk_cert_2(rcynic_ctx_t *rc,
STACK_OF(walk_ctx_t) *wsk,
- char *uri,
+ uri_t *uri,
const unsigned char *hash,
const size_t hashlen)
{
@@ -3139,14 +3204,14 @@ static void walk_cert_2(rcynic_ctx_t *rc,
certs = walk_ctx_stack_certs(wsk);
assert(certs);
- if (endswith(uri, ".cer"))
+ if (endswith(uri->s, ".cer"))
walk_cert_1(rc, wsk, uri, hash, hashlen, certs);
- else if (endswith(uri, ".roa"))
+ else if (endswith(uri->s, ".roa"))
check_roa(rc, uri, certs, hash, hashlen);
- else if (endswith(uri, ".gbr"))
+ else if (endswith(uri->s, ".gbr"))
check_ghostbuster(rc, uri, certs, hash, hashlen);
- else if (!endswith(uri, ".crl"))
- logmsg(rc, log_telemetry, "Don't know how to check object %s, ignoring", uri);
+ else if (!endswith(uri->s, ".crl"))
+ logmsg(rc, log_telemetry, "Don't know how to check object %s, ignoring", uri->s);
sk_X509_free(certs);
}
@@ -3164,7 +3229,7 @@ static void walk_cert_2(rcynic_ctx_t *rc,
*/
static void walk_cert_3(rcynic_ctx_t *rc, STACK_OF(walk_ctx_t) *wsk)
{
- char uri[URI_MAX];
+ uri_t uri;
FileAndHash *fah;
const certinfo_t *issuer;
walk_ctx_t *w;
@@ -3179,7 +3244,7 @@ static void walk_cert_3(rcynic_ctx_t *rc, STACK_OF(walk_ctx_t) *wsk)
* Pull all non-directory filenames from the publication point directory.
*/
assert(w->filenames == NULL);
- w->filenames = directory_filenames(rc, w->pass, issuer->sia);
+ w->filenames = directory_filenames(rc, w->pass, &issuer->sia);
/*
* Loop over manifest, checking everything it lists. Remove any
@@ -3189,12 +3254,12 @@ static void walk_cert_3(rcynic_ctx_t *rc, STACK_OF(walk_ctx_t) *wsk)
if (w->manifest != NULL) {
for (i = 0; (fah = sk_FileAndHash_value(w->manifest->fileList, i)) != NULL; i++) {
sk_OPENSSL_STRING_remove(w->filenames, (char *) fah->file->data);
- if (strlen(issuer->sia) + strlen((char *) fah->file->data) >= sizeof(uri)) {
- logmsg(rc, log_data_err, "URI %s%s too long, skipping", issuer->sia, fah->file->data);
+ if (strlen(issuer->sia.s) + strlen((char *) fah->file->data) >= sizeof(uri.s)) {
+ logmsg(rc, log_data_err, "URI %s%s too long, skipping", issuer->sia.s, fah->file->data);
} else {
- strcpy(uri, issuer->sia);
- strcat(uri, (char *) fah->file->data);
- walk_cert_2(rc, wsk, uri, fah->hash->data, fah->hash->length);
+ strcpy(uri.s, issuer->sia.s);
+ strcat(uri.s, (char *) fah->file->data);
+ walk_cert_2(rc, wsk, &uri, fah->hash->data, fah->hash->length);
}
}
}
@@ -3205,18 +3270,18 @@ static void walk_cert_3(rcynic_ctx_t *rc, STACK_OF(walk_ctx_t) *wsk)
*/
for (i = 0; i < sk_OPENSSL_STRING_num(w->filenames); i++) {
char *s = sk_OPENSSL_STRING_value(w->filenames, i);
- if (strlen(issuer->sia) + strlen(s) >= sizeof(uri)) {
- logmsg(rc, log_data_err, "URI %s%s too long, skipping", issuer->sia, s);
+ if (strlen(issuer->sia.s) + strlen(s) >= sizeof(uri.s)) {
+ logmsg(rc, log_data_err, "URI %s%s too long, skipping", issuer->sia.s, s);
continue;
}
- strcpy(uri, issuer->sia);
- strcat(uri, s);
- if (!strcmp(uri, issuer->manifest))
+ strcpy(uri.s, issuer->sia.s);
+ strcat(uri.s, s);
+ if (!strcmp(uri.s, issuer->manifest.s))
continue;
- logmsg(rc, log_telemetry, "Object %s present in publication directory but not in manifest", uri);
- mib_increment(rc, uri, object_not_in_manifest);
+ logmsg(rc, log_telemetry, "Object %s present in publication directory but not in manifest", uri.s);
+ mib_increment(rc, &uri, object_not_in_manifest);
if (rc->allow_object_not_in_manifest)
- walk_cert_2(rc, wsk, uri, NULL, 0);
+ walk_cert_2(rc, wsk, &uri, NULL, 0);
}
sk_OPENSSL_STRING_pop_free(w->filenames, OPENSSL_STRING_free);
@@ -3256,8 +3321,8 @@ static void walk_cert_cb(rcynic_ctx_t *rc, STACK_OF(walk_ctx_t) *wsk)
assert(w->manifest == NULL);
- if ((w->manifest = check_manifest(rc, w->certinfo.manifest, certs)) == NULL)
- logmsg(rc, log_data_err, "Couldn't get manifest %s, blundering onward", w->certinfo.manifest);
+ if ((w->manifest = check_manifest(rc, &w->certinfo.manifest, certs)) == NULL)
+ logmsg(rc, log_data_err, "Couldn't get manifest %s, blundering onward", w->certinfo.manifest.s);
sk_X509_free(certs);
certs = NULL;
@@ -3305,10 +3370,10 @@ static void walk_cert(rcynic_ctx_t *rc, STACK_OF(walk_ctx_t) *wsk)
w = walk_ctx_stack_head(wsk);
issuer = &w->certinfo;
- if (!issuer->sia[0] || !issuer->ca)
+ if (!issuer->sia.s[0] || !issuer->ca)
return;
- if (!issuer->manifest[0]) {
+ if (!issuer->manifest.s[0]) {
logmsg(rc, log_data_err, "Issuer's certificate does not specify a manifest, skipping collection");
return;
}
@@ -3326,7 +3391,7 @@ static void walk_cert(rcynic_ctx_t *rc, STACK_OF(walk_ctx_t) *wsk)
* rsync() doesn't take callbacks yet, but pretend it does, so we
* can start sorting out which bits of code go where.
*/
- rsync_tree(rc, issuer->sia);
+ rsync_tree(rc, &issuer->sia);
walk_cert_cb(rc, wsk);
assert(sk_walk_ctx_t_num(wsk) == n_wsk);
@@ -3365,9 +3430,6 @@ int main(int argc, char *argv[])
else
rc.jane++;
- set_directory(&rc.authenticated, "rcynic-data/authenticated/");
- set_directory(&rc.old_authenticated, "rcynic-data/authenticated.old/");
- set_directory(&rc.unauthenticated, "rcynic-data/unauthenticated/");
rc.log_level = log_telemetry;
rc.allow_stale_crl = 1;
rc.allow_stale_manifest = 1;
@@ -3376,6 +3438,11 @@ int main(int argc, char *argv[])
LOG_LEVELS;
#undef QQ
+ if (!set_directory(&rc, &rc.authenticated, "rcynic-data/authenticated/") ||
+ !set_directory(&rc, &rc.old_authenticated, "rcynic-data/authenticated.old/") ||
+ !set_directory(&rc, &rc.unauthenticated, "rcynic-data/unauthenticated/"))
+ goto done;
+
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
@@ -3440,14 +3507,17 @@ int main(int argc, char *argv[])
assert(val && val->name && val->value);
- if (!name_cmp(val->name, "authenticated"))
- set_directory(&rc.authenticated, val->value);
+ if (!name_cmp(val->name, "authenticated") &&
+ !set_directory(&rc, &rc.authenticated, val->value))
+ goto done;
- else if (!name_cmp(val->name, "old-authenticated"))
- set_directory(&rc.old_authenticated, val->value);
+ else if (!name_cmp(val->name, "old-authenticated") &&
+ !set_directory(&rc, &rc.old_authenticated, val->value))
+ goto done;
- else if (!name_cmp(val->name, "unauthenticated"))
- set_directory(&rc.unauthenticated, val->value);
+ else if (!name_cmp(val->name, "unauthenticated") &&
+ !set_directory(&rc, &rc.unauthenticated, val->value))
+ goto done;
else if (!name_cmp(val->name, "rsync-timeout") &&
!configure_integer(&rc, &rc.rsync_timeout, val->value))
@@ -3594,28 +3664,29 @@ int main(int argc, char *argv[])
start = time(0);
logmsg(&rc, log_telemetry, "Starting");
- if (!rm_rf(rc.old_authenticated)) {
+ if (!rm_rf(&rc.old_authenticated)) {
logmsg(&rc, log_sys_err, "Couldn't remove %s: %s",
- rc.old_authenticated, strerror(errno));
+ rc.old_authenticated.s, strerror(errno));
goto done;
}
- if (rename(rc.authenticated, rc.old_authenticated) < 0 &&
+ if (rename(rc.authenticated.s, rc.old_authenticated.s) < 0 &&
errno != ENOENT) {
logmsg(&rc, log_sys_err, "Couldn't rename %s to %s: %s",
- rc.old_authenticated, rc.authenticated, strerror(errno));
+ rc.old_authenticated.s, rc.authenticated.s, strerror(errno));
goto done;
}
- if (!access(rc.authenticated, F_OK) || !mkdir_maybe(&rc, rc.authenticated)) {
+ if (!access(rc.authenticated.s, F_OK) || !mkdir_maybe(&rc, &rc.authenticated)) {
logmsg(&rc, log_sys_err, "Couldn't prepare directory %s: %s",
- rc.authenticated, strerror(errno));
+ rc.authenticated.s, strerror(errno));
goto done;
}
for (i = 0; i < sk_CONF_VALUE_num(cfg_section); i++) {
CONF_VALUE *val = sk_CONF_VALUE_value(cfg_section, i);
- char path1[FILENAME_MAX], path2[FILENAME_MAX], uri[URI_MAX];
+ path_t path1, path2;
+ uri_t uri;
X509 *x = NULL;
assert(val && val->name && val->value);
@@ -3625,31 +3696,31 @@ int main(int argc, char *argv[])
* Old local file trust anchor method.
*/
logmsg(&rc, log_telemetry, "Processing trust anchor from local file %s", val->value);
- if (strlen(val->value) >= sizeof(path1)) {
+ if (strlen(val->value) >= sizeof(path1.s)) {
logmsg(&rc, log_usage_err, "Trust anchor path name too long %s", val->value);
goto done;
}
- strcpy(path1, val->value);
- if ((x = read_cert(path1, NULL, 0)) == NULL) {
- logmsg(&rc, log_usage_err, "Couldn't read trust anchor %s", path1);
+ strcpy(path1.s, val->value);
+ if ((x = read_cert(&path1, NULL)) == NULL) {
+ logmsg(&rc, log_usage_err, "Couldn't read trust anchor %s", path1.s);
goto done;
}
hash = X509_subject_name_hash(x);
for (j = 0; j < INT_MAX; j++) {
- if (snprintf(path2, sizeof(path2), "%s%lx.%d.cer",
- rc.authenticated, hash, j) == sizeof(path2)) {
+ if (snprintf(path2.s, sizeof(path2.s), "%s%lx.%d.cer",
+ rc.authenticated.s, hash, j) == sizeof(path2.s)) {
logmsg(&rc, log_sys_err,
- "Couldn't construct path name for trust anchor %s", path1);
+ "Couldn't construct path name for trust anchor %s", path1.s);
goto done;
}
- if (access(path2, F_OK))
+ if (access(path2.s, F_OK))
break;
}
if (j == INT_MAX) {
- logmsg(&rc, log_sys_err, "Couldn't find a free name for trust anchor %s", path1);
+ logmsg(&rc, log_sys_err, "Couldn't find a free name for trust anchor %s", path1.s);
goto done;
}
- uri[0] = '\0';
+ uri.s[0] = '\0';
}
if (!name_cmp(val->name, "trust-anchor-uri-with-key") ||
@@ -3670,32 +3741,32 @@ int main(int argc, char *argv[])
if (unified) {
fn = val->value;
bio = BIO_new_file(fn, "r");
- if (!bio || BIO_gets(bio, uri, sizeof(uri)) <= 0) {
+ if (!bio || BIO_gets(bio, uri.s, sizeof(uri.s)) <= 0) {
logmsg(&rc, log_usage_err, "Couldn't read trust anchor URI from %s", fn);
goto done;
}
- uri[strcspn(uri, " \t\r\n")] = '\0';
+ uri.s[strcspn(uri.s, " \t\r\n")] = '\0';
bio = BIO_push(BIO_new(BIO_f_base64()), bio);
} else {
j = strcspn(val->value, " \t");
- if (j >= sizeof(uri)) {
+ if (j >= sizeof(uri.s)) {
logmsg(&rc, log_usage_err, "Trust anchor URI too long %s", val->value);
goto done;
}
- memcpy(uri, val->value, j);
- uri[j] = '\0';
+ memcpy(uri.s, val->value, j);
+ uri.s[j] = '\0';
j += strspn(val->value + j, " \t");
fn = val->value + j;
bio = BIO_new_file(fn, "rb");
}
- if (!uri_to_filename(&rc, uri, path1, sizeof(path1), rc.unauthenticated) ||
- !uri_to_filename(&rc, uri, path2, sizeof(path2), rc.authenticated)) {
- logmsg(&rc, log_usage_err, "Couldn't convert trust anchor URI %s to filename", uri);
+ if (!uri_to_filename(&rc, &uri, &path1, &rc.unauthenticated) ||
+ !uri_to_filename(&rc, &uri, &path2, &rc.authenticated)) {
+ logmsg(&rc, log_usage_err, "Couldn't convert trust anchor URI %s to filename", uri.s);
goto done;
}
- logmsg(&rc, log_telemetry, "Processing trust anchor from URI %s", uri);
- if (!rsync_file(&rc, uri)) {
- logmsg(&rc, log_data_err, "Could not fetch trust anchor from %s", uri);
+ logmsg(&rc, log_telemetry, "Processing trust anchor from URI %s", uri.s);
+ if (!rsync_file(&rc, &uri)) {
+ logmsg(&rc, log_data_err, "Could not fetch trust anchor from %s", uri.s);
continue;
}
if (bio)
@@ -3703,18 +3774,18 @@ int main(int argc, char *argv[])
BIO_free_all(bio);
bio = NULL;
if (!pkey) {
- logmsg(&rc, log_usage_err, "Couldn't read trust anchor public key for %s from %s", uri, fn);
+ logmsg(&rc, log_usage_err, "Couldn't read trust anchor public key for %s from %s", uri.s, fn);
goto done;
}
- if ((x = read_cert(path1, NULL, 0)) == NULL)
- logmsg(&rc, log_data_err, "Couldn't read trust anchor %s", path1);
+ if ((x = read_cert(&path1, NULL)) == NULL)
+ logmsg(&rc, log_data_err, "Couldn't read trust anchor %s", path1.s);
if (x && (xpkey = X509_get_pubkey(x)) == NULL)
- logmsg(&rc, log_data_err, "Rejected %s because couldn't read public key from trust anchor locator", uri);
+ logmsg(&rc, log_data_err, "Rejected %s because couldn't read public key from trust anchor locator", uri.s);
j = (xpkey && EVP_PKEY_cmp(pkey, xpkey) == 1);
EVP_PKEY_free(pkey);
EVP_PKEY_free(xpkey);
if (!j) {
- logmsg(&rc, log_data_err, "Rejected %s because known public key didn't match trust anchor locator", uri);
+ logmsg(&rc, log_data_err, "Rejected %s because known public key didn't match trust anchor locator", uri.s);
X509_free(x);
continue;
}
@@ -3723,12 +3794,12 @@ int main(int argc, char *argv[])
if (!x)
continue;
- logmsg(&rc, log_telemetry, "Copying trust anchor %s to %s", path1, path2);
+ logmsg(&rc, log_telemetry, "Copying trust anchor %s to %s", path1.s, path2.s);
- if (!mkdir_maybe(&rc, path2) ||
- !(rc.use_links ? ln(path1, path2) : cp(path1, path2))) {
+ if (!mkdir_maybe(&rc, &path2) ||
+ !(rc.use_links ? ln(&path1, &path2) : cp(&path1, &path2))) {
logmsg(&rc, log_sys_err, "Couldn't %s trust anchor %s",
- (rc.use_links ? "link" : "copy"), path1);
+ (rc.use_links ? "link" : "copy"), path1.s);
goto done;
}
@@ -3742,7 +3813,7 @@ int main(int argc, char *argv[])
goto done;
}
- parse_cert(&rc, x, &w->certinfo, uri);
+ parse_cert(&rc, x, &w->certinfo, &uri);
w->certinfo.ta = 1;
w->cert = x;
@@ -3757,8 +3828,8 @@ int main(int argc, char *argv[])
}
- if (prune && !prune_unauthenticated(&rc, rc.unauthenticated,
- strlen(rc.unauthenticated))) {
+ if (prune && !prune_unauthenticated(&rc, &rc.unauthenticated,
+ strlen(rc.unauthenticated.s))) {
logmsg(&rc, log_sys_err, "Trouble pruning old unauthenticated data");
goto done;
}
@@ -3771,15 +3842,15 @@ int main(int argc, char *argv[])
if (xmlfile != NULL) {
char tad[sizeof("2006-10-13T11:22:33Z") + 1];
- char hostname[HOST_NAME_MAX];
time_t tad_time = time(0);
struct tm *tad_tm = gmtime(&tad_time);
int ok = 1, use_stdout = !strcmp(xmlfile, "-");
+ hostname_t hostname;
FILE *f = NULL;
strftime(tad, sizeof(tad), "%Y-%m-%dT%H:%M:%SZ", tad_tm);
- ok &= gethostname(hostname, sizeof(hostname)) == 0;
+ ok &= gethostname(hostname.s, sizeof(hostname.s)) == 0;
if (use_stdout)
f = stdout;
@@ -3796,7 +3867,7 @@ int main(int argc, char *argv[])
" summary-version=\"%d\" reporting-hostname=\"%s\">\n"
" <labels>\n"
" <hostname>Publication Repository</hostname>\n",
- tad, svn_id, XML_SUMMARY_VERSION, hostname) != EOF;
+ tad, svn_id, XML_SUMMARY_VERSION, hostname.s) != EOF;
for (j = 0; ok && j < MIB_COUNTER_T_MAX; ++j)
ok &= fprintf(f, " <%s kind=\"%s\">%s</%s>\n",
@@ -3815,7 +3886,7 @@ int main(int argc, char *argv[])
if (ok)
ok &= fprintf(f, " <host>\n <hostname>%s</hostname>\n",
- h->hostname) != EOF;
+ h->hostname.s) != EOF;
for (j = 0; ok && j < MIB_COUNTER_T_MAX; ++j)
ok &= fprintf(f, " <%s>%lu</%s>\n", mib_counter_label[j],
@@ -3834,7 +3905,7 @@ int main(int argc, char *argv[])
strftime(tad, sizeof(tad), "%Y-%m-%dT%H:%M:%SZ", tad_tm);
ok &= fprintf(f, " <validation_status timestamp=\"%s\" status=\"%s\">%s</validation_status>\n",
- tad, mib_counter_label[v->code], v->uri) != EOF;
+ tad, mib_counter_label[v->code], v->uri.s) != EOF;
}
if (ok)
@@ -3863,9 +3934,6 @@ int main(int argc, char *argv[])
BIO_free(bio);
EVP_cleanup();
ERR_free_strings();
- free(rc.authenticated);
- free(rc.old_authenticated);
- free(rc.unauthenticated);
if (rc.rsync_program)
free(rc.rsync_program);
if (lockfile && lockfd >= 0)