}
map.url = rpp->url;
- map.path = rpp->path;
- map.tmppath = rpp->tmppath;
+ map.path = (download != NULL) ? rpp->tmppath : rpp->path;
error = validate(&map, arg);
if (error) {
pr_val_debug("RPP validation failed.");
}
void
-deferstack_push(struct cert_stack *stack, struct deferred_cert *deferred)
+deferstack_push(struct cert_stack *stack, struct cache_mapping *map,
+ struct rpp *pp)
{
struct defer_node *node;
node = pmalloc(sizeof(struct defer_node));
node->type = DNT_CERT;
- node->deferred = *deferred;
- rpp_refget(deferred->pp);
+ node->deferred.map = *map;
+ node->deferred.pp = pp;
+ rpp_refget(pp);
SLIST_INSERT_HEAD(&stack->defers, node, next);
}
int certstack_create(struct cert_stack **);
void certstack_destroy(struct cert_stack *);
-void deferstack_push(struct cert_stack *, struct deferred_cert *cert);
+void deferstack_push(struct cert_stack *, struct cache_mapping *, struct rpp *);
int deferstack_pop(struct cert_stack *, struct deferred_cert *cert);
bool deferstack_is_empty(struct cert_stack *);
if (refs->crldp == NULL)
pr_crit("Certificate's CRL Distribution Point was not recorded.");
- crl_url = rpp_get_crl(pp);
+ crl_url = rpp_get_crl_url(pp);
if (crl_url == NULL)
pr_crit("Manifest's CRL was not recorded.");
return rpki_config.local_repository;
}
+time_t
+cfg_cache_threshold(void)
+{
+ return 86400; // XXX
+}
+
unsigned int
config_get_max_cert_depth(void)
{
pr_val_debug("Validating file hash: %s", path);
+ if (expected_len != hash_get_size(algorithm))
+ return pr_val_err("%s string has bogus size: %zu",
+ hash_get_name(algorithm), expected_len);
+
error = hash_file(algorithm, path, actual, &actual_len);
if (error)
return error;
enum incidence_id {
INID_HASHALG_HAS_PARAMS,
INID_OBJ_NOT_DER,
- INID_MFT_FILE_NOT_FOUND,
- INID_MFT_FILE_HASH_NOT_MATCH,
+ INID_MFT_FILE_NOT_FOUND, // XXX deprecate and no-op
+ INID_MFT_FILE_HASH_NOT_MATCH, // XXX deprecate and no-op
INID_MFT_STALE,
INID_CRL_STALE,
#include "rrdp.h"
#include "thread_var.h"
#include "types/name.h"
+#include "types/path.h"
#include "types/str.h"
/*
return 0;
}
+static int
+check_rpp(struct cache_mapping *map_rpp, void *rpkiManifest)
+{
+ struct cache_mapping mft;
+ struct rpp *pp;
+ int error;
+
+ mft.url = rpkiManifest;
+ mft.path = join_paths(map_rpp->path, strrchr(mft.url, '/')); // XXX
+
+ error = handle_manifest(&mft, &pp);
+ if (error)
+ goto end;
+
+ rpp_traverse(pp);
+ rpp_refput(pp);
+
+end: free(mft.path);
+ return error;
+}
+
/** Boilerplate code for CA certificate validation and recursive traversal. */
int
certificate_traverse(struct rpp *rpp_parent, struct cache_mapping *cert_map)
struct sia_uris sia_uris;
enum rpki_policy policy;
enum cert_type certype;
- struct rpp *pp;
int error;
state = state_retrieve();
map_val_get_printable(cert_map));
fnstack_push_map(cert_map);
- error = rpp_crl(rpp_parent, &rpp_parent_crl);
- if (error)
+ rpp_parent_crl = rpp_crl(rpp_parent);
+ if (rpp_parent_crl == NULL) {
+ error = -EINVAL;
goto revert_fnstack_and_debug;
+ }
/* -- Validate the certificate (@cert) -- */
error = certificate_load(cert_map, &x509);
if (error)
goto revert_uris;
- error = cache_download_alt(&sia_uris, NULL, NULL);
- if (error)
- goto revert_uris;
-
error = x509stack_push(validation_certstack(state), cert_map, x509,
policy, certype);
if (error)
goto revert_uris;
x509 = NULL; /* Ownership stolen */
- error = handle_manifest(sia_uris.rpkiManifest, &pp);
- if (error) {
+ error = cache_download_alt(&sia_uris, check_rpp, sia_uris.rpkiManifest);
+ if (error)
x509stack_cancel(validation_certstack(state));
- goto revert_uris;
- }
-
- /* -- Validate & traverse the RPP (@pp) described by the manifest -- */
- rpp_traverse(pp);
- rpp_refput(pp);
revert_uris:
sias_cleanup(&sia_uris);
#include "types/name.h"
static int
-__crl_load(struct cache_mapping *map, X509_CRL **result)
+__crl_load(char const *path, X509_CRL **result)
{
X509_CRL *crl;
BIO *bio;
bio = BIO_new(BIO_s_file());
if (bio == NULL)
return val_crypto_err("BIO_new(BIO_s_file()) returned NULL");
- if (BIO_read_filename(bio, map_get_path(map)) <= 0) {
- error = val_crypto_err("Error reading CRL '%s'",
- map_val_get_printable(map));
+ if (BIO_read_filename(bio, path) <= 0) {
+ error = val_crypto_err("Error reading CRL '%s'", path);
goto end;
}
crl = d2i_X509_CRL_bio(bio, NULL);
if (crl == NULL) {
- error = val_crypto_err("Error parsing CRL '%s'",
- map_val_get_printable(map));
+ error = val_crypto_err("Error parsing CRL '%s'", path);
goto end;
}
}
int
-crl_load(struct cache_mapping *map, X509_CRL **result)
+crl_load(char const *path, X509_CRL **result)
{
int error;
- pr_val_debug("CRL '%s' {", map_val_get_printable(map));
+ pr_val_debug("CRL '%s' {", path);
- error = __crl_load(map, result);
+ error = __crl_load(path, result);
if (error)
goto end;
#include <openssl/x509.h>
-#include "types/map.h"
-
-int crl_load(struct cache_mapping *, X509_CRL **);
+int crl_load(char const *, X509_CRL **);
#endif /* SRC_OBJECT_CRL_H_ */
#include "object/ghostbusters.h"
+#include <errno.h>
+
#include "asn1/oid.h"
#include "log.h"
#include "object/signed_object.h"
goto revert_log;
/* Prepare validation arguments */
- error = rpp_crl(pp, &crl);
- if (error)
+ crl = rpp_crl(pp);
+ if (crl == NULL) {
+ error = -EINVAL;
goto revert_sobj;
+ }
eecert_init(&ee, crl, true);
/* Validate everything */
#include "object/roa.h"
#include "object/signed_object.h"
#include "thread_var.h"
+#include "types/path.h"
static int
decode_manifest(struct signed_object *sobj, struct Manifest **result)
|| (chara == '_');
}
-/* RFC 6486bis, section 4.2.2 */
+/* RFC 9286, section 4.2.2 */
static int
validate_mft_file(IA5String_t *ia5)
{
return pr_val_err("File name is too short (%zu < 5).", ia5->size);
dot = ia5->size - 4;
if (ia5->buf[dot] != '.')
- return pr_val_err("File name seems to lack a three-letter extension.");
+ return pr_val_err("File name is missing three-letter extension.");
- for (i = 0; i < ia5->size; i++) {
- if (i != dot && !is_valid_mft_file_chara(ia5->buf[i])) {
+ for (i = 0; i < ia5->size; i++)
+ if (i != dot && !is_valid_mft_file_chara(ia5->buf[i]))
return pr_val_err("File name contains illegal character #%u",
ia5->buf[i]);
- }
- }
/*
- * Actual extension doesn't matter; if there's no handler,
- * we'll naturally ignore the file.
+ * Well... the RFC says the extension must match a IANA listing,
+ * but rejecting unknown extensions is a liability since they keep
+ * adding new ones, and people rarely updates.
+ * If we don't have a handler, we'll naturally ignore the file.
*/
return 0;
}
-///**
-// * Computes the hash of the file @map, and compares it to @expected (The
-// * "expected" hash).
-// *
-// * Returns:
-// * 0 if no errors happened and the hashes match, or the hash doesn't match
-// * but there's an incidence to ignore such error.
-// * < 0 if there was an error that can't be ignored.
-// * > 0 if there was an error but it can be ignored (file not found and there's
-// * an incidence to ignore this).
-// */
-//static int
-//hash_validate_mft_file(struct cache_mapping *map, BIT_STRING_t const *expected)
-//{
-// struct hash_algorithm const *algorithm;
-// size_t hash_size;
-// unsigned char actual[EVP_MAX_MD_SIZE];
-// int error;
-//
-// algorithm = hash_get_sha256();
-// hash_size = hash_get_size(algorithm);
-//
-// if (expected->size != hash_size)
-// return pr_val_err("%s string has bogus size: %zu",
-// hash_get_name(algorithm), expected->size);
-// if (expected->bits_unused != 0)
-// return pr_val_err("Hash string has unused bits.");
-//
-// /*
-// * TODO (#82) This is atrocious. Implement RFC 9286, and probably reuse
-// * hash_validate_file().
-// */
-//
-// error = hash_file(algorithm, map_get_path(map), actual, NULL);
-// if (error) {
-// if (error == EACCES || error == ENOENT) {
-// /* FIXME .................. */
-// if (incidence(INID_MFT_FILE_NOT_FOUND,
-// "File '%s' listed at manifest doesn't exist.",
-// map_val_get_printable(map)))
-// return -EINVAL;
-//
-// return error;
-// }
-// /* Any other error (crypto, file read) */
-// return ENSURE_NEGATIVE(error);
-// }
-//
-// if (memcmp(expected->buf, actual, hash_size) != 0) {
-// return incidence(INID_MFT_FILE_HASH_NOT_MATCH,
-// "File '%s' does not match its manifest hash.",
-// map_val_get_printable(map));
-// }
-//
-// return 0;
-//}
+static int
+check_file_and_hash(struct FileAndHash *fah, char const *path)
+{
+ if (fah->hash.bits_unused != 0)
+ return pr_val_err("Hash string has unused bits.");
+
+ /* Includes file exists validation, obv. */
+ return hash_validate_file(hash_get_sha256(), path,
+ fah->hash.buf, fah->hash.size);
+}
+
+#define INFER_CHILD(parent, fah) \
+ path_childn(parent, (char const *)fah->file.buf, fah->file.size)
+
+/*
+ * XXX
+ *
+ * revoked manifest: 6.6
+ * CRL not in fileList: 6.6
+ * fileList file in different folder: 6.6
+ * manifest is identified by id-ad-rpkiManifest. (A directory will have more
+ * than 1 on rollover.)
+ * id-ad-rpkiManifest not found: 6.6
+ * invalid manifest: 6.6
+ * stale manifest: 6.6
+ * fileList file not found: 6.6
+ * bad hash: 6.6
+ * 6.6: warning, fallback to previous version. Children inherit this.
+ */
static int
-build_rpp(struct Manifest *mft, char const *mft_url, struct rpp **pp)
+build_rpp(struct cache_mapping *mft_map, struct Manifest *mft,
+ struct rpp **result)
{
- char *rpp_url, *slash;
- size_t rpp_url_len;
+ struct cache_mapping pp_map;
+ struct rpp *pp;
int i;
struct FileAndHash *fah;
- char *file_url;
- size_t file_url_len;
- int written;
- char const *extension;
+ struct cache_mapping map;
int error;
- *pp = rpp_create();
-
- slash = strrchr(mft_url, '/');
- if (!slash)
- ; // XXX
- rpp_url_len = slash - mft_url;
- rpp_url = pstrndup(mft_url, rpp_url_len);
+ map_parent(mft_map, &pp_map);
+ pp = rpp_create();
for (i = 0; i < mft->fileList.list.count; i++) {
fah = mft->fileList.list.array[i];
/*
* IA5String is a subset of ASCII. However, IA5String_t doesn't
* seem to be guaranteed to be NULL-terminated.
- * `(char *) ia5->buf` is fair, but `strlen(ia5->buf)` is not.
*/
error = validate_mft_file(&fah->file);
if (error)
- ; // XXX
-
- file_url_len = rpp_url_len + fah->file.size + 2;
- file_url = pmalloc(file_url_len);
- written = snprintf(file_url, file_url_len, "%s/%.*s", rpp_url,
- (int)fah->file.size, fah->file.buf);
- if (written >= file_url_len)
- ; // XXX
-
-// /*
-// * XXX I think this should be moved somewhere else.
-// *
-// * Expect:
-// * - Negative value: an error not to be ignored, the whole
-// * manifest will be discarded.
-// * - Zero value: hash at manifest matches file's hash, or it
-// * doesn't match its hash but there's an incidence to ignore
-// * such error.
-// * - Positive value: file doesn't exist and keep validating
-// * manifest.
-// */
-// error = hash_validate_mft_file(map, &fah->hash);
-// if (error < 0) {
-// free(file_url);
-// goto fail;
-// }
-// if (error > 0) {
-// free(file_url);
-// continue;
-// }
-
- extension = ((char const *)fah->file.buf) + fah->file.size - 4;
- if (strcmp(extension, ".cer") == 0)
- rpp_add_cert(*pp, file_url);
- else if (strcmp(extension, ".roa") == 0)
- rpp_add_roa(*pp, file_url);
- else if (strcmp(extension, ".crl") == 0) {
- error = rpp_add_crl(*pp, file_url);
- if (error) {
- free(file_url);
- goto fail;
- }
- } else if (strcmp(extension, ".gbr") == 0)
- rpp_add_ghostbusters(*pp, file_url);
- else
- free(file_url); /* ignore it. */
+ goto fail;
+
+ map.url = INFER_CHILD(pp_map.url, fah);
+ map.path = INFER_CHILD(pp_map.path, fah);
+
+ error = check_file_and_hash(fah, map.path);
+ if (error)
+ goto fail;
+
+ error = rpp_add_file(pp, &map);
+ if (error)
+ goto fail;
}
/* rfc6486#section-7 */
- if (rpp_get_crl(*pp) == NULL) {
+ if (rpp_crl(pp) == NULL) {
error = pr_val_err("Manifest lacks a CRL.");
goto fail;
}
+ map_cleanup(&pp_map);
+ *result = pp;
return 0;
-fail:
- rpp_refput(*pp);
+fail: map_cleanup(&pp_map);
+ rpp_refput(pp);
return error;
}
-/**
- * Validates the manifest pointed by @uri, returns the RPP described by it in
- * @pp.
- */
+/* Validates the manifest @map, returns the RPP described by it in @pp. */
int
handle_manifest(struct cache_mapping *map, struct rpp **pp)
{
if (error)
goto revert_sobj;
- /* Initialize out parameter (@pp) */
- error = build_rpp(mft, map->url, pp);
+ /* Initialize @pp */
+ error = build_rpp(map, mft, pp);
if (error)
goto revert_manifest;
/* Prepare validation arguments */
- error = rpp_crl(*pp, &crl);
- if (error)
+ crl = rpp_crl(*pp);
+ if (crl == NULL) {
+ error = -EINVAL;
goto revert_rpp;
+ }
eecert_init(&ee, crl, false);
/* Validate everything */
goto revert_sobj;
/* Prepare validation arguments */
- error = rpp_crl(pp, &crl);
- if (error)
+ crl = rpp_crl(pp);
+ if (crl == NULL) {
+ error = -EINVAL;
goto revert_roa;
+ }
eecert_init(&ee, crl, false);
/* Validate and handle everything */
static BIO *
rsync2bio_cache(char const *src)
{
- char *dst;
- BIO *bio;
-
- dst = url2path(src);
- if (!dst) {
- pr_op_err("Unparseable rsync URI.");
- return NULL;
- }
-
- bio = __rsync2bio(src, dst);
+ pr_op_err("Disabled for now."); // XXX
+ return NULL;
- free(dst);
- return bio;
+// char *dst;
+// BIO *bio;
+//
+// dst = url2path(src);
+// if (!dst) {
+// pr_op_err("Unparseable rsync URI.");
+// return NULL;
+// }
+//
+// bio = __rsync2bio(src, dst);
+//
+// free(dst);
+// return bio;
}
static BIO *
#include "alloc.h"
#include "cert_stack.h"
+#include "common.h"
#include "log.h"
#include "object/certificate.h"
#include "object/crl.h"
#include "thread_var.h"
#include "types/str.h"
+STATIC_ARRAY_LIST(filelist, struct cache_mapping)
+
/* A Repository Publication Point (RFC 6481), as described by some manifest. */
struct rpp {
- struct strlist certs;
+ struct filelist files;
- /*
- * map NULL implies stack NULL and error 0.
- * If map is set, stack might or might not be set.
- * error is only relevant when map is set and stack is unset.
- */
struct {
- char *url;
- /*
- * CRL in libcrypto-friendly form.
- * Initialized lazily; access via rpp_crl().
- */
+ struct cache_mapping map;
STACK_OF(X509_CRL) *stack;
- /*
- * Some error code if we already tried to initialize @stack but
- * failed. Prevents us from wasting time doing it again, and
- * flooding the log with identical error messages.
- */
- int error;
} crl;
- /* The Manifest is not needed for now. */
- struct strlist roas;
- struct strlist ghostbusters;
-
/*
* Note that the reference counting functions are not prepared for
* multithreading, because this is not atomic.
struct rpp *
rpp_create(void)
{
- struct rpp *result;
-
- result = pmalloc(sizeof(struct rpp));
-
- strlist_init(&result->certs);
- result->crl.url = NULL;
- result->crl.stack = NULL;
- result->crl.error = 0;
- strlist_init(&result->roas);
- strlist_init(&result->ghostbusters);
+ struct rpp *result = pmalloc(sizeof(struct rpp));
+ filelist_init(&result->files);
+ memset(&result->crl, 0, sizeof(result->crl));
result->references = 1;
-
return result;
}
{
pp->references--;
if (pp->references == 0) {
- strlist_cleanup(&pp->certs);
- free(pp->crl.url);
+ filelist_cleanup(&pp->files, map_cleanup);
+ free(pp->crl.map.url);
+ free(pp->crl.map.path);
sk_X509_CRL_pop_free(pp->crl.stack, X509_CRL_free);
- strlist_cleanup(&pp->roas);
- strlist_cleanup(&pp->ghostbusters);
free(pp);
}
}
-/* Steals ownership of @url */
-void
-rpp_add_cert(struct rpp *pp, char *url)
-{
- strlist_add(&pp->certs, url);
-}
-
-/* Steals ownership of @url */
-void
-rpp_add_roa(struct rpp *pp, char *url)
-{
- strlist_add(&pp->roas, url);
-}
-
-/* Steals ownership of @url */
-void
-rpp_add_ghostbusters(struct rpp *pp, char *url)
-{
- strlist_add(&pp->ghostbusters, url);
-}
-
-/* Steals ownership of @url */
-int
-rpp_add_crl(struct rpp *pp, char *url)
-{
- /* rfc6481#section-2.2 */
- if (pp->crl.url)
- return pr_val_err("Repository Publication Point has more than one CRL.");
-
- pp->crl.url = url;
- return 0;
-}
-
-char const *
-rpp_get_crl(struct rpp const *pp)
-{
- return pp->crl.url;
-}
-
static int
-add_crl_to_stack(struct rpp *pp, STACK_OF(X509_CRL) *crls)
+set_crl(struct rpp *pp, struct cache_mapping *map)
{
X509_CRL *crl;
int error;
- int idx;
- fnstack_push(pp->crl.url);
+ /* rfc6481#section-2.2 */
+ if (pp->crl.stack != NULL)
+ return pr_val_err("Repository Publication Point has more than one CRL.");
- error = crl_load(pp->crl.url, &crl);
+ error = crl_load(map->path, &crl);
if (error)
- goto end;
+ return error;
- idx = sk_X509_CRL_push(crls, crl);
- if (idx <= 0) {
- error = val_crypto_err("Could not add CRL to a CRL stack");
+ pp->crl.stack = sk_X509_CRL_new_null();
+ if (pp->crl.stack == NULL)
+ enomem_panic();
+ if (sk_X509_CRL_push(pp->crl.stack, crl) <= 0) {
X509_CRL_free(crl);
- goto end;
+ sk_X509_CRL_pop_free(pp->crl.stack, X509_CRL_free);
+ pp->crl.stack = NULL;
+ return val_crypto_err("Could not add CRL to a CRL stack");
}
-end:
- fnstack_pop();
- return error;
+ pp->crl.map = *map;
+ return 0;
}
-/*
- * Returns the pp's CRL in stack form (which is how libcrypto functions want
- * it).
- * The stack belongs to @pp and should not be released. Can be NULL, in which
- * case you're currently validating the TA (since it lacks governing CRL).
- */
+/* Steals ownership of @map->* */
int
-rpp_crl(struct rpp *pp, STACK_OF(X509_CRL) **result)
+rpp_add_file(struct rpp *pp, struct cache_mapping *map)
{
- STACK_OF(X509_CRL) *stack;
+ if (str_ends_with(map->url, ".crl") == 0)
+ return set_crl(pp, map);
- /* -- Short circuits -- */
- if (pp == NULL) {
- /* No pp = currently validating TA. There's no CRL. */
- *result = NULL;
- return 0;
- }
- if (pp->crl.url == NULL) {
- /* rpp_crl() assumes the rpp has been populated already. */
- pr_crit("RPP lacks a CRL.");
- }
- if (pp->crl.stack != NULL) {
- /* Result already cached. */
- *result = pp->crl.stack;
- return 0;
- }
- if (pp->crl.error) {
- /* Pretend that we did everything below. */
- return pp->crl.error;
- }
-
- /* -- Actually initialize pp->crl.stack. -- */
- stack = sk_X509_CRL_new_null();
- if (stack == NULL)
- enomem_panic();
- pp->crl.error = add_crl_to_stack(pp, stack);
- if (pp->crl.error) {
- sk_X509_CRL_pop_free(stack, X509_CRL_free);
- return pp->crl.error;
- }
-
- pp->crl.stack = stack;
- *result = stack;
+ filelist_add(&pp->files, map);
return 0;
}
-static int
-__cert_traverse(struct rpp *pp)
+char const *
+rpp_get_crl_url(struct rpp const *pp)
{
- struct validation *state;
- struct cert_stack *certstack;
- ssize_t i;
- struct deferred_cert deferred;
-
- if (pp->certs.len == 0)
- return 0;
-
- state = state_retrieve();
- certstack = validation_certstack(state);
-
- deferred.pp = pp;
- /*
- * The for is inverted, to achieve FIFO behavior since the separator.
- * Not really important; it simply makes the traversal order more
- * intuitive.
- */
- for (i = pp->certs.len - 1; i >= 0; i--) {
- deferred.map = pp->certs.array[i];
- deferstack_push(certstack, &deferred);
- }
+ return pp->crl.map.url;
+}
- return 0;
+/*
+ * The stack belongs to @pp and should not be released. Can be NULL, in which
+ * case you're currently validating the TA (since it lacks governing CRL).
+ */
+STACK_OF(X509_CRL) *
+rpp_crl(struct rpp *pp)
+{
+ return pp->crl.stack;
}
/* Traverses through all of @pp's known files, validating them. */
void
rpp_traverse(struct rpp *pp)
{
- char **url;
+ struct cert_stack *certstack;
+ struct cache_mapping *map;
/*
* A subtree should not invalidate the rest of the tree, so error codes
*/
/*
- * Certificates cannot be validated now, because then the algorithm
- * would be recursive.
- * Store them in the defer stack (see cert_stack.h), will get back to
- * them later.
+ * Certificates cannot be validated now, because then
+ * the algorithm would be recursive.
+ * Store them in the defer stack (see cert_stack.h),
+ * will get back to them later.
*/
- __cert_traverse(pp);
- /* Validate ROAs, apply validation_handler on them. */
- ARRAYLIST_FOREACH(&pp->roas, url)
- roa_traverse(*url, pp);
+ certstack = validation_certstack(state_retrieve());
- /*
- * We don't do much with the ghostbusters right now.
- * Just validate them.
- */
- ARRAYLIST_FOREACH(&pp->ghostbusters, url)
- ghostbusters_traverse(*url, pp);
+ ARRAYLIST_FOREACH(&pp->files, map) {
+ char const *ext = map->url + strlen(map->url) - 4;
+ if (strcmp(ext, ".cer") == 0)
+ deferstack_push(certstack, map, pp);
+ else if (strcmp(ext, ".roa") == 0)
+ roa_traverse(map, pp);
+ else if (strcmp(ext, ".gbr") == 0)
+ ghostbusters_traverse(map, pp);
+ }
}
#include <openssl/safestack.h>
#include <openssl/x509.h>
+#include "types/map.h"
+
struct rpp;
struct rpp *rpp_create(void);
-void rpp_refget(struct rpp *pp);
-void rpp_refput(struct rpp *pp);
+void rpp_refget(struct rpp *);
+void rpp_refput(struct rpp *);
-void rpp_add_cert(struct rpp *, char *);
-int rpp_add_crl(struct rpp *, char *);
-void rpp_add_roa(struct rpp *, char *);
-void rpp_add_ghostbusters(struct rpp *, char *);
+int rpp_add_file(struct rpp *, struct cache_mapping *);
-char const *rpp_get_crl(struct rpp const *);
-int rpp_crl(struct rpp *, STACK_OF(X509_CRL) **);
+char const *rpp_get_crl_url(struct rpp const *);
+STACK_OF(X509_CRL) *rpp_crl(struct rpp *);
void rpp_traverse(struct rpp *);
#include "alloc.h"
#include "base64.h"
#include "cache.h"
+#include "cachent.h"
+#include "cachetmp.h"
#include "common.h"
#include "config.h"
#include "file.h"
db_slurm_create(struct slurm_csum_list *csums, struct db_slurm **result)
{
struct db_slurm *db;
- int error;
db = pmalloc(sizeof(struct db_slurm));
#include "types/map.h"
#include <string.h>
+
+#include "alloc.h"
#include "config.h"
#include "log.h"
+#include "types/path.h"
static char const *
get_filename(char const *file_path)
{
return map_get_printable(map, config_get_op_log_filename_format());
}
+
+void
+map_parent(struct cache_mapping *child, struct cache_mapping *parent)
+{
+ parent->url = path_parent(child->url);
+ parent->path = path_parent(child->path);
+}
+
+struct cache_mapping *
+map_child(struct cache_mapping *parent, char const *name)
+{
+ struct cache_mapping *child;
+
+ child = pmalloc(sizeof(struct cache_mapping));
+ child->url = join_paths(parent->url, name);
+ child->path = join_paths(parent->path, name);
+
+ return child;
+}
+
+void
+map_cleanup(struct cache_mapping *map)
+{
+ free(map->url);
+ free(map->path);
+}
// XXX document this better
struct cache_mapping {
- /*
- * The one that always starts with "rsync://" or "https://".
- * Normalized, ASCII-only, NULL-terminated.
- */
- char const *url;
-
- /*
- * Official cache location of the file.
- * Normalized, ASCII-only, NULL-terminated.
- */
- char const *path;
-
- /*
- * Temporary cache location of the file.
- * It'll stay here until committed.
- */
- char const *tmppath;
+ /* Normalized, ASCII-only, NULL-terminated. */
+ char *url;
+ /* Normalized, ASCII-only, NULL-terminated. */
+ char *path;
};
char const *map_val_get_printable(struct cache_mapping *);
char const *map_op_get_printable(struct cache_mapping *);
+void map_parent(struct cache_mapping *, struct cache_mapping *);
+struct cache_mapping *map_child(struct cache_mapping *, char const *);
+
+void map_cleanup(struct cache_mapping *);
+
#endif /* SRC_TYPES_MAP_H_ */
free(pb->string);
}
-/* Cannot return NULL. */
+/* Note, fatal is hardcoded as 1. */
+char *
+path_parent(char const *child)
+{
+ struct path_builder pb;
+ pb.string = pstrdup(child);
+ pb.len = pb.capacity = strlen(pb.string);
+ pb_pop(&pb, true);
+ return pb.string;
+}
+
+char *
+path_childn(char const *p1, char const *p2, size_t p2len)
+{
+ struct path_builder pb;
+
+ pb_init(&pb);
+ pb_append(&pb, p1); // XXX
+ pb_appendn(&pb, p2, p2len); // XXX
+
+ return pb.string;
+}
+
+/*
+ * Cannot return NULL.
+ *
+ * XXX I'm starting to use this more. Probably clean the slashes.
+ */
char *
join_paths(char const *path1, char const *path2)
{
void pb_cleanup(struct path_builder *);
+char *path_parent(char const *);
+char *path_childn(char const *, char const *, size_t);
char *join_paths(char const *, char const *);
#endif /* SRC_TYPES_PATH_H_ */
* times we get unsigned chars.
* Casting a negative char into a unsigned char is undefined behavior.
*/
-static int
-validate_url_character(int character)
-{
- /*
- * RFCs 1738 and 3986 define a very specific range of allowed
- * characters, but I don't think we're that concerned about URL
- * correctness. Validating the URL properly is more involved than simply
- * checking legal characters, anyway.
- *
- * What I really need this validation for is ensure that we won't get
- * any trouble later, when we attempt to map the URL to a path.
- *
- * Sample trouble: Getting UTF-8 characters. Why are they trouble?
- * Because we don't have any guarantees that the system's file name
- * encoding is UTF-8. URIs are not supposed to contain UTF-8 in the
- * first place, so we have no reason to deal with encoding conversion.
- *
- * To be perfectly fair, we have no guarantees that the system's file
- * name encoding is ASCII-compatible either, but I need to hang onto
- * SOMETHING.
- *
- * (Asking users to use UTF-8 is fine, but asking users to use something
- * ASCII-compatible is a little better.)
- *
- * So just make sure that the character is printable ASCII.
- *
- * TODO (next iteration) Consider exhaustive URL validation.
- */
- return (0x20 <= character && character <= 0x7E)
- ? 0
- : pr_val_err("URL has non-printable character code '%d'.", character);
-}
+//static int
+//validate_url_character(int character)
+//{
+// /*
+// * RFCs 1738 and 3986 define a very specific range of allowed
+// * characters, but I don't think we're that concerned about URL
+// * correctness. Validating the URL properly is more involved than simply
+// * checking legal characters, anyway.
+// *
+// * What I really need this validation for is ensure that we won't get
+// * any trouble later, when we attempt to map the URL to a path.
+// *
+// * Sample trouble: Getting UTF-8 characters. Why are they trouble?
+// * Because we don't have any guarantees that the system's file name
+// * encoding is UTF-8. URIs are not supposed to contain UTF-8 in the
+// * first place, so we have no reason to deal with encoding conversion.
+// *
+// * To be perfectly fair, we have no guarantees that the system's file
+// * name encoding is ASCII-compatible either, but I need to hang onto
+// * SOMETHING.
+// *
+// * (Asking users to use UTF-8 is fine, but asking users to use something
+// * ASCII-compatible is a little better.)
+// *
+// * So just make sure that the character is printable ASCII.
+// *
+// * TODO (next iteration) Consider exhaustive URL validation.
+// */
+// return (0x20 <= character && character <= 0x7E)
+// ? 0
+// : pr_val_err("URL has non-printable character code '%d'.", character);
+//}
static char *
path_rewind(char const *root, char *cursor)