From: Alberto Leiva Popper Date: Sat, 7 Sep 2024 02:42:39 +0000 (-0600) Subject: Week of work after August detours X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=68778e9162015f4984c2b47ea6c80a53fdd8588d;p=thirdparty%2FFORT-validator.git Week of work after August detours --- diff --git a/src/cache.c b/src/cache.c index 6713860f..aaf975ac 100644 --- a/src/cache.c +++ b/src/cache.c @@ -588,8 +588,7 @@ try_uri(char const *uri, struct cache_node *root, } 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."); diff --git a/src/cert_stack.c b/src/cert_stack.c index a9186b48..7858955b 100644 --- a/src/cert_stack.c +++ b/src/cert_stack.c @@ -175,15 +175,17 @@ certstack_destroy(struct cert_stack *stack) } 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); } diff --git a/src/cert_stack.h b/src/cert_stack.h index 3d938148..1e5c6249 100644 --- a/src/cert_stack.h +++ b/src/cert_stack.h @@ -38,7 +38,7 @@ struct deferred_cert { 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 *); diff --git a/src/certificate_refs.c b/src/certificate_refs.c index b94f6d31..87cc0b1c 100644 --- a/src/certificate_refs.c +++ b/src/certificate_refs.c @@ -27,7 +27,7 @@ validate_cdp(struct certificate_refs *refs, struct rpp const *pp) 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."); diff --git a/src/config.c b/src/config.c index 2a86fe7a..a6346e36 100644 --- a/src/config.c +++ b/src/config.c @@ -1243,6 +1243,12 @@ config_get_local_repository(void) return rpki_config.local_repository; } +time_t +cfg_cache_threshold(void) +{ + return 86400; // XXX +} + unsigned int config_get_max_cert_depth(void) { diff --git a/src/hash.c b/src/hash.c index ec78b653..4612d335 100644 --- a/src/hash.c +++ b/src/hash.c @@ -165,6 +165,10 @@ hash_validate_file(struct hash_algorithm const *algorithm, char const *path, 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; diff --git a/src/incidence.h b/src/incidence.h index 015c303e..93e97998 100644 --- a/src/incidence.h +++ b/src/incidence.h @@ -10,8 +10,8 @@ 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, diff --git a/src/object/certificate.c b/src/object/certificate.c index 072032ed..7a547bdc 100644 --- a/src/object/certificate.c +++ b/src/object/certificate.c @@ -32,6 +32,7 @@ #include "rrdp.h" #include "thread_var.h" #include "types/name.h" +#include "types/path.h" #include "types/str.h" /* @@ -1799,6 +1800,27 @@ certificate_validate_aia(char const *caIssuers, X509 *cert) 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) @@ -1810,7 +1832,6 @@ 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(); @@ -1828,9 +1849,11 @@ certificate_traverse(struct rpp *rpp_parent, struct cache_mapping *cert_map) 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); @@ -1873,25 +1896,15 @@ certificate_traverse(struct rpp *rpp_parent, struct cache_mapping *cert_map) 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); diff --git a/src/object/crl.c b/src/object/crl.c index 74781073..e4a19751 100644 --- a/src/object/crl.c +++ b/src/object/crl.c @@ -11,7 +11,7 @@ #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; @@ -20,16 +20,14 @@ __crl_load(struct cache_mapping *map, X509_CRL **result) 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; } @@ -152,13 +150,13 @@ crl_validate(X509_CRL *crl) } 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; diff --git a/src/object/crl.h b/src/object/crl.h index 6e4915bc..aecffed4 100644 --- a/src/object/crl.h +++ b/src/object/crl.h @@ -3,8 +3,6 @@ #include -#include "types/map.h" - -int crl_load(struct cache_mapping *, X509_CRL **); +int crl_load(char const *, X509_CRL **); #endif /* SRC_OBJECT_CRL_H_ */ diff --git a/src/object/ghostbusters.c b/src/object/ghostbusters.c index bb47c8e8..5d655ff4 100644 --- a/src/object/ghostbusters.c +++ b/src/object/ghostbusters.c @@ -1,5 +1,7 @@ #include "object/ghostbusters.h" +#include + #include "asn1/oid.h" #include "log.h" #include "object/signed_object.h" @@ -34,9 +36,11 @@ ghostbusters_traverse(struct cache_mapping *map, struct rpp *pp) 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 */ diff --git a/src/object/manifest.c b/src/object/manifest.c index 0afaf618..bb302dd2 100644 --- a/src/object/manifest.c +++ b/src/object/manifest.c @@ -14,6 +14,7 @@ #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) @@ -181,7 +182,7 @@ is_valid_mft_file_chara(uint8_t chara) || (chara == '_'); } -/* RFC 6486bis, section 4.2.2 */ +/* RFC 9286, section 4.2.2 */ static int validate_mft_file(IA5String_t *ia5) { @@ -192,99 +193,65 @@ 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]; @@ -292,76 +259,40 @@ build_rpp(struct Manifest *mft, char const *mft_url, struct rpp **pp) /* * 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) { @@ -385,15 +316,17 @@ 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 */ diff --git a/src/object/roa.c b/src/object/roa.c index 7d495a50..93c979cf 100644 --- a/src/object/roa.c +++ b/src/object/roa.c @@ -270,9 +270,11 @@ roa_traverse(struct cache_mapping *map, struct rpp *pp) 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 */ diff --git a/src/print_file.c b/src/print_file.c index 57abee2d..b5c1ad96 100644 --- a/src/print_file.c +++ b/src/print_file.c @@ -66,19 +66,22 @@ end: pb_cleanup(&pb); 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 * diff --git a/src/rpp.c b/src/rpp.c index 59a12287..cd70ae02 100644 --- a/src/rpp.c +++ b/src/rpp.c @@ -2,6 +2,7 @@ #include "alloc.h" #include "cert_stack.h" +#include "common.h" #include "log.h" #include "object/certificate.h" #include "object/crl.h" @@ -10,34 +11,17 @@ #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. @@ -48,18 +32,10 @@ struct rpp { 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; } @@ -74,158 +50,75 @@ rpp_refput(struct rpp *pp) { 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 @@ -234,21 +127,21 @@ rpp_traverse(struct rpp *pp) */ /* - * 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); + } } diff --git a/src/rpp.h b/src/rpp.h index 8999b4dc..15a15e3a 100644 --- a/src/rpp.h +++ b/src/rpp.h @@ -4,19 +4,18 @@ #include #include +#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 *); diff --git a/src/rrdp.c b/src/rrdp.c index 6107df51..be11c554 100644 --- a/src/rrdp.c +++ b/src/rrdp.c @@ -6,6 +6,8 @@ #include "alloc.h" #include "base64.h" #include "cache.h" +#include "cachent.h" +#include "cachetmp.h" #include "common.h" #include "config.h" #include "file.h" diff --git a/src/slurm/db_slurm.c b/src/slurm/db_slurm.c index 5a34cfcc..f93fe45e 100644 --- a/src/slurm/db_slurm.c +++ b/src/slurm/db_slurm.c @@ -97,7 +97,6 @@ int db_slurm_create(struct slurm_csum_list *csums, struct db_slurm **result) { struct db_slurm *db; - int error; db = pmalloc(sizeof(struct db_slurm)); diff --git a/src/types/map.c b/src/types/map.c index f2e620f1..b7260c07 100644 --- a/src/types/map.c +++ b/src/types/map.c @@ -1,8 +1,11 @@ #include "types/map.h" #include + +#include "alloc.h" #include "config.h" #include "log.h" +#include "types/path.h" static char const * get_filename(char const *file_path) @@ -38,3 +41,29 @@ map_op_get_printable(struct cache_mapping *map) { 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); +} diff --git a/src/types/map.h b/src/types/map.h index 2eb8568d..e678fa5b 100644 --- a/src/types/map.h +++ b/src/types/map.h @@ -3,26 +3,18 @@ // 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_ */ diff --git a/src/types/path.c b/src/types/path.c index 2246f338..672bc104 100644 --- a/src/types/path.c +++ b/src/types/path.c @@ -216,7 +216,34 @@ pb_cleanup(struct path_builder *pb) 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) { diff --git a/src/types/path.h b/src/types/path.h index 6aac775f..b8a8c14c 100644 --- a/src/types/path.h +++ b/src/types/path.h @@ -38,6 +38,8 @@ void pb_reverse(struct path_builder *); 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_ */ diff --git a/src/types/url.c b/src/types/url.c index 11d321fe..3e03b68c 100644 --- a/src/types/url.c +++ b/src/types/url.c @@ -16,38 +16,38 @@ * 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)