# {{ page.title }}
-> TODO update with proper .tar.gz releases, once they are created
-
## Index
1. [Dependencies](#dependencies)
struct validation *state;
int total_parents;
+ STACK_OF(X509_CRL) *rpp_parent_crl;
X509 *cert;
struct rpki_uri *mft;
struct certificate_refs refs;
fnstack_push_uri(cert_uri);
memset(&refs, 0, sizeof(refs));
+ error = rpp_crl(rpp_parent, &rpp_parent_crl);
+ if (error)
+ goto revert_fnstack_and_debug;
+
/* -- Validate the certificate (@cert) -- */
error = certificate_load(cert_uri, &cert);
if (error)
goto revert_fnstack_and_debug;
- error = certificate_validate_chain(cert, rpp_crl(rpp_parent));
+ error = certificate_validate_chain(cert, rpp_parent_crl);
if (error)
goto revert_cert;
error = certificate_validate_rfc6487(cert, IS_TA);
goto revert_uri_and_refs;
cert = NULL; /* Ownership stolen */
- error = handle_manifest(mft, rpp_crl(rpp_parent), &pp);
+ error = handle_manifest(mft, rpp_parent_crl, &pp);
if (error) {
x509stack_cancel(validation_certstack(state));
goto revert_uri_and_refs;
static OID oid = OID_GHOSTBUSTERS;
struct oid_arcs arcs = OID2ARCS("ghostbusters", oid);
struct signed_object_args sobj_args;
+ STACK_OF(X509_CRL) *crl;
int error;
pr_debug_add("Ghostbusters '%s' {", uri_get_printable(uri));
fnstack_push_uri(uri);
- error = signed_object_args_init(&sobj_args, uri, rpp_crl(pp), true);
+ error = rpp_crl(pp, &crl);
+ if (error)
+ goto end1;
+
+ error = signed_object_args_init(&sobj_args, uri, crl, true);
if (error)
goto end1;
struct oid_arcs arcs = OID2ARCS("roa", oid);
struct signed_object_args sobj_args;
struct RouteOriginAttestation *roa;
+ STACK_OF(X509_CRL) *crl;
int error;
pr_debug_add("ROA '%s' {", uri_get_printable(uri));
fnstack_push_uri(uri);
- error = signed_object_args_init(&sobj_args, uri, rpp_crl(pp), false);
+ error = rpp_crl(pp, &crl);
+ if (error)
+ goto revert_fnstack;
+
+ error = signed_object_args_init(&sobj_args, uri, crl, false);
if (error)
goto revert_fnstack;
return error;
}
-STACK_OF(X509_CRL) *
-rpp_crl(struct rpp *pp)
+/**
+ * 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).
+ */
+int
+rpp_crl(struct rpp *pp, STACK_OF(X509_CRL) **result)
{
- if (pp == NULL)
- return NULL;
- if (pp->crl == NULL)
- return NULL;
- if (pp->crl_stack != NULL)
- return pp->crl_stack;
+ STACK_OF(X509_CRL) *stack;
+ int error;
- pp->crl_stack = sk_X509_CRL_new_null();
- if (pp->crl_stack == NULL)
- return NULL;
- if (add_crl_to_stack(pp, pp->crl_stack) != 0) {
- sk_X509_CRL_pop_free(pp->crl_stack, X509_CRL_free);
- return NULL;
+ if (pp == NULL) {
+ /* No pp = currently validating TA. There's no CRL. */
+ *result = NULL;
+ return 0;
+ }
+ if (pp->crl == 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;
+ }
+
+ /*
+ * TODO (performance) ghostbusters_traverse() and roa_traverse() can
+ * call rpp_crl() repeatedly, which means that, if it errors here,
+ * it will keep trying to recreate the stack and log the same error
+ * over and over.
+ * Consider creating a flag which will keep track of the CRL cache
+ * status, and prevent this code if it knows it's going to fail.
+ * Or maybe some other solution.
+ */
+ stack = sk_X509_CRL_new_null();
+ if (stack == NULL)
+ return pr_enomem();
+ error = add_crl_to_stack(pp, stack);
+ if (error) {
+ sk_X509_CRL_pop_free(stack, X509_CRL_free);
+ return error;
}
- return pp->crl_stack;
+ pp->crl_stack = stack; /* Cache result */
+ *result = stack;
+ return 0;
}
static int
int rpp_add_ghostbusters(struct rpp *, struct rpki_uri *);
struct rpki_uri *rpp_get_crl(struct rpp const *);
-STACK_OF(X509_CRL) *rpp_crl(struct rpp *);
+int rpp_crl(struct rpp *, STACK_OF(X509_CRL) **);
void rpp_traverse(struct rpp *);