rpki_validator_SOURCES = main.c
rpki_validator_SOURCES += address.h address.c
+rpki_validator_SOURCES += array_list.h
+rpki_validator_SOURCES += certificate_refs.h certificate_refs.c
rpki_validator_SOURCES += common.h common.c
rpki_validator_SOURCES += debug.h debug.c
rpki_validator_SOURCES += file.h file.c
rpki_validator_SOURCES += log.h log.c
rpki_validator_SOURCES += random.h random.c
rpki_validator_SOURCES += resource.h resource.c
+rpki_validator_SOURCES += rpp.h rpp.c
rpki_validator_SOURCES += sorted_array.h sorted_array.c
rpki_validator_SOURCES += state.h state.c
rpki_validator_SOURCES += thread_var.h thread_var.c
--- /dev/null
+#ifndef SRC_ARRAY_LIST_H_
+#define SRC_ARRAY_LIST_H_
+
+#include <errno.h>
+
+#define ARRAY_LIST(name, elem_type) \
+ struct name { \
+ /** Unidimensional array. */ \
+ elem_type *array; \
+ /** Number of elements in @array. */ \
+ unsigned int len; \
+ /** Actual allocated slots in @array. */ \
+ unsigned int capacity; \
+ }; \
+ \
+ static int \
+ name##_init(struct name *list) \
+ { \
+ list->capacity = 8; \
+ list->len = 0; \
+ list->array = malloc(list->capacity \
+ * sizeof(elem_type)); \
+ return (list->array != NULL) ? 0 : -ENOMEM; \
+ } \
+ \
+ static void \
+ name##_cleanup(struct name *list, void (*cb)(elem_type *)) \
+ { \
+ unsigned int i; \
+ for (i = 0; i < list->len; i++) \
+ cb(&list->array[i]); \
+ free(list->array); \
+ } \
+ \
+ /* Will store a shallow copy, not @elem */ \
+ static int \
+ name##_add(struct name *list, elem_type *elem) \
+ { \
+ elem_type *tmp; \
+ \
+ list->len++; \
+ while (list->len >= list->capacity) { \
+ list->capacity *= 2; \
+ \
+ tmp = realloc(list->array, list->capacity \
+ * sizeof(elem_type)); \
+ if (tmp == NULL) \
+ return pr_enomem(); \
+ list->array = tmp; \
+ } \
+ \
+ list->array[list->len - 1] = *elem; \
+ return 0; \
+ } \
+ \
+ static int \
+ name##_foreach(struct name *list, \
+ int (*cb)(elem_type const *, void *), \
+ void *arg) \
+ { \
+ unsigned int i; \
+ int error; \
+ \
+ for (i = 0; i < list->len; i++) { \
+ error = cb(&list->array[i], arg); \
+ if (error) \
+ return error; \
+ } \
+ \
+ return 0; \
+ }
+
+#endif /* SRC_ARRAY_LIST_H_ */
}
static int
-handle_sdata_certificate(ANY_t *any, STACK_OF(X509_CRL) *crls,
- struct resources *res, OCTET_STRING_t *sid)
+handle_sdata_certificate(ANY_t *any, struct signed_object_args *args,
+ OCTET_STRING_t *sid)
{
const unsigned char *tmp;
X509 *cert;
int error;
- pr_debug_add("(EE?) Certificate (embedded) {");
+ pr_debug_add("EE Certificate (embedded) {");
/*
* "If the call is successful *in is incremented to the byte following
goto end1;
}
- error = certificate_validate_chain(cert, crls);
+ error = certificate_validate_chain(cert, args->crls);
if (error)
goto end2;
error = certificate_validate_rfc6487(cert, false);
if (error)
goto end2;
- if (res != NULL) {
- error = certificate_get_resources(cert, res);
+ if (args->res != NULL) {
+ error = certificate_get_resources(cert, args->res);
if (error)
goto end2;
}
- error = certificate_traverse_ee(cert, sid);
+ error = certificate_validate_extensions_ee(cert, sid, &args->refs);
end2:
X509_free(cert);
}
static int
-validate(struct SignedData *sdata, STACK_OF(X509_CRL) *crls,
- struct resources *res)
+validate(struct SignedData *sdata, struct signed_object_args *args)
{
struct SignerInfo *sinfo;
OCTET_STRING_t *sid = NULL;
}
error = handle_sdata_certificate(sdata->certificates->list.array[0],
- crls, res, sid);
+ args, sid);
if (error)
return error;
}
int
-signed_data_decode(ANY_t *coded, struct SignedData **result,
- STACK_OF(X509_CRL) *crls, struct resources *res)
+signed_data_decode(ANY_t *coded, struct signed_object_args *args,
+ struct SignedData **result)
{
struct SignedData *sdata;
int error;
if (error)
return error;
- error = validate(sdata, crls, res);
+ error = validate(sdata, args);
if (error) {
signed_data_free(sdata);
return error;
#include <openssl/x509.h>
#include <libcmscodec/SignedData.h>
#include "resource.h"
+#include "object/certificate.h"
-int signed_data_decode(ANY_t *, struct SignedData **, STACK_OF(X509_CRL) *,
- struct resources *);
+/*
+ * This only exists to reduce argument lists.
+ * TODO document fields.
+ */
+struct signed_object_args {
+ STACK_OF(X509_CRL) *crls;
+ struct resources *res;
+ struct rpki_uri const *uri;
+ struct certificate_refs refs;
+};
+
+int signed_data_decode(ANY_t *, struct signed_object_args *args,
+ struct SignedData **);
void signed_data_free(struct SignedData *);
int get_content_type_attr(struct SignedData *, OBJECT_IDENTIFIER_t **);
--- /dev/null
+#include "certificate_refs.h"
+
+#include <errno.h>
+#include "log.h"
+#include "thread_var.h"
+
+void
+refs_init(struct certificate_refs *refs)
+{
+ memset(refs, 0, sizeof(struct certificate_refs));
+}
+
+void
+refs_cleanup(struct certificate_refs *refs)
+{
+ free(refs->crldp);
+ free(refs->caIssuers);
+ free(refs->signedObject);
+}
+
+static int
+validate_cdp(struct certificate_refs *refs, struct rpp const *pp)
+{
+ struct rpki_uri const *pp_crl;
+
+ if (refs->crldp == NULL)
+ return pr_err("Programming error: Certificate's CRL Distribution Point was not recorded.");
+
+ pp_crl = rpp_get_crl(pp);
+ if (pp_crl == NULL)
+ return pr_err("Programming error: Manifest's CRL was not recorded.");
+
+ if (strcmp(refs->crldp, pp_crl->global) != 0) {
+ return pr_err("Certificate's CRL Distribution Point ('%s') does not match manifest's CRL ('%s').",
+ refs->crldp, pp_crl->global);
+ }
+
+ return 0;
+}
+
+static int
+validate_aia(struct certificate_refs *refs)
+{
+ struct validation *state;
+ struct rpki_uri const *parent;
+
+ if (refs->caIssuers == NULL)
+ return pr_err("Programming error: Certificate's AIA was not recorded.");
+
+ state = state_retrieve();
+ if (state == NULL)
+ return -EINVAL;
+ parent = validation_peek_cert_uri(state);
+ if (parent == NULL)
+ return pr_err("Programming error: CA certificate has no parent.");
+
+ if (strcmp(refs->caIssuers, parent->global) != 0) {
+ return pr_err("Certificate's AIA ('%s') does not match parent's URI ('%s').",
+ refs->caIssuers, parent->global);
+ }
+
+ return 0;
+}
+
+static int
+validate_signedObject(struct certificate_refs *refs,
+ struct rpki_uri const *signedObject_uri)
+{
+ if (refs->signedObject == NULL)
+ return pr_err("Programming error: Certificate's signedObject was not recorded.");
+
+ if (strcmp(refs->signedObject, signedObject_uri->global) != 0) {
+ return pr_err("Certificate's signedObject ('%s') does not match the URI of its own signed object (%s).",
+ refs->signedObject, signedObject_uri->global);
+ }
+
+ return 0;
+}
+
+int
+refs_validate_ca(struct certificate_refs *refs, bool is_ta,
+ struct rpp const *pp)
+{
+ int error;
+
+ if (is_ta)
+ return 0;
+
+ error = validate_cdp(refs, pp);
+ if (error)
+ return error;
+
+ error = validate_aia(refs);
+ if (error)
+ return error;
+
+ if (refs->signedObject != NULL) {
+ return pr_err("Programming error: CA summary has a signedObject ('%s').",
+ refs->signedObject);
+ }
+
+ return 0;
+}
+
+int
+refs_validate_ee(struct certificate_refs *refs, struct rpp const *pp,
+ struct rpki_uri const *uri)
+{
+ int error;
+
+ error = validate_cdp(refs, pp);
+ if (error)
+ return error;
+
+ error = validate_aia(refs);
+ if (error)
+ return error;
+
+ return validate_signedObject(refs, uri);
+}
--- /dev/null
+#ifndef SRC_CERTIFICATE_REFS_H_
+#define SRC_CERTIFICATE_REFS_H_
+
+#include <stdbool.h>
+#include "rpp.h"
+
+/**
+ * Some of the URLs defined in Access Descriptions of a certificate's
+ * extensions.
+ *
+ * It's intended to address some awkward RFC requirements:
+ * RFC 6487 defines that these "MUST reference" certain files. I think the best
+ * way to validate this is to check that they equal the respective URLs from the
+ * manifest (because these will at some point be validated as part of the
+ * traversal anyway). Problem is, these URLs are not guaranteed to be parsed by
+ * the time the extension validation kicks in. So we store them in this
+ * structure and handle them later.
+ *
+ * It makes a mess out of the code, and I'm not even sure that validating them
+ * is our responsibility, but there you go.
+ */
+struct certificate_refs {
+ /**
+ * CRL Distribution Points's fullName. Non-TA certificates only.
+ * RFC 6487, section 4.8.6.
+ */
+ char *crldp;
+ /**
+ * AIA's caIssuers. Non-TA certificates only.
+ * RFC 6487, section 4.8.7.
+ */
+ char *caIssuers;
+ /**
+ * SIA's signedObject. EE certificates only.
+ * RFC 6487, section 4.8.8.2.
+ */
+ char *signedObject;
+};
+
+void refs_init(struct certificate_refs *);
+void refs_cleanup(struct certificate_refs *);
+int refs_validate_ca(struct certificate_refs *, bool, struct rpp const *);
+int refs_validate_ee(struct certificate_refs *, struct rpp const *,
+ struct rpki_uri const *);
+
+#endif /* SRC_CERTIFICATE_REFS_H_ */
int NID_rpkiManifest;
int NID_signedObject;
int NID_rpkiNotify;
+
+int
+string_clone(void const *string, size_t size, char **clone)
+{
+ char *result;
+
+ result = malloc(size + 1);
+ if (result == NULL)
+ return pr_enomem();
+
+ memcpy(result, string, size);
+ result[size] = '\0';
+
+ *clone = result;
+ return 0;
+}
+
+int
+ia5s2string(ASN1_IA5STRING *ia5, char **result)
+{
+ return (ia5->flags & ASN1_STRING_FLAG_BITS_LEFT)
+ ? pr_err("CRL URI IA5String has unused bits.")
+ : string_clone(ia5->data, ia5->length, result);
+}
#define ARRAY_LEN(array) (sizeof(array) / sizeof(array[0]))
+int string_clone(void const *, size_t, char **);
+int ia5s2string(ASN1_IA5STRING *, char **);
+
#endif /* SRC_RTR_COMMON_H_ */
#include "common.h"
#include "debug.h"
#include "log.h"
+#include "rpp.h"
#include "thread_var.h"
#include "object/certificate.h"
+#include "object/manifest.h"
#include "object/tal.h"
#include "rsync/rsync.h"
printf("rpkiNotify registered. Its nid is %d.\n", NID_rpkiNotify);
}
-static int
-handle_tal_certificate(struct rpki_uri const *uri)
-{
- X509 *cert;
- int error;
-
- fnstack_push(uri->global);
- error = certificate_load(uri, &cert);
- if (error)
- goto end;
-
- error = certificate_validate_rfc6487(cert, true);
- if (error)
- goto revert;
- error = certificate_traverse_ta(cert, NULL);
-
-revert:
- X509_free(cert);
-end:
- fnstack_pop();
- return error;
-}
-
/**
* Performs the whole validation walkthrough on uri @uri, which is assumed to
* have been extracted from a TAL.
goto end;
}
- error = handle_tal_certificate(uri);
+ error = certificate_traverse(NULL, uri, NULL, true);
if (error) {
switch (validation_pubkey_state(state)) {
case PKS_INVALID:
#include "crypto/hash.h"
#include "rsync/rsync.h"
+/* Just to prevent some line breaking. */
+#define GN_URI uniformResourceIdentifier
+
/*
* The X509V3_EXT_METHOD that references NID_sinfo_access uses the AIA item.
* The SIA's d2i function, therefore, returns AIAs.
OCTET_STRING_t *sid;
};
-struct sia_arguments {
- X509 *cert;
- STACK_OF(X509_CRL) *crls;
-};
-
static int
validate_serial_number(X509 *cert)
{
}
static int
-handle_rpkiManifest(ACCESS_DESCRIPTION *ad, STACK_OF(X509_CRL) *crls)
+handle_rpkiManifest(ACCESS_DESCRIPTION *ad, struct rpki_uri *mft)
{
- struct rpki_uri uri;
- int error;
-
- error = uri_init_ad(&uri, ad);
- if (error)
- return error;
-
- error = handle_manifest(&uri, crls);
-
- uri_cleanup(&uri);
- return error;
+ return uri_init_ad(mft, ad);
}
static int
}
static int
-handle_signedObject(ACCESS_DESCRIPTION *ad)
+handle_signedObject(ACCESS_DESCRIPTION *ad, struct certificate_refs *refs)
{
struct rpki_uri uri;
int error;
+ /* TODO all three of them probably need this treatment. */
error = uri_init_ad(&uri, ad);
if (error)
return error;
pr_debug("signedObject: %s", uri.global);
+ refs->signedObject = uri.global;
+ uri.global = NULL;
+
uri_cleanup(&uri);
return error;
}
static int
handle_cdp(X509_EXTENSION *ext, void *arg)
{
- STACK_OF(DIST_POINT) *crldp = X509V3_EXT_d2i(ext);
+ struct certificate_refs *refs = arg;
+ STACK_OF(DIST_POINT) *crldp;
DIST_POINT *dp;
GENERAL_NAMES *names;
GENERAL_NAME *name;
names = dp->distpoint->name.fullname;
for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
name = sk_GENERAL_NAME_value(names, i);
- if (name->type == GEN_URI && is_rsync(name->d.uniformResourceIdentifier)) {
+ if (name->type == GEN_URI && is_rsync(name->d.GN_URI)) {
/*
- * TODO (certext) check the URI matches what we rsync'd.
- * Also indent properly.
+ * Since we're parsing and validating the manifest's CRL
+ * at some point, I think that all we need to do now is
+ * compare this CRL URI to that one's.
+ *
+ * But there is a problem:
+ * The manifest's CRL might not have been parsed at this
+ * point. In fact, it's guaranteed to not have been
+ * parsed if the certificate we're validating is the EE
+ * certificate of the manifest itself.
+ *
+ * So we will store the URI in @refs, and validate it
+ * later.
*/
- error = 0;
+ error = ia5s2string(name->d.GN_URI, &refs->crldp);
+ pr_debug("Certificate CRL: %s", refs->crldp);
goto end;
}
}
static int
handle_aia(X509_EXTENSION *ext, void *arg)
{
+ struct certificate_refs *refs = arg;
AUTHORITY_INFO_ACCESS *aia;
ACCESS_DESCRIPTION *ad;
int i;
for (i = 0; i < sk_ACCESS_DESCRIPTION_num(aia); i++) {
ad = sk_ACCESS_DESCRIPTION_value(aia, i);
if (OBJ_obj2nid(ad->method) == NID_ad_ca_issuers) {
+ if (ad->location->type != GEN_URI) {
+ return pr_err("The AIA caIssuers is not an URI. (type: %d)",
+ ad->location->type);
+ }
+
/*
- * TODO (certext) check the URI matches what we rsync'd.
+ * Bringing the parent certificate's URI all the way
+ * over here is too much trouble, so do the handle_cdp()
+ * hack.
*/
+
+ return ia5s2string(ad->location->d.GN_URI,
+ &refs->caIssuers);
}
}
static int
handle_sia_ca(X509_EXTENSION *ext, void *arg)
{
- struct sia_arguments *args = arg;
- struct validation *state;
SIGNATURE_INFO_ACCESS *sia;
ACCESS_DESCRIPTION *ad;
bool rsync_found = false;
if (sia == NULL)
return cannot_decode(&SIA);
- state = state_retrieve();
- if (state == NULL) {
- error = -EINVAL;
- goto end2;
- }
- error = validation_push_cert(state, args->cert, false);
- if (error)
- goto end2;
-
/* rsync */
for (i = 0; i < sk_ACCESS_DESCRIPTION_num(sia); i++) {
ad = sk_ACCESS_DESCRIPTION_value(sia, i);
if (error == ENOTRSYNC)
continue;
if (error)
- goto end1;
+ goto end;
rsync_found = true;
break;
}
if (!rsync_found) {
pr_err("SIA extension lacks a caRepository RSYNC URI.");
error = -ESRCH;
- goto end1;
+ goto end;
}
- /* validate */
+ /*
+ * Store the manifest URI in @mft.
+ * (We won't actually touch the manifest until we know the certificate
+ * is fully valid.)
+ */
for (i = 0; i < sk_ACCESS_DESCRIPTION_num(sia); i++) {
ad = sk_ACCESS_DESCRIPTION_value(sia, i);
if (OBJ_obj2nid(ad->method) == NID_rpkiManifest) {
*/
if (manifest_found) {
error = pr_err("SIA defines more than one manifest.");
- goto end1;
+ goto end;
}
- error = handle_rpkiManifest(ad, args->crls);
+ error = handle_rpkiManifest(ad, arg);
if (error)
- goto end1;
+ goto end;
manifest_found = true;
}
}
error = -ESRCH;
}
-end1:
- validation_pop_cert(state); /* Error code is useless. */
-end2:
+end:
AUTHORITY_INFO_ACCESS_free(sia);
return error;
}
nid = OBJ_obj2nid(ad->method);
if (nid == NID_signedObject) {
- error = handle_signedObject(ad);
+ error = handle_signedObject(ad, arg);
/* TODO Unknown signedObjects are allowed. */
if (error)
goto end;
}
int
-certificate_traverse_ta(X509 *cert, STACK_OF(X509_CRL) *crls)
+certificate_validate_extensions_ta(X509 *cert, struct rpki_uri *mft)
{
- struct sia_arguments sia_args;
struct extension_handler handlers[] = {
/* ext reqd handler arg */
{ &BC, true, handle_bc, },
{ &SKI, true, handle_ski_ca, cert },
{ &AKI, false, handle_aki_ta, cert },
{ &KU, true, handle_ku_ca, },
- { &SIA, true, handle_sia_ca, &sia_args },
+ { &SIA, true, handle_sia_ca, mft },
{ &CP, true, handle_cp, },
{ &IR, false, handle_ir, },
{ &AR, false, handle_ar, },
{ NULL },
};
- sia_args.cert = cert;
- sia_args.crls = crls;
-
return handle_cert_extensions(handlers, cert);
}
int
-certificate_traverse_ca(X509 *cert, STACK_OF(X509_CRL) *crls)
+certificate_validate_extensions_ca(X509 *cert, struct rpki_uri *mft,
+ struct certificate_refs *refs)
{
- struct sia_arguments sia_args;
struct extension_handler handlers[] = {
/* ext reqd handler arg */
{ &BC, true, handle_bc, },
{ &SKI, true, handle_ski_ca, cert },
{ &AKI, true, handle_aki, },
{ &KU, true, handle_ku_ca, },
- { &CDP, true, handle_cdp, },
- { &AIA, true, handle_aia, },
- { &SIA, true, handle_sia_ca, &sia_args },
+ { &CDP, true, handle_cdp, refs },
+ { &AIA, true, handle_aia, refs },
+ { &SIA, true, handle_sia_ca, mft },
{ &CP, true, handle_cp, },
{ &IR, false, handle_ir, },
{ &AR, false, handle_ar, },
{ NULL },
};
- sia_args.cert = cert;
- sia_args.crls = crls;
-
return handle_cert_extensions(handlers, cert);
}
int
-certificate_traverse_ee(X509 *cert, OCTET_STRING_t *sid)
+certificate_validate_extensions_ee(X509 *cert, OCTET_STRING_t *sid,
+ struct certificate_refs *refs)
{
struct ski_arguments ski_args;
struct extension_handler handlers[] = {
{ &SKI, true, handle_ski_ee, &ski_args },
{ &AKI, true, handle_aki, },
{ &KU, true, handle_ku_ee, },
- { &CDP, true, handle_cdp, },
- { &AIA, true, handle_aia, },
- { &SIA, true, handle_sia_ee, },
+ { &CDP, true, handle_cdp, refs },
+ { &AIA, true, handle_aia, refs },
+ { &SIA, true, handle_sia_ee, refs },
{ &CP, true, handle_cp, },
{ &IR, false, handle_ir, },
{ &AR, false, handle_ar, },
return handle_cert_extensions(handlers, cert);
}
+
+/* Boilerplate code for CA certificate validation and recursive traversal. */
+int
+certificate_traverse(struct rpp *rpp_parent, struct rpki_uri const *cert_uri,
+ STACK_OF(X509_CRL) *crls, bool is_ta)
+{
+ struct validation *state;
+ X509 *cert;
+ struct rpki_uri mft;
+ struct certificate_refs refs;
+ struct rpp *pp;
+ int error;
+
+ pr_debug_add("%s Certificate %s {", is_ta ? "TA" : "CA",
+ cert_uri->global);
+ fnstack_push(cert_uri->global);
+ memset(&refs, 0, sizeof(refs));
+
+ /* -- Validate the certificate (@cert) -- */
+ error = certificate_load(cert_uri, &cert);
+ if (error)
+ goto end1;
+ if (!is_ta) {
+ error = certificate_validate_chain(cert, crls);
+ if (error)
+ goto end2;
+ }
+ error = certificate_validate_rfc6487(cert, is_ta);
+ if (error)
+ goto end2;
+ error = is_ta
+ ? certificate_validate_extensions_ta(cert, &mft)
+ : certificate_validate_extensions_ca(cert, &mft, &refs);
+ if (error)
+ goto end2;
+
+ error = refs_validate_ca(&refs, is_ta, rpp_parent);
+ if (error)
+ goto end3;
+
+ /* -- Validate the manifest (@mft) pointed by the certificate -- */
+ state = state_retrieve();
+ if (state == NULL) {
+ error = -EINVAL;
+ goto end3;
+ }
+ error = validation_push_cert(state, cert_uri, cert, is_ta);
+ if (error)
+ goto end3;
+
+ error = handle_manifest(&mft, crls, &pp);
+ if (error)
+ goto end4;
+
+ /* -- Validate & traverse the RPP (@pp) described by the manifest -- */
+ error = rpp_traverse(pp);
+
+ rpp_destroy(pp);
+end4:
+ validation_pop_cert(state); /* Error code is useless. */
+end3:
+ uri_cleanup(&mft);
+ refs_cleanup(&refs);
+end2:
+ X509_free(cert);
+end1:
+ fnstack_pop();
+ pr_debug_rm("}");
+ return error;
+}
#include <stdbool.h>
#include <openssl/x509.h>
+#include "certificate_refs.h"
#include "resource.h"
+#include "rpp.h"
#include "uri.h"
int certificate_load(struct rpki_uri const *, X509 **);
/**
* Performs the basic (RFC 5280, presumably) chain validation.
- * (Ignores the IP, AS and SIA extensions.)
+ * (Ignores the IP and AS extensions.)
*/
int certificate_validate_chain(X509 *, STACK_OF(X509_CRL) *);
/**
* Validates RFC 6487 compliance.
- * (Except IP, AS and SIA extensions.)
+ * (Except extensions.)
*/
int certificate_validate_rfc6487(X509 *, bool);
/**
* Returns the IP and AS resources declared in the respective extensions.
+ *
+ * TODO why is this not part of the certificate_validate*s, again?
*/
int certificate_get_resources(X509 *, struct resources *);
/**
- * Handles the SIA extension, Trust Anchor style.
- * (ie. Recursively walks through the certificate's children.)
+ * Validates the certificate extensions, Trust Anchor style.
+ *
+ * Also initializes the second argument as the URI of the rpkiManifest Access
+ * Description from the SIA extension.
*/
-int certificate_traverse_ta(X509 *, STACK_OF(X509_CRL) *);
+int certificate_validate_extensions_ta(X509 *, struct rpki_uri *);
/**
- * Handles the SIA extension, (intermediate) CA style.
- * (ie. Recursively walks through the certificate's children.)
+ * Validates the certificate extensions, (intermediate) Certificate Authority
+ * style.
+ *
+ * Also initializes the second argument as the URI of the rpkiManifest Access
+ * Description from the SIA extension.
+ * Also initializes the third argument with the references found in the
+ * extensions.
*/
-int certificate_traverse_ca(X509 *, STACK_OF(X509_CRL) *);
+int certificate_validate_extensions_ca(X509 *, struct rpki_uri *,
+ struct certificate_refs *);
/**
- * Handles the SIA extension, EE style.
- * (Doesn't actually "traverse" anything. The name is just for the sake of
- * mirroring.)
+ * Validates the certificate extensions, End-Entity style.
+ *
+ * Also initializes the second argument with the references found in the
+ * extensions.
*/
-int certificate_traverse_ee(X509 *, OCTET_STRING_t *);
+int certificate_validate_extensions_ee(X509 *, OCTET_STRING_t *,
+ struct certificate_refs *);
+
+int certificate_traverse(struct rpp *, struct rpki_uri const *,
+ STACK_OF(X509_CRL) *, bool);
#endif /* SRC_OBJECT_CERTIFICATE_H_ */
return 0;
}
-typedef int (*foreach_cb)(struct rpki_uri const *, void *);
-
static int
-foreach_file(struct manifest *mft, char *extension, foreach_cb cb, void *arg)
+__handle_manifest(struct manifest *mft, struct rpp **pp)
{
+ int i;
struct FileAndHash *fah;
struct rpki_uri uri;
- int i;
int error;
+ *pp = rpp_create();
+ if (*pp == NULL)
+ return pr_enomem();
+
for (i = 0; i < mft->obj->fileList.list.count; i++) {
fah = mft->obj->fileList.list.array[i];
- error = uri_init_ia5(&uri, mft->file_path, &fah->file);
+ error = uri_init_mft(&uri, mft->file_path, &fah->file);
if (error)
- return error;
-
- if (!uri_has_extension(&uri, extension)) {
- uri_cleanup(&uri);
- continue;
- }
+ goto fail;
error = hash_validate_file("sha256", &uri, &fah->hash);
if (error) {
continue;
}
- error = cb(&uri, arg);
- uri_cleanup(&uri);
- if (error)
- return error;
- }
-
- return 0;
-}
-
-static int
-pile_crls(struct rpki_uri const *uri, void *crls)
-{
- X509_CRL *crl;
- int error;
- int idx;
-
- /* rfc6481#section-2.2 */
- if (sk_X509_CRL_num(crls) != 0)
- return pr_err("The Manifest defines more than one CRL.");
-
- fnstack_push(uri->global);
-
- error = crl_load(uri, &crl);
- if (error)
- goto end;
+ if (uri_has_extension(&uri, ".cer"))
+ error = rpp_add_cert(*pp, &uri);
+ else if (uri_has_extension(&uri, ".roa"))
+ error = rpp_add_roa(*pp, &uri);
+ else if (uri_has_extension(&uri, ".crl"))
+ error = rpp_add_crl(*pp, &uri);
+ else
+ uri_cleanup(&uri); /* ignore it. */
- idx = sk_X509_CRL_push(crls, crl);
- if (idx <= 0) {
- error = crypto_err("Could not add CRL to a CRL stack");
- X509_CRL_free(crl);
- goto end;
+ if (error) {
+ uri_cleanup(&uri);
+ goto fail;
+ } /* Otherwise ownership was transferred to @pp. */
}
-end:
- fnstack_pop();
- return error;
-}
-
-/*
- * Speaking of CA certs: I still don't get the CA/EE cert duality at the
- * implementation level.
- *
- * Right now, I'm assuming that file certs are CA certs, and CMS-embedded certs
- * are EE certs. None of the RFCs seem to mandate this, but I can't think of any
- * other way to interpret it.
- *
- * It's really weird because the RFCs actually define requirements like "other
- * AccessMethods MUST NOT be used for an EE certificates's SIA," (RFC6481) which
- * seems to imply that there's some contextual way to already know whether a
- * certificate is CA or EE. But it just doesn't exist.
- */
-static int
-traverse_ca_certs(struct rpki_uri const *uri, void *crls)
-{
- X509 *cert;
-
- pr_debug_add("(CA?) Certificate {");
- fnstack_push(uri->global);
-
- /*
- * Errors on at least some of these functions should not interrupt the
- * traversal of sibling nodes, so ignore them.
- * (Error messages should have been printed in stderr.)
- */
-
- if (certificate_load(uri, &cert))
- goto revert1; /* Fine */
-
- if (certificate_validate_chain(cert, crls))
- goto revert2; /* Fine */
- if (certificate_validate_rfc6487(cert, false))
- goto revert2; /* Fine */
- certificate_traverse_ca(cert, crls); /* Error code is useless. */
-
-revert2:
- X509_free(cert);
-revert1:
- pr_debug_rm("}");
- fnstack_pop();
- return 0;
-}
-
-static int
-print_roa(struct rpki_uri const *uri, void *arg)
-{
- handle_roa(uri, arg);
return 0;
-}
-static int
-__handle_manifest(struct manifest *mft)
-{
- STACK_OF(X509_CRL) *crls;
- int error;
-
- /* Init */
- crls = sk_X509_CRL_new_null();
- if (crls == NULL)
- return pr_enomem();
-
- /* Get the one CRL as a stack. */
- error = foreach_file(mft, ".crl", pile_crls, crls);
- if (error)
- goto end;
-
- /* Use CRL stack to validate certificates, and also traverse them. */
- error = foreach_file(mft, ".cer", traverse_ca_certs, crls);
- if (error)
- goto end;
-
- /* Use valid address ranges to print ROAs that match them. */
- error = foreach_file(mft, ".roa", print_roa, crls);
-
-end:
- sk_X509_CRL_pop_free(crls, X509_CRL_free);
+fail:
+ rpp_destroy(*pp);
return error;
}
+/**
+ * Validates the manifest pointed by @uri, returns the RPP described by it in
+ * @pp.
+ */
int
-handle_manifest(struct rpki_uri const *uri, STACK_OF(X509_CRL) *crls)
+handle_manifest(struct rpki_uri const *uri, STACK_OF(X509_CRL) *crls,
+ struct rpp **pp)
{
static OID oid = OID_MANIFEST;
struct oid_arcs arcs = OID2ARCS(oid);
+ struct signed_object_args sobj_args;
struct manifest mft;
int error;
pr_debug_add("Manifest %s {", uri->global);
fnstack_push(uri->global);
+ sobj_args.uri = uri;
+ sobj_args.crls = crls;
+ sobj_args.res = NULL;
+ memset(&sobj_args.refs, 0, sizeof(sobj_args.refs));
mft.file_path = uri->global;
- error = signed_object_decode(uri, &asn_DEF_Manifest, &arcs,
- (void **) &mft.obj, crls, NULL);
+ error = signed_object_decode(&sobj_args, &asn_DEF_Manifest, &arcs,
+ (void **) &mft.obj); /* mft.obj and sobj_args.refs in the heap */
if (error)
- goto end;
+ goto end1;
error = validate_manifest(mft.obj);
- if (!error)
- error = __handle_manifest(&mft);
+ if (error)
+ goto end2;
+ error = __handle_manifest(&mft, pp); /* pp in the heap */
+ if (error)
+ goto end2;
+
+ error = refs_validate_ee(&sobj_args.refs, *pp, uri);
+ if (error)
+ rpp_destroy(*pp);
+end2:
ASN_STRUCT_FREE(asn_DEF_Manifest, mft.obj);
-end:
+ refs_cleanup(&sobj_args.refs);
+end1:
pr_debug_rm("}");
fnstack_pop();
return error;
#include <openssl/x509.h>
#include "uri.h"
+#include "rpp.h"
-int handle_manifest(struct rpki_uri const *, STACK_OF(X509_CRL) *);
+int handle_manifest(struct rpki_uri const *, STACK_OF(X509_CRL) *,
+ struct rpp **);
#endif /* SRC_OBJECT_MANIFEST_H_ */
return pr_err("ROA's IP family is not v4 or v6.");
}
-int handle_roa(struct rpki_uri const *uri, STACK_OF(X509_CRL) *crls)
+int handle_roa(struct rpki_uri const *uri, struct rpp *pp,
+ STACK_OF(X509_CRL) *crls)
{
static OID oid = OID_ROA;
struct oid_arcs arcs = OID2ARCS(oid);
+ struct signed_object_args sobj_args;
struct RouteOriginAttestation *roa;
- /* Resources contained in the ROA certificate, not in the ROA itself. */
- struct resources *cert_resources;
int error;
pr_debug_add("ROA %s {", uri->global);
fnstack_push(uri->global);
- cert_resources = resources_create();
- if (cert_resources == NULL) {
+ sobj_args.uri = uri;
+ sobj_args.crls = crls;
+ sobj_args.res = resources_create();
+ if (sobj_args.res == NULL) {
error = pr_enomem();
goto end1;
}
+ memset(&sobj_args.refs, 0, sizeof(sobj_args.refs));
- error = signed_object_decode(uri, &asn_DEF_RouteOriginAttestation,
- &arcs, (void **) &roa, crls, cert_resources);
+ error = signed_object_decode(&sobj_args,
+ &asn_DEF_RouteOriginAttestation, &arcs, (void **) &roa);
if (error)
goto end2;
- error = __handle_roa(roa, cert_resources);
- ASN_STRUCT_FREE(asn_DEF_RouteOriginAttestation, roa);
+ error = __handle_roa(roa, sobj_args.res);
+ if (error)
+ goto end3;
+
+ error = refs_validate_ee(&sobj_args.refs, pp, sobj_args.uri);
+
+end3:
+ ASN_STRUCT_FREE(asn_DEF_RouteOriginAttestation, roa);
+ refs_cleanup(&sobj_args.refs);
end2:
- resources_destroy(cert_resources);
+ resources_destroy(sobj_args.res);
end1:
pr_debug_rm("}");
fnstack_pop();
#define SRC_OBJECT_ROA_H_
#include <openssl/x509.h>
+#include "rpp.h"
#include "uri.h"
-int handle_roa(struct rpki_uri const *uri, STACK_OF(X509_CRL) *);
+int handle_roa(struct rpki_uri const *, struct rpp *, STACK_OF(X509_CRL) *);
#endif /* SRC_OBJECT_ROA_H_ */
#include "log.h"
#include "asn1/content_info.h"
#include "asn1/decode.h"
-#include "asn1/signed_data.h"
static int
validate_eContentType(struct SignedData *sdata,
}
int
-signed_object_decode(struct rpki_uri const *uri,
+signed_object_decode(struct signed_object_args *args,
asn_TYPE_descriptor_t const *descriptor,
struct oid_arcs const *oid,
- void **result,
- STACK_OF(X509_CRL) *crls,
- struct resources *res)
+ void **result)
{
struct ContentInfo *cinfo;
struct SignedData *sdata;
int error;
- error = content_info_load(uri, &cinfo);
+ error = content_info_load(args->uri, &cinfo);
if (error)
goto end1;
- error = signed_data_decode(&cinfo->content, &sdata, crls, res);
+ error = signed_data_decode(&cinfo->content, args, &sdata);
if (error)
goto end2;
#include <openssl/x509.h>
#include "asn1/oid.h"
-#include "resource.h"
-#include "uri.h"
+#include "asn1/signed_data.h"
-int signed_object_decode(struct rpki_uri const *, asn_TYPE_descriptor_t const *,
- struct oid_arcs const *, void **, STACK_OF(X509_CRL) *, struct resources *);
+int signed_object_decode(struct signed_object_args *args,
+ asn_TYPE_descriptor_t const *, struct oid_arcs const *, void **);
#endif /* SRC_OBJECT_SIGNED_OBJECT_H_ */
int error;
for (i = 0; i < tal->uris.count; i++) {
- error = uri_init(&uri, tal->uris.array[i]);
+ error = uri_init_str(&uri, tal->uris.array[i]);
if (error)
return error;
#include <errno.h>
#include <arpa/inet.h>
-#include <sys/queue.h>
#include "address.h"
#include "log.h"
struct resources_ipv4 *ip4s;
struct resources_ipv6 *ip6s;
struct resources_asn *asns;
-
- /*
- * Used by restack. Points to the resources of the parent certificate.
- */
- SLIST_ENTRY(resources) next;
};
-/*
- * "Resource stack". It's a chain of resources, to complement a chain of
- * certificates.
- */
-SLIST_HEAD(restack, resources);
-
struct resources *
resources_create(void)
{
return res6_contains_prefix(res->ip6s, prefix);
}
-struct restack *
-restack_create(void)
-{
- struct restack *result;
-
- result = malloc(sizeof(struct restack));
- if (result == NULL) {
- pr_enomem();
- return NULL;
- }
-
- SLIST_INIT(result);
- return result;
-}
-
-void
-restack_destroy(struct restack *stack)
-{
- struct resources *resources;
- unsigned int r = 0;
-
- while (!SLIST_EMPTY(stack)) {
- resources = SLIST_FIRST(stack);
- SLIST_REMOVE_HEAD(stack, next);
- resources_destroy(resources);
- r++;
- }
-
- free(stack);
- pr_debug("Deleted %u resources from the stack.", r);
-}
-
-void
-restack_push(struct restack *stack, struct resources *new)
-{
- SLIST_INSERT_HEAD(stack, new, next);
-}
-
-struct resources *
-restack_pop(struct restack *stack)
-{
- struct resources *res;
-
- res = SLIST_FIRST(stack);
- if (res != NULL) {
- SLIST_REMOVE_HEAD(stack, next);
- SLIST_NEXT(res, next) = NULL;
- }
-
- return res;
-}
-
-struct resources *
-restack_peek(struct restack *stack)
-{
- return SLIST_FIRST(stack);
-}
bool resources_contains_ipv4(struct resources *, struct ipv4_prefix *);
bool resources_contains_ipv6(struct resources *, struct ipv6_prefix *);
-/* "Resource stack." Stack of struct resources. */
-struct restack;
-
-struct restack *restack_create(void);
-void restack_destroy(struct restack *);
-
-void restack_push(struct restack *, struct resources *);
-struct resources *restack_pop(struct restack *);
-struct resources *restack_peek(struct restack *);
-
#endif /* SRC_RESOURCE_H_ */
--- /dev/null
+#include "rpp.h"
+
+#include <stdlib.h>
+#include "array_list.h"
+#include "log.h"
+#include "thread_var.h"
+#include "uri.h"
+#include "object/certificate.h"
+#include "object/crl.h"
+#include "object/roa.h"
+
+ARRAY_LIST(uris, struct rpki_uri)
+
+/** A Repository Publication Point (RFC 6481), as described by some manifest. */
+struct rpp {
+ struct uris certs; /* Certificates */
+
+ struct rpki_uri crl; /* Certificate Revocation List */
+ bool crl_set;
+
+ /* The Manifest is not needed for now. */
+
+ struct uris roas; /* Route Origin Attestations */
+};
+
+struct foreach_args {
+ struct rpp *pp;
+ STACK_OF(X509_CRL) *crls;
+};
+
+struct rpp *
+rpp_create(void)
+{
+ struct rpp *result;
+
+ result = malloc(sizeof(struct rpp));
+ if (result == NULL)
+ goto fail1;
+
+ if (uris_init(&result->certs) != 0)
+ goto fail2;
+ result->crl_set = false;
+ if (uris_init(&result->roas) != 0)
+ goto fail3;
+
+ return result;
+
+fail3:
+ uris_cleanup(&result->certs, uri_cleanup);
+fail2:
+ free(result);
+fail1:
+ return NULL;
+}
+
+void
+rpp_destroy(struct rpp *pp)
+{
+ uris_cleanup(&pp->certs, uri_cleanup);
+ uris_cleanup(&pp->roas, uri_cleanup);
+ free(pp);
+}
+
+int
+rpp_add_cert(struct rpp *pp, struct rpki_uri *uri)
+{
+ return uris_add(&pp->certs, uri);
+}
+
+int
+rpp_add_roa(struct rpp *pp, struct rpki_uri *uri)
+{
+ return uris_add(&pp->roas, uri);
+}
+
+int
+rpp_add_crl(struct rpp *pp, struct rpki_uri *uri)
+{
+ /* rfc6481#section-2.2 */
+ if (pp->crl_set)
+ return pr_err("Repository Publication Point has more than one CRL.");
+
+ pp->crl = *uri;
+ pp->crl_set = true;
+ pr_debug("Manifest CRL: %s", uri->global);
+ return 0;
+}
+
+static int
+add_crl_to_stack(struct rpp *pp, STACK_OF(X509_CRL) *crls)
+{
+ X509_CRL *crl;
+ int error;
+ int idx;
+
+ pr_debug("MANIFEST.CRL: %s", pp->crl.global);
+ fnstack_push(pp->crl.global);
+
+ error = crl_load(&pp->crl, &crl);
+ if (error)
+ goto end;
+
+ idx = sk_X509_CRL_push(crls, crl);
+ if (idx <= 0) {
+ error = crypto_err("Could not add CRL to a CRL stack");
+ X509_CRL_free(crl);
+ goto end;
+ }
+
+end:
+ fnstack_pop();
+ return error;
+}
+
+static int
+traverse_ca_certs(struct rpki_uri const *uri, void *arg)
+{
+ struct foreach_args *args = arg;
+ return certificate_traverse(args->pp, uri, args->crls, false);
+}
+
+static int
+print_roa(struct rpki_uri const *uri, void *arg)
+{
+ struct foreach_args *args = arg;
+ handle_roa(uri, args->pp, args->crls);
+ return 0;
+}
+
+struct rpki_uri const *
+rpp_get_crl(struct rpp const *pp)
+{
+ return pp->crl_set ? &pp->crl : NULL;
+}
+
+int
+rpp_traverse(struct rpp *pp)
+{
+ /*
+ * TODO is the stack supposed to have only the CRLs of this layer,
+ * or all of them?
+ */
+ struct foreach_args args;
+ int error;
+
+ args.pp = pp;
+ args.crls = sk_X509_CRL_new_null();
+ if (args.crls == NULL)
+ return pr_enomem();
+ error = add_crl_to_stack(pp, args.crls);
+ if (error)
+ goto end;
+
+ /* Use CRL stack to validate certificates, and also traverse them. */
+ error = uris_foreach(&pp->certs, traverse_ca_certs, &args);
+ if (error)
+ goto end;
+
+ /* Use valid address ranges to print ROAs that match them. */
+ error = uris_foreach(&pp->roas, print_roa, &args);
+
+end:
+ sk_X509_CRL_pop_free(args.crls, X509_CRL_free);
+ return error;
+}
--- /dev/null
+#ifndef SRC_RPP_H_
+#define SRC_RPP_H_
+
+#include "uri.h"
+
+struct rpp;
+
+struct rpp *rpp_create(void);
+void rpp_destroy(struct rpp *);
+
+int rpp_add_cert(struct rpp *, struct rpki_uri *);
+int rpp_add_crl(struct rpp *, struct rpki_uri *);
+int rpp_add_roa(struct rpp *, struct rpki_uri *);
+
+struct rpki_uri const *rpp_get_crl(struct rpp const *);
+
+int rpp_traverse(struct rpp *);
+
+#endif /* SRC_RPP_H_ */
#include "state.h"
#include <errno.h>
+#include <sys/queue.h>
#include "log.h"
#include "thread_var.h"
#include "object/certificate.h"
+/**
+ * Cached certificate data.
+ */
+struct certificate {
+ struct rpki_uri uri;
+ struct resources *resources;
+
+ /** Used by certstack. Points to the next stacked certificate. */
+ SLIST_ENTRY(certificate) next;
+};
+
+SLIST_HEAD(certstack, certificate);
+
/**
* The current state of the validation cycle.
*
/** Certificates we've already validated. */
STACK_OF(X509) *trusted;
+
/**
- * The resources owned by the certificates from @trusted.
+ * Stacked additional data to each @trusted certificate.
*
- * (One for each certificate; these two stacks should practically always
- * have the same size. The reason why I don't combine them is because
- * libcrypto's validation function wants the stack of X509 and I'm not
- * creating it over and over again.)
+ * (These two stacks should always have the same size. The reason why I
+ * don't combine them is because libcrypto's validation function needs
+ * the X509 stack, and I'm not creating it over and over again.)
*
* (This is a SLIST and not a STACK_OF because the OpenSSL stack
* implementation is different than the LibreSSL one, and the latter is
* seemingly not intended to be used outside of its library.)
*/
- struct restack *rsrcs;
+ struct certstack certs;
/* Did the TAL's public key match the root certificate's public key? */
enum pubkey_state pubkey_state;
goto abort2;
}
- result->rsrcs = restack_create();
- if (!result->rsrcs) {
- error = -ENOMEM;
- goto abort3;
- }
-
+ SLIST_INIT(&result->certs);
result->pubkey_state = PKS_UNTESTED;
*out = result;
return 0;
-abort3:
- sk_X509_pop_free(result->trusted, X509_free);
abort2:
X509_STORE_free(result->store);
abort1:
validation_destroy(struct validation *state)
{
int cert_num;
+ struct certificate *cert;
+ unsigned int c;
cert_num = sk_X509_num(state->trusted);
if (cert_num != 0) {
cert_num);
}
- restack_destroy(state->rsrcs);
+ c = 0;
+ while (!SLIST_EMPTY(&state->certs)) {
+ cert = SLIST_FIRST(&state->certs);
+ SLIST_REMOVE_HEAD(&state->certs, next);
+ resources_destroy(cert->resources);
+ free(cert);
+ c++;
+ }
+ pr_debug("Deleted %u certificates from the stack.", c);
+
sk_X509_pop_free(state->trusted, X509_free);
X509_STORE_free(state->store);
free(state);
return state->trusted;
}
-struct restack *
-validation_resources(struct validation *state)
-{
- return state->rsrcs;
-}
-
void validation_pubkey_valid(struct validation *state)
{
state->pubkey_state = PKS_VALID;
return state->pubkey_state;
}
+/**
+ * Ownership of @cert_uri's members will NOT be transferred to @state on
+ * success, and they will be expected to outlive @x509.
+ */
int
-validation_push_cert(struct validation *state, X509 *cert, bool is_ta)
+validation_push_cert(struct validation *state, struct rpki_uri const *cert_uri,
+ X509 *x509, bool is_ta)
{
- struct resources *resources;
+ struct certificate *cert;
int ok;
int error;
- resources = resources_create();
- if (resources == NULL)
- return pr_enomem();
+ cert = malloc(sizeof(struct certificate));
+ if (cert == NULL) {
+ error = pr_enomem();
+ goto end1;
+ }
+
+ cert->uri = *cert_uri;
+ cert->resources = resources_create();
+ if (cert->resources == NULL) {
+ error = pr_enomem();
+ goto end2;
+ }
- error = certificate_get_resources(cert, resources);
+ error = certificate_get_resources(x509, cert->resources);
if (error)
- goto fail;
+ goto end3;
/*
* rfc7730#section-2.2
* The "It MUST NOT use the "inherit" form of the INR extension(s)"
* part is already handled in certificate_get_resources().
*/
- if (is_ta && resources_empty(resources))
- return pr_err("Trust Anchor certificate does not define any number resources.");
+ if (is_ta && resources_empty(cert->resources)) {
+ error = pr_err("Trust Anchor certificate does not define any number resources.");
+ goto end3;
+ }
- ok = sk_X509_push(state->trusted, cert);
+ ok = sk_X509_push(state->trusted, x509);
if (ok <= 0) {
error = crypto_err(
"Couldn't add certificate to trusted stack: %d", ok);
- goto fail;
+ goto end3;
}
- restack_push(state->rsrcs, resources);
+ SLIST_INSERT_HEAD(&state->certs, cert, next);
+
return 0;
-fail:
- resources_destroy(resources);
- return error;
+end3: resources_destroy(cert->resources);
+end2: free(cert);
+end1: return error;
}
int
validation_pop_cert(struct validation *state)
{
- struct resources *resources;
+ struct certificate *cert;
if (sk_X509_pop(state->trusted) == NULL)
- return pr_crit("Attempted to pop empty certificate stack");
+ return pr_crit("Attempted to pop empty certificate stack (1)");
- resources = restack_pop(state->rsrcs);
- if (resources == NULL)
- return pr_crit("Attempted to pop empty resource stack");
- resources_destroy(resources);
+ cert = SLIST_FIRST(&state->certs);
+ if (cert == NULL)
+ return pr_crit("Attempted to pop empty certificate stack (2)");
+ SLIST_REMOVE_HEAD(&state->certs, next);
+ resources_destroy(cert->resources);
+ free(cert);
return 0;
}
return sk_X509_value(state->trusted, sk_X509_num(state->trusted) - 1);
}
+struct rpki_uri const *
+validation_peek_cert_uri(struct validation *state)
+{
+ struct certificate *cert = SLIST_FIRST(&state->certs);
+ return (cert != NULL) ? &cert->uri : NULL;
+}
+
struct resources *
validation_peek_resource(struct validation *state)
{
- return restack_peek(state->rsrcs);
+ struct certificate *cert = SLIST_FIRST(&state->certs);
+ return (cert != NULL) ? cert->resources : NULL;
}
struct tal *validation_tal(struct validation *);
X509_STORE *validation_store(struct validation *);
STACK_OF(X509) *validation_certs(struct validation *);
-struct restack *validation_resources(struct validation *);
enum pubkey_state {
PKS_VALID,
void validation_pubkey_invalid(struct validation *);
enum pubkey_state validation_pubkey_state(struct validation *);
-int validation_push_cert(struct validation *, X509 *, bool);
+int validation_push_cert(struct validation *, struct rpki_uri const *, X509 *,
+ bool);
int validation_pop_cert(struct validation *);
X509 *validation_peek_cert(struct validation *);
+struct rpki_uri const *validation_peek_cert_uri(struct validation *);
struct resources *validation_peek_resource(struct validation *);
* This function does not assume that @str is null-terminated.
*/
static int
-str2global(char const *str, size_t str_len, struct rpki_uri *uri)
+str2global(void const *str, size_t str_len, struct rpki_uri *uri)
{
- uri->global = malloc(str_len + 1);
- if (uri->global == NULL)
- return pr_enomem();
- strncpy(uri->global, str, str_len);
- uri->global[str_len] = '\0';
-
uri->global_len = str_len;
-
- return 0;
+ return string_clone(str, str_len, &uri->global);
}
/**
}
int
-uri_init(struct rpki_uri *uri, char const *guri)
+uri_init(struct rpki_uri *uri, void const *guri, size_t guri_len)
{
int error;
- error = str2global(guri, strlen(guri), uri);
+ error = str2global(guri, guri_len, uri);
if (error)
return error;
return 0;
}
+/**
+ * Do not call this function unless you're sure that @guri is NULL-terminated.
+ */
+int uri_init_str(struct rpki_uri *uri, char const *guri)
+{
+ return uri_init(uri, guri, strlen(guri));
+}
+
+/*
+ * Manifests URIs are a little special in that they are relative.
+ */
int
-uri_init_ia5(struct rpki_uri *uri, char const *mft, IA5String_t *ia5)
+uri_init_mft(struct rpki_uri *uri, char const *mft, IA5String_t *ia5)
{
int error;
{
ASN1_STRING *asn1_string;
int type;
- int error;
asn1_string = GENERAL_NAME_get0_value(ad->location, &type);
* directory our g2l version of @asn1_string should contain.
* But ask the testers to keep an eye on it anyway.
*/
- error = str2global((char *) ASN1_STRING_get0_data(asn1_string),
- ASN1_STRING_length(asn1_string), uri);
- if (error)
- return error;
-
- error = autocomplete_local(uri);
- if (error)
- free(uri->global);
-
- return error;
+ return uri_init(uri, ASN1_STRING_get0_data(asn1_string),
+ ASN1_STRING_length(asn1_string));
}
void
/* "local_len" is not needed for now. */
};
-int uri_init(struct rpki_uri *, char const *guri);
-int uri_init_ia5(struct rpki_uri *, char const *, IA5String_t *);
+int uri_init(struct rpki_uri *, void const *, size_t);
+int uri_init_str(struct rpki_uri *uri, char const *guri);
+int uri_init_mft(struct rpki_uri *, char const *, IA5String_t *);
int uri_init_ad(struct rpki_uri *, ACCESS_DESCRIPTION *ad);
void uri_cleanup(struct rpki_uri *);