fort_SOURCES += base64.h base64.c
fort_SOURCES += cache.c cache.h
fort_SOURCES += cachetmp.c cachetmp.h
-fort_SOURCES += certificate_refs.h certificate_refs.c
fort_SOURCES += common.c common.h
fort_SOURCES += config/boolean.c config/boolean.h
fort_SOURCES += config/filename_format.h config/filename_format.c
}
int
-validate_cms_hashing_algorithm(AlgorithmIdentifier_t *id, char const *what)
+validate_cms_hash_algorithm(AlgorithmIdentifier_t *id, char const *what)
{
int error;
if (id == NULL)
return pr_val_err("The hash algorithm of the '%s' is absent", what);
- error = validate_cms_hashing_algorithm_oid(&id->algorithm, what);
+ error = validate_cms_hash_algorithm_oid(&id->algorithm, what);
if (error)
return error;
}
int
-validate_cms_hashing_algorithm_oid(OBJECT_IDENTIFIER_t *oid, char const *what)
+validate_cms_hash_algorithm_oid(OBJECT_IDENTIFIER_t *oid, char const *what)
{
/*
* RFC 7935:
int validate_certificate_public_key_algorithm(X509_ALGOR *);
int validate_certificate_public_key_algorithm_bgpsec(X509_ALGOR *);
-int validate_cms_hashing_algorithm(AlgorithmIdentifier_t *, char const *);
-int validate_cms_hashing_algorithm_oid(OBJECT_IDENTIFIER_t *, char const *);
+int validate_cms_hash_algorithm(AlgorithmIdentifier_t *, char const *);
+int validate_cms_hash_algorithm_oid(OBJECT_IDENTIFIER_t *, char const *);
int validate_cms_signature_algorithm(AlgorithmIdentifier_t *);
#endif /* SRC_ALGORITHM_H_ */
#include "hash.h"
#include "log.h"
#include "object/certificate.h"
+#include "object/signed_object.h"
#include "types/name.h"
static const OID oid_cta = OID_CONTENT_TYPE_ATTR;
static const OID oid_sta = OID_SIGNING_TIME_ATTR;
static int
-get_sid(struct SignerInfo *sinfo, OCTET_STRING_t **result)
+get_sid(struct SignerInfo *sinfo, OCTET_STRING_t const **result)
{
switch (sinfo->sid.present) {
case SignerIdentifier_PR_subjectKeyIdentifier:
break;
}
+ *result = NULL;
return pr_val_err("Signer Info's sid is not a SubjectKeyIdentifier.");
}
static int
-handle_sdata_certificate(ANY_t *cert_encoded, struct rpki_certificate *ee,
- OCTET_STRING_t *sid, ANY_t *signedData, SignatureValue_t *signature)
+handle_sdata_ee(struct signed_object *so, struct rpki_certificate *ee,
+ ANY_t *cer_encoded)
{
const unsigned char *otmp, *tmp;
- int error;
/*
* No need to validate certificate chain length, since we just arrived
* We definitely don't want @any->buf to be modified, so use a dummy
* pointer.
*/
- tmp = (const unsigned char *) cert_encoded->buf;
+ tmp = (const unsigned char *)cer_encoded->buf;
otmp = tmp;
- ee->x509 = d2i_X509(NULL, &tmp, cert_encoded->size);
+ ee->x509 = d2i_X509(NULL, &tmp, cer_encoded->size);
if (ee->x509 == NULL)
return val_crypto_err("Signed object's 'certificate' element does not decode into a Certificate");
- if (tmp != otmp + cert_encoded->size)
+ if (tmp != otmp + cer_encoded->size)
return val_crypto_err("Signed object's 'certificate' element contains trailing garbage");
- x509_name_pr_clutter("Issuer", X509_get_issuer_name(ee->x509));
-
- error = certificate_validate_chain(ee);
- if (error)
- return error;
- error = certificate_validate_rfc6487(ee);
- if (error)
- return error;
- error = certificate_validate_extensions_ee(ee, sid);
- if (error)
- return error;
- error = certificate_validate_aia(ee);
- if (error)
- return error;
- error = certificate_validate_signature(ee->x509, signedData, signature);
- if (error)
- return error;
- resources_set_policy(ee->resources, ee->policy);
- return certificate_get_resources(ee);
+ return cer_validate_ee(ee, so);
}
/* rfc6488#section-2.1.6.4.1 */
}
int
-signed_data_validate(ANY_t *encoded, struct SignedData *sdata,
- struct rpki_certificate *ee)
+signed_data_validate(struct signed_object *so, struct rpki_certificate *ee)
{
+ struct SignedData *sdata;
struct SignerInfo *sinfo;
- OCTET_STRING_t *sid = NULL;
unsigned long version;
int error;
/* rfc6488#section-2.1 */
+ sdata = so->sdata;
if (sdata->signerInfos.list.count != 1) {
return pr_val_err("The SignedData's SignerInfo set is supposed to have only one element. (%d given.)",
sdata->signerInfos.list.count);
* AlgorithmIdentifier instead. There's no API.
* This seems to work fine.
*/
- error = validate_cms_hashing_algorithm(
+ error = validate_cms_hash_algorithm(
(AlgorithmIdentifier_t *) sdata->digestAlgorithms.list.array[0],
"SignedData");
if (error)
sinfo = sdata->signerInfos.list.array[0];
if (sinfo == NULL)
return pr_val_err("The SignerInfo object is NULL.");
+ so->signature = &sinfo->signature;
error = asn_INTEGER2ulong(&sinfo->version, &version);
if (error) {
/* rfc6488#section-2.1.6.2 */
/* rfc6488#section-3.1.c 2/2 */
/* (Most of this requirement is in handle_ski_ee().) */
- error = get_sid(sinfo, &sid);
+ error = get_sid(sinfo, &so->sid);
if (error)
return error;
/* rfc6488#section-2.1.6.3 */
/* rfc6488#section-3.1.j 2/2 */
- error = validate_cms_hashing_algorithm(&sinfo->digestAlgorithm,
+ error = validate_cms_hash_algorithm(&sinfo->digestAlgorithm,
"SignerInfo");
if (error)
return error;
sdata->certificates->list.count);
}
- return handle_sdata_certificate(sdata->certificates->list.array[0],
- ee, sid, encoded, &sinfo->signature);
+ return handle_sdata_ee(so, ee, sdata->certificates->list.array[0]);
}
/*
/* Some wrappers for asn1/asn1c/SignedData.h. */
#include "asn1/asn1c/SignedData.h"
-#include "object/certificate.h"
+
+struct rpki_certificate;
+struct signed_object;
int signed_data_decode(ANY_t *, struct SignedData **);
-int signed_data_validate(ANY_t *, struct SignedData *,
- struct rpki_certificate *);
+int signed_data_validate(struct signed_object *, struct rpki_certificate *);
int get_content_type_attr(struct SignedData *, OBJECT_IDENTIFIER_t **);
}
static struct cache_node *
-find_rrdp_fallback_node(struct sia_uris *sias)
+find_rrdp_fallback_node(struct extension_uris *uris)
{
struct node_key key;
struct cache_node *result;
- if (!uri_str(&sias->rpkiNotify) || !uri_str(&sias->caRepository))
+ if (!uri_str(&uris->rpkiNotify) || !uri_str(&uris->caRepository))
return NULL;
- init_rrdp_fallback_key(&key, &sias->rpkiNotify, &sias->caRepository);
+ init_rrdp_fallback_key(&key, &uris->rpkiNotify, &uris->caRepository);
result = find_node(&cache.fallback, key.id, key.idlen);
free(key.id);
}
static struct cache_node *
-get_fallback(struct sia_uris *sias)
+get_fallback(struct extension_uris *uris)
{
struct cache_node *rrdp;
struct cache_node *rsync;
- rrdp = find_rrdp_fallback_node(sias);
- rsync = find_node(&cache.fallback, uri_str(&sias->caRepository),
- uri_len(&sias->caRepository));
+ rrdp = find_rrdp_fallback_node(uris);
+ rsync = find_node(&cache.fallback, uri_str(&uris->caRepository),
+ uri_len(&uris->caRepository));
if (rrdp == NULL)
return rsync;
* XXX Fallback only if parent is fallback
*/
validation_verdict
-cache_refresh_by_sias(struct sia_uris *sias, struct cache_cage **result)
+cache_refresh_by_uris(struct extension_uris *uris, struct cache_cage **result)
{
struct cache_node *node;
struct cache_cage *cage;
validation_verdict vv;
// XXX Make sure somewhere validates rpkiManifest matches caRepository.
- // XXX review result signs
/* Try RRDP + optional fallback */
- if (uri_str(&sias->rpkiNotify) != NULL) {
- vv = do_refresh(&cache.rrdp, &sias->rpkiNotify, &node);
+ if (uri_str(&uris->rpkiNotify) != NULL) {
+ vv = do_refresh(&cache.rrdp, &uris->rpkiNotify, &node);
if (vv == VV_CONTINUE) {
- rpkiNotify = sias->rpkiNotify;
+ rpkiNotify = uris->rpkiNotify;
goto refresh_success;
}
if (vv == VV_BUSY)
}
/* Try rsync + optional fallback */
- vv = do_refresh(&cache.rsync, &sias->caRepository, &node);
+ vv = do_refresh(&cache.rsync, &uris->caRepository, &node);
if (vv == VV_CONTINUE) {
memset(&rpkiNotify, 0, sizeof(rpkiNotify));
goto refresh_success;
return VV_BUSY;
/* Try fallback only */
- node = get_fallback(sias);
+ node = get_fallback(uris);
if (!node)
return VV_FAIL; /* Nothing to work with */
*result = cage = pzalloc(sizeof(struct cache_cage));
cage->rpkiNotify = rpkiNotify;
cage->refresh = node;
- cage->fallback = get_fallback(sias);
+ cage->fallback = get_fallback(uris);
return VV_CONTINUE;
}
}
void
-sias_init(struct sia_uris *sias)
+exturis_init(struct extension_uris *uris)
{
- memset(sias, 0, sizeof(*sias));
+ memset(uris, 0, sizeof(*uris));
}
void
-sias_cleanup(struct sia_uris *sias)
+exturis_cleanup(struct extension_uris *uris)
{
- uri_cleanup(&sias->caRepository);
- uri_cleanup(&sias->rpkiNotify);
- uri_cleanup(&sias->rpkiManifest);
- uri_cleanup(&sias->crldp);
- uri_cleanup(&sias->caIssuers);
- uri_cleanup(&sias->signedObject);
+ uri_cleanup(&uris->caRepository);
+ uri_cleanup(&uris->rpkiNotify);
+ uri_cleanup(&uris->rpkiManifest);
+ uri_cleanup(&uris->crldp);
+ uri_cleanup(&uris->caIssuers);
+ uri_cleanup(&uris->signedObject);
}
int cache_prepare(void); /* Prepare cache for new validation cycle */
void cache_commit(void); /* Finish validation cycle */
-/* XXX might wanna rename */
-struct sia_uris {
+struct extension_uris {
struct uri caRepository; /* RPP cage */
struct uri rpkiNotify; /* RRDP Notification */
struct uri rpkiManifest;
struct uri signedObject;
};
-void sias_init(struct sia_uris *);
-void sias_cleanup(struct sia_uris *);
+void exturis_init(struct extension_uris *);
+void exturis_cleanup(struct extension_uris *);
char *cache_refresh_by_url(struct uri const *);
char *cache_get_fallback(struct uri const *);
struct cache_cage;
-validation_verdict cache_refresh_by_sias(struct sia_uris *,
+validation_verdict cache_refresh_by_uris(struct extension_uris *,
struct cache_cage **);
char const *cage_map_file(struct cache_cage *, struct uri const *);
bool cage_disable_refresh(struct cache_cage *);
+++ /dev/null
-#include "certificate_refs.h"
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "log.h"
-
-int
-validate_cdp(struct sia_uris const *sias, struct uri const *crl_url)
-{
- if (uri_str(&sias->crldp) == NULL)
- pr_crit("Certificate's CRL Distribution Point was not recorded.");
- if (uri_str(crl_url) == NULL)
- pr_crit("Manifest's CRL was not recorded.");
-
- if (uri_equals(&sias->crldp, crl_url) != 0) {
- return pr_val_err("Certificate's CRL Distribution Point ('%s') does not match manifest's CRL ('%s').",
- uri_str(&sias->crldp), uri_str(crl_url));
- }
-
- return 0;
-}
-
-static int
-validate_signedObject(struct sia_uris const *sias, struct uri const *url)
-{
- if (uri_str(&sias->signedObject) == NULL)
- pr_crit("Certificate's signedObject was not recorded.");
-
- if (!uri_equals(&sias->signedObject, url))
- return pr_val_err("Certificate's signedObject ('%s') does not match the URI of its own signed object (%s).",
- uri_str(&sias->signedObject), uri_str(url));
-
- return 0;
-}
-
-/**
- * Ensures the @refs URIs match the Manifest URIs. Assumes @refs came from an
- * EE certificate.
- *
- * @refs: References you want validated.
- * @url: URL of the signed object that contains the EE certificate.
- */
-int
-refs_validate_ee(struct sia_uris const *sias, struct uri const *crl_url,
- struct uri const *url)
-{
- int error;
-
- error = validate_cdp(sias, crl_url);
- if (error)
- return error;
-
- return validate_signedObject(sias, url);
-}
+++ /dev/null
-#ifndef SRC_CERTIFICATE_REFS_H_
-#define SRC_CERTIFICATE_REFS_H_
-
-/* XXX delete this */
-
-#include "cache.h"
-
-int validate_cdp(struct sia_uris const *, struct uri const *);
-int refs_validate_ee(struct sia_uris const *, struct uri const *,
- struct uri const *);
-
-#endif /* SRC_CERTIFICATE_REFS_H_ */
#define ENOTIMPLEMENTED 3173
typedef char const *validation_verdict;
-extern validation_verdict const VV_CONTINUE;
-extern validation_verdict const VV_FAIL;
-extern validation_verdict const VV_BUSY;
+extern validation_verdict const VV_CONTINUE; /* "No issues yet" */
+extern validation_verdict const VV_FAIL; /* "Validation failed" */
+extern validation_verdict const VV_BUSY; /* "Try again later" */
bool str_starts_with(char const *, char const *);
bool str_ends_with(char const *, char const *);
struct {
/* Enables the protocol */
bool enabled;
- /* Protocol preference; compared to http.priority */
+ /* Deprecated; does nothing. */
unsigned int priority;
/* Maximum simultaneous rsyncs */
unsigned int max;
struct {
/* Enables the protocol */
bool enabled;
- /* Protocol preference; compared to rsync.priority */
+ /* Deprecated; does nothing. */
unsigned int priority;
/* HTTP User-Agent request header */
char *user_agent;
.doc = "rsync's priority for repository file fetching. Higher value means higher priority.",
.min = 0,
.max = 100,
- /* XXX deprecated? */
+ .deprecated = true,
}, {
.id = 3002,
.name = "rsync.strategy",
.doc = "HTTP's priority for repository file fetching. Higher value means higher priority.",
.min = 0,
.max = 100,
- /* XXX deprecated? */
+ .deprecated = true,
}, {
.id = 9004,
.name = "http.user-agent",
string_array_init(&rpki_config.rsync.args, trash, ARRAY_LEN(trash));
rpki_config.http.enabled = true;
- /* Higher priority than rsync by default */
rpki_config.http.priority = 60;
rpki_config.http.user_agent = pstrdup(PACKAGE_NAME "/" PACKAGE_VERSION);
rpki_config.http.max_redirs = 10;
return !rpki_config.work_offline && rpki_config.rsync.enabled;
}
-unsigned int
-config_get_rsync_priority(void)
-{
- return rpki_config.rsync.priority;
-}
-
unsigned int
config_rsync_max(void)
{
return !rpki_config.work_offline && rpki_config.http.enabled;
}
-unsigned int
-config_get_http_priority(void)
-{
- return rpki_config.http.priority;
-}
-
char const *
config_get_http_user_agent(void)
{
char const *config_get_http_ca_path(void);
unsigned int config_get_rrdp_delta_threshold(void);
bool config_get_rsync_enabled(void);
-unsigned int config_get_rsync_priority(void);
unsigned int config_rsync_max(void);
long config_rsync_timeout(void);
char const *config_get_rsync_program(void);
bool config_get_http_enabled(void);
-unsigned int config_get_http_priority(void);
char const *config_get_output_roa(void);
char const *config_get_output_bgpsec(void);
enum output_format config_get_output_format(void);
resources = resources_create(policy, false);
if (resources == NULL)
goto revert_ski;
- error = certificate_get_resources(cert, resources, CERTYPE_BGPSEC);
+ error = cer_get_resources(cert, resources, CERTYPE_BGPSEC);
if (error)
goto revert_resources;
#include "object/ghostbusters.h"
#include "object/manifest.h"
#include "object/roa.h"
+#include "object/signed_object.h"
#include "object/tal.h"
#include "task.h"
#include "thread_var.h"
struct ski_arguments {
X509 *cert;
- OCTET_STRING_t *sid;
+ OCTET_STRING_t const *sid;
};
struct bgpsec_ski {
};
/* Callback method to fetch repository objects */
-typedef int (access_method_exec)(struct sia_uris *);
+typedef int (access_method_exec)(struct extension_uris *);
struct ad_metadata {
char const *name;
return 0;
}
-int
-certificate_validate_rfc6487(struct rpki_certificate *cert)
+/* Validates RFC 6487 compliance (except extensions) */
+static int
+validate_rfc6487(struct rpki_certificate *cert)
{
int error;
* skips unnecessary validations when using the PKCS7 API. Maybe the methods
* we're using have something similar.
*/
-int
-certificate_validate_signature(X509 *cert, ANY_t *signedData,
- SignatureValue_t *signature)
+static int
+validate_signature(X509 *cert, ANY_t *signedData,
+ SignatureValue_t const *signature)
{
static const uint8_t EXPLICIT_SET_OF_TAG = 0x31;
}
static X509 *
-certificate_load(char const *path)
+load_certificate(char const *path)
{
X509 *cert = NULL;
BIO *bio;
}
void
-rpki_certificate_init_ee(struct rpki_certificate *ee,
- struct rpki_certificate *parent, bool force_inherit)
+cer_init_ee(struct rpki_certificate *ee, struct rpki_certificate *parent,
+ bool force_inherit)
{
memset(ee, 0, sizeof(*ee));
ee->type = CERTYPE_EE;
}
void
-rpki_certificate_cleanup(struct rpki_certificate *cert)
+cer_cleanup(struct rpki_certificate *cert)
{
map_cleanup(&cert->map);
if (cert->x509 != NULL)
X509_free(cert->x509);
resources_destroy(cert->resources);
- sias_cleanup(&cert->sias);
+ exturis_cleanup(&cert->uris);
// XXX Recursive. Try refcounting the resources.
if (cert->parent)
- rpki_certificate_free(cert->parent);
+ cer_free(cert->parent);
rpp_cleanup(&cert->rpp);
}
void
-rpki_certificate_free(struct rpki_certificate *cert)
+cer_free(struct rpki_certificate *cert)
{
if (atomic_fetch_sub(&cert->refcount, 1) == 1) {
- rpki_certificate_cleanup(cert);
+ cer_cleanup(cert);
free(cert);
}
}
free(nu);
}
-int
-certificate_validate_chain(struct rpki_certificate *cert)
+/*
+ * Performs the basic (RFC 5280, presumably) chain validation.
+ * (Ignores the IP and AS extensions.)
+ */
+static int
+validate_chain(struct rpki_certificate *cert)
{
/* Reference: openbsd/src/usr.bin/openssl/verify.c */
}
static int
-__certificate_get_resources(struct rpki_certificate *cert,
+__convert_resources(struct rpki_certificate *cert,
int addr_nid, int asn_nid, int bad_addr_nid, int bad_asn_nid,
char const *policy_rfc, char const *bad_ext_rfc)
{
return 0;
}
-/* Copies the resources from @cert to @resources. */
-int
-certificate_get_resources(struct rpki_certificate *cert)
+/**
+ * Copies the resources from cert->x509 into cert->resources.
+ *
+ * Note: One reason why this is separate from the validate_extensions functions
+ * is because it needs to be handled after the policy has been extracted from
+ * the certificate policies extension, and handle_extensions() currently does
+ * not care about order. I don't know if you'll find other reasons if you choose
+ * to migrate it.
+ */
+static int
+convert_resources(struct rpki_certificate *cert)
{
switch (cert->policy) {
case RPKI_POLICY_RFC6484:
- return __certificate_get_resources(cert,
+ return __convert_resources(cert,
NID_sbgp_ipAddrBlock, NID_sbgp_autonomousSysNum,
nid_ipAddrBlocksv2(), nid_autonomousSysIdsv2(),
"6484", "8360");
case RPKI_POLICY_RFC8360:
- return __certificate_get_resources(cert,
+ return __convert_resources(cert,
nid_ipAddrBlocksv2(), nid_autonomousSysIdsv2(),
NID_sbgp_ipAddrBlock, NID_sbgp_autonomousSysNum,
"8360", "6484");
}
pr_crit("Unknown policy: %u", cert->policy);
+ return EINVAL;
}
static int
handle_rpkiManifest(struct uri const *uri, void *arg)
{
- struct sia_uris *uris = arg;
+ struct extension_uris *uris = arg;
char const *rm;
rm = uri_str(uri);
static int
handle_caRepository(struct uri const *uri, void *arg)
{
- struct sia_uris *uris = arg;
+ struct extension_uris *uris = arg;
char const *cr;
cr = uri_str(uri);
static int
handle_rpkiNotify(struct uri const *uri, void *arg)
{
- struct sia_uris *uris = arg;
+ struct extension_uris *uris = arg;
char const *rn;
rn = uri_str(uri);
static int
handle_signedObject(struct uri const *uri, void *arg)
{
- struct sia_uris *sias = arg;
+ struct extension_uris *sias = arg;
char const *so;
so = uri_str(uri);
{
ASN1_OCTET_STRING *ski = ext;
struct ski_arguments *args = arg;
- OCTET_STRING_t *sid;
+ OCTET_STRING_t const *sid;
int error;
error = validate_public_key_hash(args->cert, ski, "SKI");
handle_cdp(void *ext, void *arg)
{
STACK_OF(DIST_POINT) *crldp = ext;
- struct sia_uris *sias = arg;
+ struct extension_uris *sias = arg;
DIST_POINT *dp;
GENERAL_NAMES *names;
int i;
static int
handle_caIssuers(struct uri const *uri, void *arg)
{
- struct sia_uris *sias = arg;
+ struct extension_uris *sias = arg;
if (!uri_is_rsync(uri)) {
pr_val_debug("Ignoring non-rsync caIssuers '%s'.", uri_str(uri));
handle_sia_ca(void *ext, void *arg)
{
SIGNATURE_INFO_ACCESS *sia = ext;
- struct sia_uris *uris = arg;
+ struct extension_uris *uris = arg;
int error;
/* rsync */
return 0;
}
+/* rfc6487#section-4.8.7 */
+static int
+validate_aia(struct rpki_certificate *cert)
+{
+ if (!uri_equals(&cert->parent->map.url, &cert->uris.caIssuers))
+ return pr_val_err("Certificate's caIssuers (%s) does not match parent certificate's URL (%s).",
+ uri_str(&cert->parent->map.url),
+ uri_str(&cert->uris.caIssuers));
+
+ return 0;
+}
+
+static int
+validate_cdp(struct rpki_certificate *cer)
+{
+ struct uri *crl_url = &cer->parent->rpp.crl.map->url;
+
+ if (uri_str(&cer->uris.crldp) == NULL)
+ pr_crit("Certificate's CRL Distribution Point was not recorded.");
+ if (uri_str(crl_url) == NULL)
+ pr_crit("Manifest's CRL was not recorded.");
+
+ if (!uri_equals(&cer->uris.crldp, crl_url)) {
+ return pr_val_err("Certificate's CRL Distribution Point ('%s') does not match manifest's CRL ('%s').",
+ uri_str(&cer->uris.crldp), uri_str(crl_url));
+ }
+
+ return 0;
+}
+
/* Validates the certificate extensions, Trust Anchor style. */
static int
validate_ta_extensions(struct rpki_certificate *cert)
{ ext_ski(), true, handle_ski_ca, cert->x509 },
{ ext_aki(), false, handle_aki_ta, cert->x509 },
{ ext_ku(), true, handle_ku_ca, },
- { ext_sia(), true, handle_sia_ca, &cert->sias },
+ { ext_sia(), true, handle_sia_ca, &cert->uris },
{ ext_cp(), true, handle_cp, &cert->policy },
- /* These are handled by certificate_get_resources(). */
+ /* These are handled by convert_resources(). */
{ ext_ir(), false, },
{ ext_ar(), false, },
{ ext_ir2(), false, },
{ ext_ski(), true, handle_ski_ca, cert->x509 },
{ ext_aki(), true, handle_aki, cert->parent->x509 },
{ ext_ku(), true, handle_ku_ca, },
- { ext_cdp(), true, handle_cdp, &cert->sias },
- { ext_aia(), true, handle_aia, &cert->sias },
- { ext_sia(), true, handle_sia_ca, &cert->sias },
+ { ext_cdp(), true, handle_cdp, &cert->uris },
+ { ext_aia(), true, handle_aia, &cert->uris },
+ { ext_sia(), true, handle_sia_ca, &cert->uris },
{ ext_cp(), true, handle_cp, &cert->policy },
- /* These are handled by certificate_get_resources(). */
+ /* These are handled by convert_resources(). */
{ ext_ir(), false, },
{ ext_ar(), false, },
{ ext_ir2(), false, },
error = handle_extensions(handlers, X509_get0_extensions(cert->x509));
if (error)
return error;
- error = certificate_validate_aia(cert);
+ error = validate_aia(cert);
if (error)
return error;
- return validate_cdp(&cert->sias, &cert->parent->rpp.crl.map->url);
+ return validate_cdp(cert);
}
-int
-certificate_validate_extensions_ee(struct rpki_certificate *cert,
- OCTET_STRING_t *sid)
+/*
+ * Validates the certificate extensions, End-Entity style.
+ *
+ * Also initializes the second argument with the references found in the
+ * extensions.
+ */
+static int
+validate_extensions_ee(struct rpki_certificate *cert, OCTET_STRING_t const *sid)
{
struct ski_arguments ski_args;
struct extension_handler handlers[] = {
{ ext_ski(), true, handle_ski_ee, &ski_args },
{ ext_aki(), true, handle_aki, cert->parent->x509 },
{ ext_ku(), true, handle_ku_ee, },
- { ext_cdp(), true, handle_cdp, &cert->sias },
- { ext_aia(), true, handle_aia, &cert->sias },
- { ext_sia(), true, handle_sia_ee, &cert->sias },
+ { ext_cdp(), true, handle_cdp, &cert->uris },
+ { ext_aia(), true, handle_aia, &cert->uris },
+ { ext_sia(), true, handle_sia_ee, &cert->uris },
{ ext_cp(), true, handle_cp, &cert->policy },
{ ext_ir(), false, },
{ ext_ar(), false, },
return handle_extensions(handlers, X509_get0_extensions(cert->x509));
}
-int
-certificate_validate_extensions_bgpsec(void)
-{
- return 0; /* TODO (#58) */
-}
-
static bool
has_bgpsec_router_eku(X509 *cert)
{
* certificate.
*/
static enum cert_type
-get_certificate_type(struct rpki_certificate *cert)
+get_cert_type(struct rpki_certificate *cert)
{
if (cert->parent == NULL)
return CERTYPE_TA;
return CERTYPE_UNKNOWN;
}
-int
-certificate_validate_aia(struct rpki_certificate *cert)
-{
- if (!uri_equals(&cert->parent->map.url, &cert->sias.caIssuers))
- return pr_val_err("Certificate's caIssuers (%s) does not match parent certificate's URL (%s).",
- uri_str(&cert->parent->map.url),
- uri_str(&cert->sias.caIssuers));
-
- return 0;
-}
-
static unsigned int
chain_length(struct rpki_certificate *cert)
{
cert->resources = resources_create(cert->policy, false);
- error = certificate_get_resources(cert);
+ error = convert_resources(cert);
if (error)
return error;
* "The INR extension(s) of this TA MUST contain a non-empty set of
* number resources."
* The "It MUST NOT use the "inherit" form of the INR extension(s)"
- * part is already handled in certificate_get_resources().
+ * part is already handled in convert_resources().
*/
if (cert->type == CERTYPE_TA && resources_empty(cert->resources))
return pr_val_err("Trust Anchor certificate does not define any number resources.");
}
static int
-certificate_validate(struct rpki_certificate *cert)
+validate_certificate(struct rpki_certificate *cert)
{
int error;
fnstack_push_map(&cert->map);
- cert->x509 = certificate_load(cert->map.path);
+ cert->x509 = load_certificate(cert->map.path);
if (!cert->x509) {
error = EINVAL;
goto end;
}
- cert->type = get_certificate_type(cert);
+ cert->type = get_cert_type(cert);
- error = certificate_validate_chain(cert);
+ error = validate_chain(cert);
if (error)
goto end;
goto end;
}
- error = certificate_validate_rfc6487(cert);
+ error = validate_rfc6487(cert);
if (error)
goto end;
}
validation_verdict
-certificate_traverse(struct rpki_certificate *ca)
+cer_traverse(struct rpki_certificate *ca)
{
struct cache_cage *cage;
struct cache_mapping mft;
validation_verdict vv;
if (!ca->x509) {
- if (certificate_validate(ca) != 0)
+ if (validate_certificate(ca) != 0)
return VV_FAIL;
if (ca->type != CERTYPE_TA && ca->type != CERTYPE_CA)
return VV_CONTINUE;
} /* else "we already did this, and returned VV_BUSY" */
- vv = cache_refresh_by_sias(&ca->sias, &cage);
+ vv = cache_refresh_by_uris(&ca->uris, &cage);
if (vv == VV_BUSY)
return VV_BUSY;
if (vv == VV_FAIL) {
pr_val_err("caRepository '%s' could not be refreshed, "
"and there is no fallback in the cache. "
"I'm going to have to skip it.",
- uri_str(&ca->sias.caRepository));
+ uri_str(&ca->uris.caRepository));
return VV_FAIL;
}
- mft.url = ca->sias.rpkiManifest;
+ mft.url = ca->uris.rpkiManifest;
retry: mft.path = (char *)cage_map_file(cage, &mft.url); /* Will not edit */
if (!mft.path) {
if (cage_disable_refresh(cage))
goto retry;
pr_val_err("caRepository '%s' is missing a manifest.",
- uri_str(&ca->sias.caRepository));
+ uri_str(&ca->uris.caRepository));
vv = VV_FAIL;
goto end;
}
if (queued > 0)
task_wakeup();
- cache_commit_rpp(cage_rpkiNotify(cage), &ca->sias.caRepository,
+ cache_commit_rpp(cage_rpkiNotify(cage), &ca->uris.caRepository,
&ca->rpp);
end: free(cage);
return vv;
}
+
+static int
+validate_signedObject(struct extension_uris const *exts, struct uri const *url)
+{
+ if (uri_str(&exts->signedObject) == NULL)
+ pr_crit("Certificate's signedObject was not recorded.");
+
+ if (!uri_equals(&exts->signedObject, url))
+ return pr_val_err("Certificate's signedObject ('%s') does not match the URI of its own signed object (%s).",
+ uri_str(&exts->signedObject), uri_str(url));
+
+ return 0;
+}
+
+/**
+ * Ensures the extension URIs of @ee match the actual URIs.
+ *
+ * @so_url: URL of the signed object that contains the EE certificate.
+ */
+static int
+validate_ee_refs(struct rpki_certificate *ee, struct signed_object *so)
+{
+ int error;
+
+ error = validate_cdp(ee);
+ if (error)
+ return error;
+
+ return validate_signedObject(&ee->uris, &so->map->url);
+}
+
+int
+cer_validate_ee(struct rpki_certificate *ee, struct signed_object *so)
+{
+ int error;
+
+ x509_name_pr_clutter("Issuer", X509_get_issuer_name(ee->x509));
+
+ error = validate_chain(ee);
+ if (error)
+ return error;
+ error = validate_rfc6487(ee);
+ if (error)
+ return error;
+ error = validate_extensions_ee(ee, so->sid);
+ if (error)
+ return error;
+ error = validate_aia(ee);
+ if (error)
+ return error;
+ error = validate_signature(ee->x509, &so->cinfo->content, so->signature);
+ if (error)
+ return error;
+
+ resources_set_policy(ee->resources, ee->policy);
+ error = convert_resources(ee);
+ if (error)
+ return error;
+
+ return validate_ee_refs(ee, so);
+}
#include "asn1/asn1c/ANY.h"
#include "asn1/asn1c/SignatureValue.h"
#include "cache.h"
-#include "certificate_refs.h"
#include "resource.h"
#include "types/rpp.h"
X509 *x509; /* Initializes after dequeue */
enum cert_type type;
- enum rpki_policy policy; /* XXX seems redundant */
+ enum rpki_policy policy;
struct resources *resources;
- struct sia_uris sias;
+ struct extension_uris uris;
struct tal *tal; /* Only needed by TAs for now */
struct rpki_certificate *parent;
atomic_uint refcount;
};
-void rpki_certificate_init_ee(struct rpki_certificate *,
- struct rpki_certificate *, bool);
-void rpki_certificate_cleanup(struct rpki_certificate *);
-void rpki_certificate_free(struct rpki_certificate *);
+void cer_init_ee(struct rpki_certificate *, struct rpki_certificate *, bool);
+void cer_cleanup(struct rpki_certificate *);
+void cer_free(struct rpki_certificate *);
-/**
- * Performs the basic (RFC 5280, presumably) chain validation.
- * (Ignores the IP and AS extensions.)
- */
-int certificate_validate_chain(struct rpki_certificate *);
-/**
- * Validates RFC 6487 compliance.
- * (Except extensions.)
- */
-int certificate_validate_rfc6487(struct rpki_certificate *);
+validation_verdict cer_traverse(struct rpki_certificate *);
-int certificate_validate_signature(X509 *, ANY_t *coded, SignatureValue_t *);
-
-/**
- * Extracts the resources from cert->x509 into cert->resources.
- *
- * Note: One reason why this is separate from the validate_extensions functions
- * is because it needs to be handled after the policy has been extracted from
- * the certificate policies extension, and handle_extensions() currently does
- * not care about order. I don't know if you'll find other reasons if you choose
- * to migrate it.
- */
-int certificate_get_resources(struct rpki_certificate *cert);
-
-/**
- * Validates the certificate extensions, End-Entity style.
- *
- * Also initializes the second argument with the references found in the
- * extensions.
- */
-int certificate_validate_extensions_ee(struct rpki_certificate *,
- OCTET_STRING_t *);
-int certificate_validate_extensions_bgpsec(void);
-
-/*
- * Specific validation of AIA (rfc6487#section-4.8.7) extension, public so that
- * CAs and EEs can access it.
- */
-int certificate_validate_aia(struct rpki_certificate *);
-
-validation_verdict certificate_traverse(struct rpki_certificate *);
+struct signed_object;
+int cer_validate_ee(struct rpki_certificate *, struct signed_object *);
#endif /* SRC_OBJECT_CERTIFICATE_H_ */
#include "thread_var.h"
static int
-handle_vcard(struct signed_object *sobj)
+handle_vcard(struct signed_object *so)
{
return handle_ghostbusters_vcard(
- sobj->sdata->encapContentInfo.eContent
+ so->sdata->encapContentInfo.eContent
);
}
{
static OID oid = OID_GHOSTBUSTERS;
struct oid_arcs arcs = OID2ARCS("ghostbusters", oid);
- struct signed_object sobj;
+ struct signed_object so;
struct rpki_certificate ee;
int error;
fnstack_push_map(map);
/* Decode */
- error = signed_object_decode(&sobj, map->path);
+ error = signed_object_decode(&so, map);
if (error)
goto end1;
/* Prepare validation arguments */
- rpki_certificate_init_ee(&ee, parent, true);
+ cer_init_ee(&ee, parent, true);
/* Validate everything */
- error = signed_object_validate(&sobj, &arcs, &ee);
+ error = signed_object_validate(&so, &ee, &arcs);
if (error)
goto end3;
- error = handle_vcard(&sobj);
- if (error)
- goto end3;
- error = refs_validate_ee(&ee.sias, &parent->rpp.crl.map->url, &map->url);
+ error = handle_vcard(&so);
-end3: rpki_certificate_cleanup(&ee);
- signed_object_cleanup(&sobj);
+end3: cer_cleanup(&ee);
+ signed_object_cleanup(&so);
end1: fnstack_pop();
return error;
}
#include "types/uri.h"
static int
-decode_manifest(struct signed_object *sobj, struct Manifest **result)
+decode_manifest(struct signed_object *so, struct Manifest **result)
{
return asn1_decode_octet_string(
- sobj->sdata->encapContentInfo.eContent,
+ so->sdata->encapContentInfo.eContent,
&asn_DEF_Manifest,
(void **) result,
true
* I'm going with the signed object hash function, since it appears to
* be the closest match.
*/
- error = validate_cms_hashing_algorithm_oid(&mft->fileHashAlg,
+ error = validate_cms_hash_algorithm_oid(&mft->fileHashAlg,
"manifest file");
if (error)
return error;
{
static OID oid = OID_MANIFEST;
struct oid_arcs arcs = OID2ARCS("manifest", oid);
- struct signed_object sobj;
+ struct signed_object so;
struct rpki_certificate ee;
struct Manifest *mft;
int error;
fnstack_push_map(map);
/* Decode */
- error = signed_object_decode(&sobj, map->path);
+ error = signed_object_decode(&so, map);
if (error)
goto end1;
- error = decode_manifest(&sobj, &mft);
+ error = decode_manifest(&so, &mft);
if (error)
goto end2;
goto end3;
/* Prepare validation arguments */
- rpki_certificate_init_ee(&ee, parent, false);
+ cer_init_ee(&ee, parent, false);
/* Validate everything */
- error = signed_object_validate(&sobj, &arcs, &ee);
+ error = signed_object_validate(&so, &ee, &arcs);
if (error)
goto end5;
error = validate_manifest(mft, cage, &parent->rpp.mft);
- if (error)
- goto end5;
- error = refs_validate_ee(&ee.sias, &parent->rpp.crl.map->url, &map->url);
-end5: rpki_certificate_cleanup(&ee);
+end5: cer_cleanup(&ee);
if (error)
rpp_cleanup(&parent->rpp);
end3: ASN_STRUCT_FREE(asn_DEF_Manifest, mft);
-end2: signed_object_cleanup(&sobj);
+end2: signed_object_cleanup(&so);
end1: fnstack_pop();
return error;
}
#include "validation_handler.h"
static int
-decode_roa(struct signed_object *sobj, struct RouteOriginAttestation **result)
+decode_roa(struct signed_object *so, struct RouteOriginAttestation **result)
{
return asn1_decode_octet_string(
- sobj->sdata->encapContentInfo.eContent,
+ so->sdata->encapContentInfo.eContent,
&asn_DEF_RouteOriginAttestation,
(void **) result,
true
{
static OID oid = OID_ROA;
struct oid_arcs arcs = OID2ARCS("roa", oid);
- struct signed_object sobj;
+ struct signed_object so;
struct rpki_certificate ee;
struct RouteOriginAttestation *roa;
int error;
fnstack_push_map(map);
/* Decode */
- error = signed_object_decode(&sobj, map->path);
+ error = signed_object_decode(&so, map);
if (error)
goto end1;
- error = decode_roa(&sobj, &roa);
+ error = decode_roa(&so, &roa);
if (error)
goto end2;
/* Prepare validation arguments */
- rpki_certificate_init_ee(&ee, parent, false);
+ cer_init_ee(&ee, parent, false);
/* Validate and handle everything */
- error = signed_object_validate(&sobj, &arcs, &ee);
+ error = signed_object_validate(&so, &ee, &arcs);
if (error)
goto end4;
error = __handle_roa(roa, ee.resources);
- if (error)
- goto end4;
- error = refs_validate_ee(&ee.sias, &parent->rpp.crl.map->url, &map->url);
-end4: rpki_certificate_cleanup(&ee);
+end4: cer_cleanup(&ee);
ASN_STRUCT_FREE(asn_DEF_RouteOriginAttestation, roa);
-end2: signed_object_cleanup(&sobj);
+end2: signed_object_cleanup(&so);
end1: fnstack_pop();
return error;
}
#include "object/signed_object.h"
#include "asn1/content_info.h"
+#include "asn1/signed_data.h"
#include "log.h"
int
-signed_object_decode(struct signed_object *sobj, char const *path)
+signed_object_decode(struct signed_object *so, struct cache_mapping const *map)
{
int error;
- error = content_info_load(path, &sobj->cinfo);
+ so->map = map;
+
+ error = content_info_load(map->path, &so->cinfo);
if (error)
return error;
- error = signed_data_decode(&sobj->cinfo->content, &sobj->sdata);
+ error = signed_data_decode(&so->cinfo->content, &so->sdata);
if (error) {
- content_info_free(sobj->cinfo);
+ content_info_free(so->cinfo);
return error;
}
}
int
-signed_object_validate(struct signed_object *sobj, struct oid_arcs const *oid,
- struct rpki_certificate *ee)
+signed_object_validate(struct signed_object *so, struct rpki_certificate *ee,
+ struct oid_arcs const *oid)
{
int error;
/* rfc6482#section-2 */
/* rfc6486#section-4.1 */
/* rfc6486#section-4.4.1 */
- error = validate_eContentType(sobj->sdata, oid);
+ error = validate_eContentType(so->sdata, oid);
if (error)
return error;
/* rfc6482#section-2 */
/* rfc6486#section-4.3 */
- error = validate_content_type(sobj->sdata, oid);
+ error = validate_content_type(so->sdata, oid);
if (error)
return error;
- return signed_data_validate(&sobj->cinfo->content, sobj->sdata, ee);
+ return signed_data_validate(so, ee);
}
void
-signed_object_cleanup(struct signed_object *sobj)
+signed_object_cleanup(struct signed_object *so)
{
- content_info_free(sobj->cinfo);
- ASN_STRUCT_FREE(asn_DEF_SignedData, sobj->sdata);
+ content_info_free(so->cinfo);
+ ASN_STRUCT_FREE(asn_DEF_SignedData, so->sdata);
}
#define SRC_OBJECT_SIGNED_OBJECT_H_
#include "asn1/asn1c/ContentInfo.h"
+#include "asn1/asn1c/SignedData.h"
#include "asn1/oid.h"
-#include "asn1/signed_data.h"
+#include "types/map.h"
struct signed_object {
+ struct cache_mapping const *map;
struct ContentInfo *cinfo;
struct SignedData *sdata;
+ OCTET_STRING_t const *sid;
+ SignatureValue_t const *signature;
};
-int signed_object_decode(struct signed_object *, char const *);
-int signed_object_validate(struct signed_object *, struct oid_arcs const *,
- struct rpki_certificate *);
+int signed_object_decode(struct signed_object *, struct cache_mapping const *);
+
+struct rpki_certificate;
+int signed_object_validate(struct signed_object *, struct rpki_certificate *,
+ struct oid_arcs const *);
+
void signed_object_cleanup(struct signed_object *);
#endif /* SRC_OBJECT_SIGNED_OBJECT_H_ */
ta->tal = tal;
atomic_init(&ta->refcount, 1);
- vv = certificate_traverse(ta);
+ vv = cer_traverse(ta);
- rpki_certificate_free(ta);
+ cer_free(ta);
return vv;
}
while ((task = task_dequeue(task)) != NULL) {
switch (task->type) {
case VTT_RPP:
- if (certificate_traverse(task->u.ca) == VV_BUSY) {
+ if (cer_traverse(task->u.ca) == VV_BUSY) {
task_requeue_dormant(task);
task = NULL;
}
{
switch (task->type) {
case VTT_RPP:
- rpki_certificate_free(task->u.ca);
+ cer_free(task->u.ca);
break;
case VTT_TAL:
free(task->u.tal);
#include "types/uri.h"
-// XXX document this better
struct cache_mapping {
- struct uri url; /* Normalized */
- char *path; /* Normalized */
+ /* Global identifier of a file */
+ struct uri url;
+ /* Cache location where the file was (or will be) downloaded */
+ char *path;
};
char const *map_val_get_printable(struct cache_mapping const *);
run_dl_rsync(char *caRepository, validation_verdict vv,
unsigned int expected_calls)
{
- struct sia_uris sias = { 0 };
+ struct extension_uris sias = { 0 };
struct cache_cage *cage;
ck_assert_ptr_eq(NULL, uri_init(&sias.caRepository, caRepository));
rsync_counter = 0;
https_counter = 0;
printf("---- Downloading... ----\n");
- ck_assert_str_eq(vv, cache_refresh_by_sias(&sias, &cage));
+ ck_assert_str_eq(vv, cache_refresh_by_uris(&sias, &cage));
printf("---- Downloaded. ----\n");
ck_assert_uint_eq(expected_calls, rsync_counter);
ck_assert_uint_eq(0, https_counter);
char *FILE_RRDP_PATH = "rrdp/0/0";
char *FILE_RSYNC_PATH = "rsync/0/rpp3/a.cer";
- struct sia_uris sias = { 0 };
+ struct extension_uris sias = { 0 };
struct uri file_url;
struct cache_cage *cage;
struct rpp rpp = { 0 };
print_tree();
ck_assert_ptr_eq(NULL, uri_init(&sias.rpkiNotify, RPKI_NOTIFY));
ck_assert_ptr_eq(NULL, uri_init(&sias.caRepository, CA_REPOSITORY));
- ck_assert_str_eq(VV_CONTINUE, cache_refresh_by_sias(&sias, &cage));
+ ck_assert_str_eq(VV_CONTINUE, cache_refresh_by_uris(&sias, &cage));
ck_assert_str_eq(RPKI_NOTIFY, uri_str(&cage->rpkiNotify));
ck_assert_str_eq(FILE_RRDP_PATH, cage_map_file(cage, &file_url));
ck_assert_int_eq(false, cage_disable_refresh(cage));
print_tree();
uri_cleanup(&sias.rpkiNotify);
- ck_assert_str_eq(VV_BUSY, cache_refresh_by_sias(&sias, &cage));
+ ck_assert_str_eq(VV_BUSY, cache_refresh_by_uris(&sias, &cage));
finish_rsync();
- ck_assert_str_eq(VV_CONTINUE, cache_refresh_by_sias(&sias, &cage));
+ ck_assert_str_eq(VV_CONTINUE, cache_refresh_by_uris(&sias, &cage));
ck_assert_ptr_eq(NULL, uri_str(&cage->rpkiNotify));
ck_assert_str_eq(FILE_RSYNC_PATH, cage_map_file(cage, &file_url));
printf("4. Redo both CAs, check the fallbacks too\n");
print_tree();
- ck_assert_str_eq(VV_CONTINUE, cache_refresh_by_sias(&sias, &cage));
+ ck_assert_str_eq(VV_CONTINUE, cache_refresh_by_uris(&sias, &cage));
ck_assert_ptr_eq(NULL, uri_str(&cage->rpkiNotify));
ck_assert_str_eq(FILE_RSYNC_PATH, cage_map_file(cage, &file_url));
ck_assert_int_eq(true, cage_disable_refresh(cage));
ck_assert_str_eq("fallback/1/0", cage_map_file(cage, &file_url));
ck_assert_ptr_eq(NULL, uri_init(&sias.rpkiNotify, RPKI_NOTIFY));
- ck_assert_str_eq(VV_CONTINUE, cache_refresh_by_sias(&sias, &cage));
+ ck_assert_str_eq(VV_CONTINUE, cache_refresh_by_uris(&sias, &cage));
ck_assert_str_eq(RPKI_NOTIFY, uri_str(&cage->rpkiNotify));
ck_assert_str_eq(FILE_RRDP_PATH, cage_map_file(cage, &file_url));
ck_assert_int_eq(true, cage_disable_refresh(cage));
#include "types/uri.c"
void
-rpki_certificate_free(struct rpki_certificate *cert)
+cer_free(struct rpki_certificate *cert)
{
if (atomic_fetch_sub(&cert->refcount, 1) == 1) {
map_cleanup(&cert->map);