It does pretty much everything, but the CA lookup is very dumb.
It performs a full tree traversal.
Also, it's not documented yet.
Recommended usage:
fort --tal tal/ripe-ncc.tal \
--local-repository /path/to/cache \
--rsc /path/to/checklist.sig
Awaiting feedback.
fort_SOURCES += object/name.h object/name.c
fort_SOURCES += object/roa.h object/roa.c
fort_SOURCES += object/router_key.c object/router_key.h
+fort_SOURCES += object/rsc.h object/rsc.c
fort_SOURCES += object/signed_object.h object/signed_object.c
fort_SOURCES += object/tal.h object/tal.c
fort_SOURCES += object/vcard.h object/vcard.c
--- /dev/null
+/*
+ * Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
+ * From ASN.1 module "RpkiSignedChecklist-2021"
+ * found in "draft-ietf-sidrops-rpki-rsc.asn1"
+ * `asn1c -Werror -fcompound-names -fwide-types -D asn1/asn1c -no-gen-PER -no-gen-example`
+ */
+
+#include "AsList.h"
+
+static asn_oer_constraints_t asn_OER_type_AsList_constr_1 CC_NOTUSED = {
+ { 0, 0 },
+ -1 /* (SIZE(1..MAX)) */};
+asn_TYPE_member_t asn_MBR_AsList_1[] = {
+ { ATF_POINTER, 0, 0,
+ -1 /* Ambiguous tag (CHOICE?) */,
+ 0,
+ &asn_DEF_ASIdOrRange,
+ 0,
+ { 0, 0, 0 },
+ 0, 0, /* No default value */
+ ""
+ },
+};
+static const ber_tlv_tag_t asn_DEF_AsList_tags_1[] = {
+ (ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+asn_SET_OF_specifics_t asn_SPC_AsList_specs_1 = {
+ sizeof(struct AsList),
+ offsetof(struct AsList, _asn_ctx),
+ 2, /* XER encoding is XMLValueList */
+};
+asn_TYPE_descriptor_t asn_DEF_AsList = {
+ "AsList",
+ "AsList",
+ &asn_OP_SEQUENCE_OF,
+ asn_DEF_AsList_tags_1,
+ sizeof(asn_DEF_AsList_tags_1)
+ /sizeof(asn_DEF_AsList_tags_1[0]), /* 1 */
+ asn_DEF_AsList_tags_1, /* Same as above */
+ sizeof(asn_DEF_AsList_tags_1)
+ /sizeof(asn_DEF_AsList_tags_1[0]), /* 1 */
+ { &asn_OER_type_AsList_constr_1, 0, SEQUENCE_OF_constraint },
+ asn_MBR_AsList_1,
+ 1, /* Single element */
+ &asn_SPC_AsList_specs_1 /* Additional specs */
+};
+
--- /dev/null
+/*
+ * Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
+ * From ASN.1 module "RpkiSignedChecklist-2021"
+ * found in "draft-ietf-sidrops-rpki-rsc.asn1"
+ * `asn1c -Werror -fcompound-names -fwide-types -D asn1/asn1c -no-gen-PER -no-gen-example`
+ */
+
+#ifndef _AsList_H_
+#define _AsList_H_
+
+
+#include "asn1/asn1c/asn_application.h"
+
+/* Including external dependencies */
+#include "asn1/asn1c/asn_SEQUENCE_OF.h"
+#include "asn1/asn1c/constr_SEQUENCE_OF.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Forward declarations */
+struct ASIdOrRange;
+
+/* AsList */
+typedef struct AsList {
+ A_SEQUENCE_OF(struct ASIdOrRange) list;
+
+ /* Context for parsing across buffer boundaries */
+ asn_struct_ctx_t _asn_ctx;
+} AsList_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_AsList;
+extern asn_SET_OF_specifics_t asn_SPC_AsList_specs_1;
+extern asn_TYPE_member_t asn_MBR_AsList_1[1];
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Referred external types */
+#include "ASIdOrRange.h"
+
+#endif /* _AsList_H_ */
+#include "asn1/asn1c/asn_internal.h"
--- /dev/null
+/*
+ * Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
+ * From ASN.1 module "RpkiSignedChecklist-2021"
+ * found in "draft-ietf-sidrops-rpki-rsc.asn1"
+ * `asn1c -Werror -fcompound-names -fwide-types -D asn1/asn1c -no-gen-PER -no-gen-example`
+ */
+
+#include "FileNameAndHash.h"
+
+asn_TYPE_member_t asn_MBR_FileNameAndHash_1[] = {
+ { ATF_POINTER, 1, offsetof(struct FileNameAndHash, fileName),
+ (ASN_TAG_CLASS_UNIVERSAL | (22 << 2)),
+ 0,
+ &asn_DEF_IA5String,
+ 0,
+ { 0, 0, 0 },
+ 0, 0, /* No default value */
+ "fileName"
+ },
+ { ATF_NOFLAGS, 0, offsetof(struct FileNameAndHash, hash),
+ (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)),
+ 0,
+ &asn_DEF_OCTET_STRING,
+ 0,
+ { 0, 0, 0 },
+ 0, 0, /* No default value */
+ "hash"
+ },
+};
+static const int asn_MAP_FileNameAndHash_oms_1[] = { 0 };
+static const ber_tlv_tag_t asn_DEF_FileNameAndHash_tags_1[] = {
+ (ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+static const asn_TYPE_tag2member_t asn_MAP_FileNameAndHash_tag2el_1[] = {
+ { (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)), 1, 0, 0 }, /* hash */
+ { (ASN_TAG_CLASS_UNIVERSAL | (22 << 2)), 0, 0, 0 } /* fileName */
+};
+asn_SEQUENCE_specifics_t asn_SPC_FileNameAndHash_specs_1 = {
+ sizeof(struct FileNameAndHash),
+ offsetof(struct FileNameAndHash, _asn_ctx),
+ asn_MAP_FileNameAndHash_tag2el_1,
+ 2, /* Count of tags in the map */
+ asn_MAP_FileNameAndHash_oms_1, /* Optional members */
+ 1, 0, /* Root/Additions */
+ -1, /* First extension addition */
+};
+asn_TYPE_descriptor_t asn_DEF_FileNameAndHash = {
+ "FileNameAndHash",
+ "FileNameAndHash",
+ &asn_OP_SEQUENCE,
+ asn_DEF_FileNameAndHash_tags_1,
+ sizeof(asn_DEF_FileNameAndHash_tags_1)
+ /sizeof(asn_DEF_FileNameAndHash_tags_1[0]), /* 1 */
+ asn_DEF_FileNameAndHash_tags_1, /* Same as above */
+ sizeof(asn_DEF_FileNameAndHash_tags_1)
+ /sizeof(asn_DEF_FileNameAndHash_tags_1[0]), /* 1 */
+ { 0, 0, SEQUENCE_constraint },
+ asn_MBR_FileNameAndHash_1,
+ 2, /* Elements count */
+ &asn_SPC_FileNameAndHash_specs_1 /* Additional specs */
+};
+
--- /dev/null
+/*
+ * Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
+ * From ASN.1 module "RpkiSignedChecklist-2021"
+ * found in "draft-ietf-sidrops-rpki-rsc.asn1"
+ * `asn1c -Werror -fcompound-names -fwide-types -D asn1/asn1c -no-gen-PER -no-gen-example`
+ */
+
+#ifndef _FileNameAndHash_H_
+#define _FileNameAndHash_H_
+
+
+#include "asn1/asn1c/asn_application.h"
+
+/* Including external dependencies */
+#include "asn1/asn1c/IA5String.h"
+#include "asn1/asn1c/OCTET_STRING.h"
+#include "asn1/asn1c/constr_SEQUENCE.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* FileNameAndHash */
+typedef struct FileNameAndHash {
+ IA5String_t *fileName /* OPTIONAL */;
+ OCTET_STRING_t hash;
+
+ /* Context for parsing across buffer boundaries */
+ asn_struct_ctx_t _asn_ctx;
+} FileNameAndHash_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_FileNameAndHash;
+extern asn_SEQUENCE_specifics_t asn_SPC_FileNameAndHash_specs_1;
+extern asn_TYPE_member_t asn_MBR_FileNameAndHash_1[2];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FileNameAndHash_H_ */
+#include "asn1/asn1c/asn_internal.h"
--- /dev/null
+/*
+ * Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
+ * From ASN.1 module "RpkiSignedChecklist-2021"
+ * found in "draft-ietf-sidrops-rpki-rsc.asn1"
+ * `asn1c -Werror -fcompound-names -fwide-types -D asn1/asn1c -no-gen-PER -no-gen-example`
+ */
+
+#include "IPAddressFamilyItem.h"
+
+static int
+memb_addressFamily_constraint_1(const asn_TYPE_descriptor_t *td, const void *sptr,
+ asn_app_constraint_failed_f *ctfailcb, void *app_key) {
+ const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
+ size_t size;
+
+ if(!sptr) {
+ ASN__CTFAIL(app_key, td, sptr,
+ "%s: value not given (%s:%d)",
+ td->name, __FILE__, __LINE__);
+ return -1;
+ }
+
+ size = st->size;
+
+ if((size >= 2 && size <= 3)) {
+ /* Constraint check succeeded */
+ return 0;
+ } else {
+ ASN__CTFAIL(app_key, td, sptr,
+ "%s: constraint failed (%s:%d)",
+ td->name, __FILE__, __LINE__);
+ return -1;
+ }
+}
+
+static asn_oer_constraints_t asn_OER_memb_addressFamily_constr_2 CC_NOTUSED = {
+ { 0, 0 },
+ -1 /* (SIZE(2..3)) */};
+asn_TYPE_member_t asn_MBR_IPAddressFamilyItem_1[] = {
+ { ATF_NOFLAGS, 0, offsetof(struct IPAddressFamilyItem, addressFamily),
+ (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)),
+ 0,
+ &asn_DEF_OCTET_STRING,
+ 0,
+ { &asn_OER_memb_addressFamily_constr_2, 0, memb_addressFamily_constraint_1 },
+ 0, 0, /* No default value */
+ "addressFamily"
+ },
+ { ATF_NOFLAGS, 0, offsetof(struct IPAddressFamilyItem, iPAddressOrRange),
+ -1 /* Ambiguous tag (CHOICE?) */,
+ 0,
+ &asn_DEF_IPAddressOrRange,
+ 0,
+ { 0, 0, 0 },
+ 0, 0, /* No default value */
+ "iPAddressOrRange"
+ },
+};
+static const ber_tlv_tag_t asn_DEF_IPAddressFamilyItem_tags_1[] = {
+ (ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+static const asn_TYPE_tag2member_t asn_MAP_IPAddressFamilyItem_tag2el_1[] = {
+ { (ASN_TAG_CLASS_UNIVERSAL | (3 << 2)), 1, 0, 0 }, /* addressPrefix */
+ { (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)), 0, 0, 0 }, /* addressFamily */
+ { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 1, 0, 0 } /* addressRange */
+};
+asn_SEQUENCE_specifics_t asn_SPC_IPAddressFamilyItem_specs_1 = {
+ sizeof(struct IPAddressFamilyItem),
+ offsetof(struct IPAddressFamilyItem, _asn_ctx),
+ asn_MAP_IPAddressFamilyItem_tag2el_1,
+ 3, /* Count of tags in the map */
+ 0, 0, 0, /* Optional elements (not needed) */
+ -1, /* First extension addition */
+};
+asn_TYPE_descriptor_t asn_DEF_IPAddressFamilyItem = {
+ "IPAddressFamilyItem",
+ "IPAddressFamilyItem",
+ &asn_OP_SEQUENCE,
+ asn_DEF_IPAddressFamilyItem_tags_1,
+ sizeof(asn_DEF_IPAddressFamilyItem_tags_1)
+ /sizeof(asn_DEF_IPAddressFamilyItem_tags_1[0]), /* 1 */
+ asn_DEF_IPAddressFamilyItem_tags_1, /* Same as above */
+ sizeof(asn_DEF_IPAddressFamilyItem_tags_1)
+ /sizeof(asn_DEF_IPAddressFamilyItem_tags_1[0]), /* 1 */
+ { 0, 0, SEQUENCE_constraint },
+ asn_MBR_IPAddressFamilyItem_1,
+ 2, /* Elements count */
+ &asn_SPC_IPAddressFamilyItem_specs_1 /* Additional specs */
+};
+
--- /dev/null
+/*
+ * Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
+ * From ASN.1 module "RpkiSignedChecklist-2021"
+ * found in "draft-ietf-sidrops-rpki-rsc.asn1"
+ * `asn1c -Werror -fcompound-names -fwide-types -D asn1/asn1c -no-gen-PER -no-gen-example`
+ */
+
+#ifndef _IPAddressFamilyItem_H_
+#define _IPAddressFamilyItem_H_
+
+
+#include "asn1/asn1c/asn_application.h"
+
+/* Including external dependencies */
+#include "asn1/asn1c/OCTET_STRING.h"
+#include "IPAddressOrRange.h"
+#include "asn1/asn1c/constr_SEQUENCE.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* IPAddressFamilyItem */
+typedef struct IPAddressFamilyItem {
+ OCTET_STRING_t addressFamily;
+ IPAddressOrRange_t iPAddressOrRange;
+
+ /* Context for parsing across buffer boundaries */
+ asn_struct_ctx_t _asn_ctx;
+} IPAddressFamilyItem_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_IPAddressFamilyItem;
+extern asn_SEQUENCE_specifics_t asn_SPC_IPAddressFamilyItem_specs_1;
+extern asn_TYPE_member_t asn_MBR_IPAddressFamilyItem_1[2];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _IPAddressFamilyItem_H_ */
+#include "asn1/asn1c/asn_internal.h"
--- /dev/null
+/*
+ * Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
+ * From ASN.1 module "RpkiSignedChecklist-2021"
+ * found in "draft-ietf-sidrops-rpki-rsc.asn1"
+ * `asn1c -Werror -fcompound-names -fwide-types -D asn1/asn1c -no-gen-PER -no-gen-example`
+ */
+
+#include "IPList.h"
+
+static asn_oer_constraints_t asn_OER_type_IPList_constr_1 CC_NOTUSED = {
+ { 0, 0 },
+ -1 /* (SIZE(1..MAX)) */};
+asn_TYPE_member_t asn_MBR_IPList_1[] = {
+ { ATF_POINTER, 0, 0,
+ (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
+ 0,
+ &asn_DEF_IPAddressFamilyItem,
+ 0,
+ { 0, 0, 0 },
+ 0, 0, /* No default value */
+ ""
+ },
+};
+static const ber_tlv_tag_t asn_DEF_IPList_tags_1[] = {
+ (ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+asn_SET_OF_specifics_t asn_SPC_IPList_specs_1 = {
+ sizeof(struct IPList),
+ offsetof(struct IPList, _asn_ctx),
+ 0, /* XER encoding is XMLDelimitedItemList */
+};
+asn_TYPE_descriptor_t asn_DEF_IPList = {
+ "IPList",
+ "IPList",
+ &asn_OP_SEQUENCE_OF,
+ asn_DEF_IPList_tags_1,
+ sizeof(asn_DEF_IPList_tags_1)
+ /sizeof(asn_DEF_IPList_tags_1[0]), /* 1 */
+ asn_DEF_IPList_tags_1, /* Same as above */
+ sizeof(asn_DEF_IPList_tags_1)
+ /sizeof(asn_DEF_IPList_tags_1[0]), /* 1 */
+ { &asn_OER_type_IPList_constr_1, 0, SEQUENCE_OF_constraint },
+ asn_MBR_IPList_1,
+ 1, /* Single element */
+ &asn_SPC_IPList_specs_1 /* Additional specs */
+};
+
--- /dev/null
+/*
+ * Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
+ * From ASN.1 module "RpkiSignedChecklist-2021"
+ * found in "draft-ietf-sidrops-rpki-rsc.asn1"
+ * `asn1c -Werror -fcompound-names -fwide-types -D asn1/asn1c -no-gen-PER -no-gen-example`
+ */
+
+#ifndef _IPList_H_
+#define _IPList_H_
+
+
+#include "asn1/asn1c/asn_application.h"
+
+/* Including external dependencies */
+#include "asn1/asn1c/asn_SEQUENCE_OF.h"
+#include "asn1/asn1c/constr_SEQUENCE_OF.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Forward declarations */
+struct IPAddressFamilyItem;
+
+/* IPList */
+typedef struct IPList {
+ A_SEQUENCE_OF(struct IPAddressFamilyItem) list;
+
+ /* Context for parsing across buffer boundaries */
+ asn_struct_ctx_t _asn_ctx;
+} IPList_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_IPList;
+extern asn_SET_OF_specifics_t asn_SPC_IPList_specs_1;
+extern asn_TYPE_member_t asn_MBR_IPList_1[1];
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Referred external types */
+#include "IPAddressFamilyItem.h"
+
+#endif /* _IPList_H_ */
+#include "asn1/asn1c/asn_internal.h"
ASN_MODULE_SRCS= \
+ asn1/asn1c/RpkiSignedChecklist.c \
+ asn1/asn1c/FileNameAndHash.c \
+ asn1/asn1c/ResourceBlock.c \
+ asn1/asn1c/AsList.c \
+ asn1/asn1c/IPList.c \
+ asn1/asn1c/IPAddressFamilyItem.c \
asn1/asn1c/IPAddrBlocks.c \
asn1/asn1c/IPAddressFamily.c \
asn1/asn1c/IPAddressChoice.c \
asn1/asn1c/BinaryTime.c
ASN_MODULE_HDRS= \
+ asn1/asn1c/RpkiSignedChecklist.h \
+ asn1/asn1c/FileNameAndHash.h \
+ asn1/asn1c/ResourceBlock.h \
+ asn1/asn1c/AsList.h \
+ asn1/asn1c/IPList.h \
+ asn1/asn1c/IPAddressFamilyItem.h \
asn1/asn1c/IPAddrBlocks.h \
asn1/asn1c/IPAddressFamily.h \
asn1/asn1c/IPAddressChoice.h \
--- /dev/null
+/*
+ * Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
+ * From ASN.1 module "RpkiSignedChecklist-2021"
+ * found in "draft-ietf-sidrops-rpki-rsc.asn1"
+ * `asn1c -Werror -fcompound-names -fwide-types -D asn1/asn1c -no-gen-PER -no-gen-example`
+ */
+
+#include "ResourceBlock.h"
+
+static asn_oer_constraints_t asn_OER_type_ResourceBlock_constr_1 CC_NOTUSED = {
+ { 0, 0 },
+ -1};
+asn_TYPE_member_t asn_MBR_ResourceBlock_1[] = {
+ { ATF_POINTER, 2, offsetof(struct ResourceBlock, asID),
+ (ASN_TAG_CLASS_CONTEXT | (0 << 2)),
+ +1, /* EXPLICIT tag at current level */
+ &asn_DEF_AsList,
+ 0,
+ { 0, 0, 0 },
+ 0, 0, /* No default value */
+ "asID"
+ },
+ { ATF_POINTER, 1, offsetof(struct ResourceBlock, ipAddrBlocks),
+ (ASN_TAG_CLASS_CONTEXT | (1 << 2)),
+ +1, /* EXPLICIT tag at current level */
+ &asn_DEF_IPList,
+ 0,
+ { 0, 0, 0 },
+ 0, 0, /* No default value */
+ "ipAddrBlocks"
+ },
+};
+static const int asn_MAP_ResourceBlock_oms_1[] = { 0, 1 };
+static const ber_tlv_tag_t asn_DEF_ResourceBlock_tags_1[] = {
+ (ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+static const asn_TYPE_tag2member_t asn_MAP_ResourceBlock_tag2el_1[] = {
+ { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* asID */
+ { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 } /* ipAddrBlocks */
+};
+asn_SEQUENCE_specifics_t asn_SPC_ResourceBlock_specs_1 = {
+ sizeof(struct ResourceBlock),
+ offsetof(struct ResourceBlock, _asn_ctx),
+ asn_MAP_ResourceBlock_tag2el_1,
+ 2, /* Count of tags in the map */
+ asn_MAP_ResourceBlock_oms_1, /* Optional members */
+ 2, 0, /* Root/Additions */
+ -1, /* First extension addition */
+};
+asn_TYPE_descriptor_t asn_DEF_ResourceBlock = {
+ "ResourceBlock",
+ "ResourceBlock",
+ &asn_OP_SEQUENCE,
+ asn_DEF_ResourceBlock_tags_1,
+ sizeof(asn_DEF_ResourceBlock_tags_1)
+ /sizeof(asn_DEF_ResourceBlock_tags_1[0]), /* 1 */
+ asn_DEF_ResourceBlock_tags_1, /* Same as above */
+ sizeof(asn_DEF_ResourceBlock_tags_1)
+ /sizeof(asn_DEF_ResourceBlock_tags_1[0]), /* 1 */
+ { &asn_OER_type_ResourceBlock_constr_1, 0, SEQUENCE_constraint },
+ asn_MBR_ResourceBlock_1,
+ 2, /* Elements count */
+ &asn_SPC_ResourceBlock_specs_1 /* Additional specs */
+};
+
--- /dev/null
+/*
+ * Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
+ * From ASN.1 module "RpkiSignedChecklist-2021"
+ * found in "draft-ietf-sidrops-rpki-rsc.asn1"
+ * `asn1c -Werror -fcompound-names -fwide-types -D asn1/asn1c -no-gen-PER -no-gen-example`
+ */
+
+#ifndef _ResourceBlock_H_
+#define _ResourceBlock_H_
+
+
+#include "asn1/asn1c/asn_application.h"
+
+/* Including external dependencies */
+#include "asn1/asn1c/constr_SEQUENCE.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Forward declarations */
+struct AsList;
+struct IPList;
+
+/* ResourceBlock */
+typedef struct ResourceBlock {
+ struct AsList *asID /* OPTIONAL */;
+ struct IPList *ipAddrBlocks /* OPTIONAL */;
+
+ /* Context for parsing across buffer boundaries */
+ asn_struct_ctx_t _asn_ctx;
+} ResourceBlock_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_ResourceBlock;
+extern asn_SEQUENCE_specifics_t asn_SPC_ResourceBlock_specs_1;
+extern asn_TYPE_member_t asn_MBR_ResourceBlock_1[2];
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Referred external types */
+#include "AsList.h"
+#include "IPList.h"
+
+#endif /* _ResourceBlock_H_ */
+#include "asn1/asn1c/asn_internal.h"
--- /dev/null
+/*
+ * Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
+ * From ASN.1 module "RpkiSignedChecklist-2021"
+ * found in "draft-ietf-sidrops-rpki-rsc.asn1"
+ * `asn1c -Werror -fcompound-names -fwide-types -D asn1/asn1c -no-gen-PER -no-gen-example`
+ */
+
+#include "RpkiSignedChecklist.h"
+
+static int
+memb_checkList_constraint_1(const asn_TYPE_descriptor_t *td, const void *sptr,
+ asn_app_constraint_failed_f *ctfailcb, void *app_key) {
+ size_t size;
+
+ if(!sptr) {
+ ASN__CTFAIL(app_key, td, sptr,
+ "%s: value not given (%s:%d)",
+ td->name, __FILE__, __LINE__);
+ return -1;
+ }
+
+ /* Determine the number of elements */
+ size = _A_CSEQUENCE_FROM_VOID(sptr)->count;
+
+ if((size >= 1)) {
+ /* Perform validation of the inner elements */
+ return td->encoding_constraints.general_constraints(td, sptr, ctfailcb, app_key);
+ } else {
+ ASN__CTFAIL(app_key, td, sptr,
+ "%s: constraint failed (%s:%d)",
+ td->name, __FILE__, __LINE__);
+ return -1;
+ }
+}
+
+static asn_oer_constraints_t asn_OER_type_checkList_constr_5 CC_NOTUSED = {
+ { 0, 0 },
+ -1 /* (SIZE(1..MAX)) */};
+static asn_oer_constraints_t asn_OER_memb_checkList_constr_5 CC_NOTUSED = {
+ { 0, 0 },
+ -1 /* (SIZE(1..MAX)) */};
+static int asn_DFL_2_cmp_0(const void *sptr) {
+ const INTEGER_t *st = sptr;
+
+ if(!st) {
+ return -1; /* No value is not a default value */
+ }
+
+ /* Test default value 0 */
+ long value;
+ if(asn_INTEGER2long(st, &value))
+ return -1;
+ return (value != 0);
+}
+static int asn_DFL_2_set_0(void **sptr) {
+ INTEGER_t *st = *sptr;
+
+ if(!st) {
+ st = (*sptr = CALLOC(1, sizeof(*st)));
+ if(!st) return -1;
+ }
+
+ /* Install default value 0 */
+ return asn_long2INTEGER(st, 0);
+}
+static asn_TYPE_member_t asn_MBR_checkList_5[] = {
+ { ATF_POINTER, 0, 0,
+ (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
+ 0,
+ &asn_DEF_FileNameAndHash,
+ 0,
+ { 0, 0, 0 },
+ 0, 0, /* No default value */
+ ""
+ },
+};
+static const ber_tlv_tag_t asn_DEF_checkList_tags_5[] = {
+ (ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+static asn_SET_OF_specifics_t asn_SPC_checkList_specs_5 = {
+ sizeof(struct RpkiSignedChecklist__checkList),
+ offsetof(struct RpkiSignedChecklist__checkList, _asn_ctx),
+ 0, /* XER encoding is XMLDelimitedItemList */
+};
+static /* Use -fall-defs-global to expose */
+asn_TYPE_descriptor_t asn_DEF_checkList_5 = {
+ "checkList",
+ "checkList",
+ &asn_OP_SEQUENCE_OF,
+ asn_DEF_checkList_tags_5,
+ sizeof(asn_DEF_checkList_tags_5)
+ /sizeof(asn_DEF_checkList_tags_5[0]), /* 1 */
+ asn_DEF_checkList_tags_5, /* Same as above */
+ sizeof(asn_DEF_checkList_tags_5)
+ /sizeof(asn_DEF_checkList_tags_5[0]), /* 1 */
+ { &asn_OER_type_checkList_constr_5, 0, SEQUENCE_OF_constraint },
+ asn_MBR_checkList_5,
+ 1, /* Single element */
+ &asn_SPC_checkList_specs_5 /* Additional specs */
+};
+
+static asn_TYPE_member_t asn_MBR_RpkiSignedChecklist_1[] = {
+ { ATF_POINTER, 1, offsetof(struct RpkiSignedChecklist, version),
+ (ASN_TAG_CLASS_CONTEXT | (0 << 2)),
+ +1, /* EXPLICIT tag at current level */
+ &asn_DEF_INTEGER,
+ 0,
+ { 0, 0, 0 },
+ &asn_DFL_2_cmp_0, /* Compare DEFAULT 0 */
+ &asn_DFL_2_set_0, /* Set DEFAULT 0 */
+ "version"
+ },
+ { ATF_NOFLAGS, 0, offsetof(struct RpkiSignedChecklist, resources),
+ (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
+ 0,
+ &asn_DEF_ResourceBlock,
+ 0,
+ { 0, 0, 0 },
+ 0, 0, /* No default value */
+ "resources"
+ },
+ { ATF_NOFLAGS, 0, offsetof(struct RpkiSignedChecklist, digestAlgorithm),
+ (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
+ 0,
+ &asn_DEF_DigestAlgorithmIdentifier,
+ 0,
+ { 0, 0, 0 },
+ 0, 0, /* No default value */
+ "digestAlgorithm"
+ },
+ { ATF_NOFLAGS, 0, offsetof(struct RpkiSignedChecklist, checkList),
+ (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
+ 0,
+ &asn_DEF_checkList_5,
+ 0,
+ { &asn_OER_memb_checkList_constr_5, 0, memb_checkList_constraint_1 },
+ 0, 0, /* No default value */
+ "checkList"
+ },
+};
+static const int asn_MAP_RpkiSignedChecklist_oms_1[] = { 0 };
+static const ber_tlv_tag_t asn_DEF_RpkiSignedChecklist_tags_1[] = {
+ (ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+static const asn_TYPE_tag2member_t asn_MAP_RpkiSignedChecklist_tag2el_1[] = {
+ { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 1, 0, 2 }, /* resources */
+ { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 2, -1, 1 }, /* digestAlgorithm */
+ { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 3, -2, 0 }, /* checkList */
+ { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 } /* version */
+};
+static asn_SEQUENCE_specifics_t asn_SPC_RpkiSignedChecklist_specs_1 = {
+ sizeof(struct RpkiSignedChecklist),
+ offsetof(struct RpkiSignedChecklist, _asn_ctx),
+ asn_MAP_RpkiSignedChecklist_tag2el_1,
+ 4, /* Count of tags in the map */
+ asn_MAP_RpkiSignedChecklist_oms_1, /* Optional members */
+ 1, 0, /* Root/Additions */
+ -1, /* First extension addition */
+};
+asn_TYPE_descriptor_t asn_DEF_RpkiSignedChecklist = {
+ "RpkiSignedChecklist",
+ "RpkiSignedChecklist",
+ &asn_OP_SEQUENCE,
+ asn_DEF_RpkiSignedChecklist_tags_1,
+ sizeof(asn_DEF_RpkiSignedChecklist_tags_1)
+ /sizeof(asn_DEF_RpkiSignedChecklist_tags_1[0]), /* 1 */
+ asn_DEF_RpkiSignedChecklist_tags_1, /* Same as above */
+ sizeof(asn_DEF_RpkiSignedChecklist_tags_1)
+ /sizeof(asn_DEF_RpkiSignedChecklist_tags_1[0]), /* 1 */
+ { 0, 0, SEQUENCE_constraint },
+ asn_MBR_RpkiSignedChecklist_1,
+ 4, /* Elements count */
+ &asn_SPC_RpkiSignedChecklist_specs_1 /* Additional specs */
+};
+
--- /dev/null
+/*
+ * Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
+ * From ASN.1 module "RpkiSignedChecklist-2021"
+ * found in "draft-ietf-sidrops-rpki-rsc.asn1"
+ * `asn1c -Werror -fcompound-names -fwide-types -D asn1/asn1c -no-gen-PER -no-gen-example`
+ */
+
+#ifndef _RpkiSignedChecklist_H_
+#define _RpkiSignedChecklist_H_
+
+
+#include "asn1/asn1c/asn_application.h"
+
+/* Including external dependencies */
+#include "asn1/asn1c/INTEGER.h"
+#include "ResourceBlock.h"
+#include "DigestAlgorithmIdentifier.h"
+#include "asn1/asn1c/asn_SEQUENCE_OF.h"
+#include "asn1/asn1c/constr_SEQUENCE_OF.h"
+#include "asn1/asn1c/constr_SEQUENCE.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Forward declarations */
+struct FileNameAndHash;
+
+/* RpkiSignedChecklist */
+typedef struct RpkiSignedChecklist {
+ INTEGER_t *version /* DEFAULT 0 */;
+ ResourceBlock_t resources;
+ DigestAlgorithmIdentifier_t digestAlgorithm;
+ struct RpkiSignedChecklist__checkList {
+ A_SEQUENCE_OF(struct FileNameAndHash) list;
+
+ /* Context for parsing across buffer boundaries */
+ asn_struct_ctx_t _asn_ctx;
+ } checkList;
+
+ /* Context for parsing across buffer boundaries */
+ asn_struct_ctx_t _asn_ctx;
+} RpkiSignedChecklist_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_RpkiSignedChecklist;
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Referred external types */
+#include "FileNameAndHash.h"
+
+#endif /* _RpkiSignedChecklist_H_ */
+#include "asn1/asn1c/asn_internal.h"
}
int
-content_info_load(struct rpki_uri *uri, struct ContentInfo **result)
+content_info_load(char const *luri, struct ContentInfo **result)
{
struct file_contents fc;
int error;
- error = file_load(uri_get_local(uri), &fc);
+ error = file_load(luri, &fc);
if (error)
return error;
#include "uri.h"
#include "asn1/asn1c/ContentInfo.h"
-int content_info_load(struct rpki_uri *, struct ContentInfo **);
+int content_info_load(char const *, struct ContentInfo **);
void content_info_free(struct ContentInfo *);
#endif /* SRC_CONTENT_INFO_H_ */
#define OID_ROA { 1, 2, 840, 113549, 1, 9, 16, 1, 24 }
#define OID_MANIFEST { 1, 2, 840, 113549, 1, 9, 16, 1, 26 }
#define OID_GHOSTBUSTERS { 1, 2, 840, 113549, 1, 9, 16, 1, 35 }
+#define OID_SIGNED_CHECKLIST { 1, 2, 840, 113549, 1, 9, 16, 1, 48 }
int oid2arcs(OBJECT_IDENTIFIER_t *, struct oid_arcs *);
int
signed_object_args_init(struct signed_object_args *args,
- struct rpki_uri *uri,
STACK_OF(X509_CRL) *crls,
bool force_inherit)
{
if (args->res == NULL)
return pr_enomem();
- args->uri = uri;
+ args->cert_type = EE;
args->crls = crls;
memset(&args->refs, 0, sizeof(args->refs));
return 0;
error = certificate_validate_chain(cert, args->crls);
if (error)
goto end2;
- error = certificate_validate_rfc6487(cert, EE);
+ error = certificate_validate_rfc6487(cert, args->cert_type);
if (error)
goto end2;
- error = certificate_validate_extensions_ee(cert, sid, &args->refs,
- &policy);
+
+ switch (args->cert_type) {
+ case EE:
+ error = certificate_validate_extensions_ee(cert, sid,
+ &args->refs, &policy);
+ break;
+ case EE_CHECKLIST:
+ error = certificate_validate_extensions_ee_checklist(cert, sid,
+ &args->refs, &policy);
+ break;
+ default:
+ error = pr_val_err("Certificate type is not EE, even though we're validating a Signed Object.");
+ }
if (error)
goto end2;
+
error = certificate_validate_aia(args->refs.caIssuers, cert);
if (error)
goto end2;
goto end2;
resources_set_policy(args->res, policy);
- error = certificate_get_resources(cert, args->res, EE);
+ error = certificate_get_resources(cert, args->res, args->cert_type);
if (error)
goto end2;
* signed objects anymore.
*/
struct signed_object_args {
- /** Location of the signed object. */
- struct rpki_uri *uri;
+ /** Type of the embedded EE certificate. */
+ enum cert_type cert_type;
/** CRL that might or might not revoke the embedded certificate. */
STACK_OF(X509_CRL) *crls;
/** A copy of the resources carried by the embedded certificate. */
struct certificate_refs refs;
};
-int signed_object_args_init(struct signed_object_args *, struct rpki_uri *,
- STACK_OF(X509_CRL) *, bool);
+int signed_object_args_init(struct signed_object_args *, STACK_OF(X509_CRL) *,
+ bool);
void signed_object_args_cleanup(struct signed_object_args *);
struct signed_data {
return validate_signedObject(refs, uri);
}
+
+int
+refs_validate_ee_checklist(struct certificate_refs *refs, struct rpp const *pp)
+{
+ return validate_cdp(refs, pp);
+}
int refs_validate_ca(struct certificate_refs *, struct rpp const *);
int refs_validate_ee(struct certificate_refs *, struct rpp const *,
struct rpki_uri *);
+int refs_validate_ee_checklist(struct certificate_refs *, struct rpp const *);
#endif /* SRC_CERTIFICATE_REFS_H_ */
unsigned int maximum_certificate_depth;
/** File or directory where the .slurm file(s) is(are) located */
char *slurm;
+ /**
+ * .sig file. If not null, triggers RCS validation
+ * (draft-ietf-sidrops-rpki-rsc), which replaces the normal RPKI
+ * validation.
+ */
+ char *rsc;
/* Run as RTR server or standalone validation */
enum mode mode;
/*
.offset = offsetof(struct rpki_config, slurm),
.doc = "Path to the SLURM file or SLURMs directory (files must have the extension .slurm)",
.arg_doc = "<file>|<directory>"
+ }, {
+ .id = 1007,
+ .name = "rsc",
+ .type = >_string,
+ .offset = offsetof(struct rpki_config, rsc),
+ .doc = "Path to .sig file. Triggers RCS validation (draft-ietf-sidrops-rpki-rsc), which replaces the normal RPKI validation. Implies --mode standalone.",
+ .arg_doc = "<file>"
}, {
.id = 1004,
.name = "mode",
rpki_config.tal = NULL;
rpki_config.slurm = NULL;
+ rpki_config.rsc = NULL;
rpki_config.local_repository = strdup("/tmp/fort/repository");
if (rpki_config.local_repository == NULL) {
if (rpki_config.slurm != NULL &&
!valid_file_or_dir(rpki_config.slurm, true, true, __pr_op_err))
- return pr_op_err("Invalid slurm location.");
+ return -EINVAL;
+
+ if (rpki_config.rsc != NULL &&
+ !valid_file_or_dir(rpki_config.rsc, true, false, __pr_op_err))
+ return -EINVAL;
/* FIXME (later) Remove when sync-strategy is fully deprecated */
if (!rpki_config.rsync.enabled)
enum mode
config_get_mode(void)
{
+ /* TODO meh, kinda rude. */
+ if (rpki_config.rsc != NULL)
+ return STANDALONE;
+
return rpki_config.mode;
}
return rpki_config.slurm;
}
+char const *
+config_get_rsc(void)
+{
+ return rpki_config.rsc;
+}
+
char const *
config_get_tal(void)
{
unsigned int config_get_interval_retry(void);
unsigned int config_get_interval_expire(void);
char const *config_get_slurm(void);
+char const *config_get_rsc(void);
char const *config_get_tal(void);
char const *config_get_local_repository(void);
#include "object/bgpsec.h"
#include "object/name.h"
#include "object/manifest.h"
+#include "object/rsc.h"
#include "object/signed_object.h"
#include "rrdp/rrdp_loader.h"
#include "rsync/rsync.h"
}
static int
-validate_issuer(X509 *cert, bool is_ta)
+validate_issuer(X509 *cert, enum cert_type type)
{
X509_NAME *issuer;
struct rfc5280_name *name;
issuer = X509_get_issuer_name(cert);
- if (!is_ta)
+ if (type != TA)
return validate_issuer_name("Certificate", issuer);
/* TODO wait. Shouldn't we check subject == issuer? */
unsigned char *tmp;
int error;
- error = signed_object_decode(&sobj, uri);
+ error = signed_object_decode(&sobj, uri_get_local(uri));
if (error)
return error;
return error;
/* rfc6487#section-4.4 */
- error = validate_issuer(cert, type == TA);
+ error = validate_issuer(cert, type);
if (error)
return error;
static int
handle_asn_extension(X509_EXTENSION *ext, struct resources *resources,
- bool allow_inherit)
+ enum cert_type type)
{
ASN1_OCTET_STRING *string;
struct ASIdentifiers *ids;
if (error)
return error;
- error = resources_add_asn(resources, ids, allow_inherit);
+ error = resources_add_asn(resources, ids, type);
ASN_STRUCT_FREE(asn_DEF_ASIdentifiers, ids);
return error;
static int
__certificate_get_resources(X509 *cert, struct resources *resources,
int addr_nid, int asn_nid, int bad_addr_nid, int bad_asn_nid,
- char const *policy_rfc, char const *bad_ext_rfc, bool allow_asn_inherit)
+ char const *policy_rfc, char const *bad_ext_rfc, enum cert_type type)
{
X509_EXTENSION *ext;
int nid;
return pr_val_err("The AS extension is not marked as critical.");
pr_val_debug("ASN {");
- error = handle_asn_extension(ext, resources,
- allow_asn_inherit);
+ error = handle_asn_extension(ext, resources, type);
pr_val_debug("}");
asn_ext_found = true;
if (!ip_ext_found && !asn_ext_found)
return pr_val_err("Certificate lacks both IP and AS extension.");
+ if (type == EE_CHECKLIST && !ip_ext_found)
+ return pr_val_err("Certificate lacks an IP extension.");
return 0;
}
return __certificate_get_resources(cert, resources,
NID_sbgp_ipAddrBlock, NID_sbgp_autonomousSysNum,
nid_ipAddrBlocksv2(), nid_autonomousSysIdsv2(),
- "6484", "8360", type != BGPSEC);
+ "6484", "8360", type);
case RPKI_POLICY_RFC8360:
return __certificate_get_resources(cert, resources,
nid_ipAddrBlocksv2(), nid_autonomousSysIdsv2(),
NID_sbgp_ipAddrBlock, NID_sbgp_autonomousSysNum,
- "8360", "6484", type != BGPSEC);
+ "8360", "6484", type);
}
pr_crit("Unknown policy: %u", policy);
char const *ad_name, int ad_nid, int uri_flags, bool required,
int (*cb)(struct rpki_uri *, uint8_t, void *), void *arg)
{
-# define AD_METHOD ((uri_flags & URI_VALID_RSYNC) == URI_VALID_RSYNC ? \
+#define AD_METHOD ((uri_flags & URI_VALID_RSYNC) == URI_VALID_RSYNC ? \
"RSYNC" : \
(((uri_flags & URI_VALID_HTTPS) == URI_VALID_HTTPS) ? \
"HTTPS" : "RSYNC/HTTPS"))
+
ACCESS_DESCRIPTION *ad;
struct rpki_uri *uri;
bool found = false;
return handle_extensions(handlers, X509_get0_extensions(cert));
}
+int
+certificate_validate_extensions_ee_checklist(X509 *cert, OCTET_STRING_t *sid,
+ struct certificate_refs *refs, enum rpki_policy *policy)
+{
+ struct ski_arguments ski_args;
+ struct extension_handler handlers[] = {
+ /* ext reqd handler arg */
+ { ext_ski(), true, handle_ski_ee, &ski_args },
+ { ext_aki(), true, handle_aki, },
+ { ext_ku(), true, handle_ku_ee, },
+ { ext_cdp(), true, handle_cdp, refs },
+ { ext_aia(), true, handle_aia, refs },
+ { ext_cp(), true, handle_cp, policy },
+ { ext_ir(), false, handle_ir, },
+ { ext_ar(), false, handle_ar, },
+ { ext_ir2(), false, handle_ir, },
+ { ext_ar2(), false, handle_ar, },
+ { NULL },
+ };
+
+ ski_args.cert = cert;
+ ski_args.sid = sid;
+
+ /* TODO (RSC) make sure SIA does not exist. */
+
+ return handle_extensions(handlers, X509_get0_extensions(cert));
+}
+
static enum cert_type
get_certificate_type(X509 *cert, bool is_ta)
{
return 0;
}
+struct rsc_args {
+ struct rpp *pp;
+ struct rpki_uri *cert_uri;
+};
+
+static int
+check_rsc_uri(struct rpki_uri const *rsc_uri, void *_args)
+{
+ struct rsc_args *args = _args;
+
+ if (uri_equals(rsc_uri, args->cert_uri))
+ exit(rsc_traverse(args->pp));
+
+ return 0;
+}
+
+static void
+handle_rsc(struct validation *state, struct rpp *pp, struct rpki_uri *cert_uri)
+{
+ struct rsc_args args;
+ args.pp = pp;
+ args.cert_uri = cert_uri;
+ validation_foreach_rsc(state, check_rsc_uri, &args);
+}
+
/** Boilerplate code for CA certificate validation and recursive traversal. */
int
certificate_traverse(struct rpp *rpp_parent, struct rpki_uri *cert_uri)
pr_val_debug("Type: BGPsec EE");
break;
case EE:
+ case EE_CHECKLIST:
pr_val_debug("Type: unexpected, validated as CA");
break;
}
goto revert_uris;
}
+ if (config_get_rsc() != NULL)
+ handle_rsc(state, pp, cert_uri);
+
/* -- Validate & traverse the RPP (@pp) described by the manifest -- */
rpp_traverse(pp);
TA, /* Trust Anchor */
CA, /* Certificate Authority */
BGPSEC, /* BGPsec certificates */
- EE, /* End Entity certificates */
+ EE, /* End Entity certificates (Except Signed Checklist) */
+ EE_CHECKLIST, /* End Entity certificate inside of Signed Checklist */
};
int certificate_load(struct rpki_uri *, X509 **);
*/
int certificate_validate_extensions_ee(X509 *, OCTET_STRING_t *,
struct certificate_refs *, enum rpki_policy *);
+int certificate_validate_extensions_ee_checklist(X509 *cert,
+ OCTET_STRING_t *sid, struct certificate_refs *refs,
+ enum rpki_policy *policy);
/*
* Specific validation of AIA (rfc6487#section-4.8.7) extension, public so that
validate_extensions(X509_CRL *crl)
{
struct extension_handler handlers[] = {
- /* ext reqd handler arg */
+ /* ext reqd handler arg */
{ ext_aki(), true, handle_aki, },
{ ext_cn(), true, handle_crlnum, },
{ NULL },
fnstack_push_uri(uri);
/* Decode */
- error = signed_object_decode(&sobj, uri);
+ error = signed_object_decode(&sobj, uri_get_local(uri));
if (error)
goto revert_log;
error = rpp_crl(pp, &crl);
if (error)
goto revert_sobj;
- error = signed_object_args_init(&sobj_args, uri, crl, true);
+ error = signed_object_args_init(&sobj_args, crl, true);
if (error)
goto revert_sobj;
error = handle_vcard(&sobj);
if (error)
goto revert_args;
- error = refs_validate_ee(&sobj_args.refs, pp, sobj_args.uri);
+ error = refs_validate_ee(&sobj_args.refs, pp, uri);
revert_args:
signed_object_args_cleanup(&sobj_args);
fnstack_push_uri(uri);
/* Decode */
- error = signed_object_decode(&sobj, uri);
+ error = signed_object_decode(&sobj, uri_get_local(uri));
if (error)
goto revert_log;
error = decode_manifest(&sobj, &mft);
error = rpp_crl(*pp, &crl);
if (error)
goto revert_rpp;
- error = signed_object_args_init(&sobj_args, uri, crl, false);
+ error = signed_object_args_init(&sobj_args, crl, false);
if (error)
goto revert_rpp;
void
x509_name_pr_debug(const char *prefix, X509_NAME *name)
{
+ struct rfc5280_name *printable;
+
if (!log_val_enabled(LOG_DEBUG))
return;
- struct rfc5280_name *printable;
-
if (name == NULL) {
pr_val_debug("%s: (null)", prefix);
return;
fnstack_push_uri(uri);
/* Decode */
- error = signed_object_decode(&sobj, uri);
+ error = signed_object_decode(&sobj, uri_get_local(uri));
if (error)
goto revert_log;
error = decode_roa(&sobj, &roa);
error = rpp_crl(pp, &crl);
if (error)
goto revert_roa;
- error = signed_object_args_init(&sobj_args, uri, crl, false);
+ error = signed_object_args_init(&sobj_args, crl, false);
if (error)
goto revert_roa;
error = __handle_roa(roa, sobj_args.res);
if (error)
goto revert_args;
- error = refs_validate_ee(&sobj_args.refs, pp, sobj_args.uri);
+ error = refs_validate_ee(&sobj_args.refs, pp, uri);
revert_args:
signed_object_args_cleanup(&sobj_args);
--- /dev/null
+#include "object/rsc.h"
+
+#include "algorithm.h"
+#include "log.h"
+#include "thread_var.h"
+#include "asn1/oid.h"
+#include "asn1/decode.h"
+#include "asn1/asn1c/RpkiSignedChecklist.h"
+#include "object/signed_object.h"
+
+/* Returns @sobj's EE certificate. */
+static int
+get_certificate(struct signed_object *sobj, X509 **result)
+{
+ struct SignedData *decoded_object;
+ ANY_t *encoded_certificate;
+ X509 *decoded_certificate;
+ const unsigned char *tmp;
+
+ *result = NULL; /* Warning shutupper */
+ decoded_object = sobj->sdata.decoded;
+
+ if (decoded_object->certificates == NULL)
+ return pr_val_err("The SignedData does not contain certificates.");
+ if (decoded_object->certificates->list.count != 1) {
+ return pr_val_err("The SignedData contains %d certificates, one expected.",
+ decoded_object->certificates->list.count);
+ }
+
+ encoded_certificate = decoded_object->certificates->list.array[0];
+
+ /*
+ * "If the call is successful *in is incremented to the byte following
+ * the parsed data."
+ * (https://www.openssl.org/docs/man1.0.2/crypto/d2i_X509_fp.html)
+ * We definitely don't want @any->buf to be modified, so use a dummy
+ * pointer.
+ */
+ tmp = (const unsigned char *) encoded_certificate->buf;
+
+ decoded_certificate = d2i_X509(NULL, &tmp, encoded_certificate->size);
+ if (decoded_certificate == NULL)
+ return val_crypto_err("Signed object's 'certificate' element does not decode into a Certificate");
+
+ *result = decoded_certificate;
+ return 0;
+}
+
+/* "Find (and return) the Authority Information Access extension" */
+static int
+find_aia(STACK_OF(X509_EXTENSION) const *extensions,
+ AUTHORITY_INFO_ACCESS **result)
+{
+ int e;
+ X509_EXTENSION *ext;
+ int nid;
+ AUTHORITY_INFO_ACCESS *aia;
+
+ for (e = 0; e < sk_X509_EXTENSION_num(extensions); e++) {
+ ext = sk_X509_EXTENSION_value(extensions, e);
+ nid = OBJ_obj2nid(X509_EXTENSION_get_object(ext));
+ if (nid == NID_info_access) {
+ aia = X509V3_EXT_d2i(ext);
+ if (aia == NULL)
+ return pr_val_err("Embedded EE certificate's Authority Information Access extension seems to be malformed.");
+ *result = aia;
+ return 0;
+ }
+ }
+
+ return pr_val_err("Embedded EE certificate appears to have no Authority Information Access extension.");
+}
+
+/* "Store Acess Descriptors" (in the validation state) */
+static int
+store_ads(AUTHORITY_INFO_ACCESS *aia)
+{
+ struct validation *state;
+ unsigned int ad;
+
+ struct rpki_uri **rsc_uris;
+ unsigned int uri;
+
+ int error;
+
+ rsc_uris = calloc(sk_ACCESS_DESCRIPTION_num(aia),
+ sizeof(struct rpki_uri *));
+ if (rsc_uris == NULL)
+ return pr_enomem();
+ uri = 0;
+
+ for (ad = 0; ad < sk_ACCESS_DESCRIPTION_num(aia); ad++) {
+ error = uri_create_ad(&rsc_uris[uri],
+ sk_ACCESS_DESCRIPTION_value(aia, ad),
+ URI_VALID_RSYNC | URI_VALID_HTTPS);
+ if (error == ENOTSUPPORTED)
+ continue; /* Unknown; whatever. */
+ if (error)
+ goto revert;
+
+ pr_val_info("Found AIA: %s\n",
+ uri_val_get_printable(rsc_uris[uri]));
+ uri++;
+ }
+
+ state = state_retrieve();
+ if (!state) {
+ error = -EINVAL;
+ goto revert;
+ }
+
+ /* TODO (RSC) this is not being freed. Probably not important. */
+ validation_set_rsc_uris(state, rsc_uris, uri);
+ return 0;
+
+revert:
+ for (ad = 0; ad < sk_ACCESS_DESCRIPTION_num(aia); ad++)
+ if (rsc_uris[uri] != NULL)
+ uri_refput(rsc_uris[uri]);
+ free(rsc_uris);
+ return error;
+}
+
+int
+rsc_store_aias(void)
+{
+ char const *rsc_uri;
+ struct signed_object sobj;
+ X509 *certificate;
+ AUTHORITY_INFO_ACCESS *aia;
+ int error;
+
+ rsc_uri = config_get_rsc();
+
+ /* Prepare */
+ pr_val_debug("Signed Checklist '%s' {", rsc_uri);
+ fnstack_push(rsc_uri);
+
+ /* Decode */
+ error = signed_object_decode(&sobj, rsc_uri);
+ if (error)
+ goto revert_log;
+
+ error = get_certificate(&sobj, &certificate);
+ if (error)
+ goto revert_decode;
+
+ error = find_aia(X509_get0_extensions(certificate), &aia);
+ if (error)
+ goto revert_certificate;
+
+ error = store_ads(aia);
+
+ AUTHORITY_INFO_ACCESS_free(aia);
+
+revert_certificate:
+ X509_free(certificate);
+revert_decode:
+ signed_object_cleanup(&sobj);
+revert_log:
+ pr_val_debug("}");
+ fnstack_pop();
+ return error;
+}
+
+static int
+decode_checklist(struct signed_object *sobj,
+ struct RpkiSignedChecklist **result)
+{
+ return asn1_decode_octet_string(
+ sobj->sdata.decoded->encapContentInfo.eContent,
+ &asn_DEF_RpkiSignedChecklist,
+ (void **) result,
+ true,
+ false
+ );
+}
+
+static bool
+is_portable_character(uint8_t chara)
+{
+ if (0x20 <= chara && chara <= 0x7E)
+ return true;
+ if (0x07 <= chara && chara <= 0x0D)
+ return true;
+ return chara == 0;
+}
+
+static int
+validate_filename(IA5String_t *filename)
+{
+ size_t i;
+
+ if (filename == NULL)
+ return 0;
+ if (filename->buf == NULL)
+ return pr_val_err("fileName contains a NULL buffer.");
+
+ for (i = 0; i < filename->size; i++)
+ if (!is_portable_character(filename->buf[i]))
+ return pr_val_err("fileName contains invalid character %u.", filename->buf[i]);
+
+ return 0;
+}
+
+static int
+print_checklist(struct RpkiSignedChecklist *rsc)
+{
+ struct FileNameAndHash *fnah;
+ int error;
+ int i;
+
+ if (rsc->checkList.list.array == NULL)
+ return pr_val_err("RSC's checklist is a NULL array.");
+
+ for (i = 0; i < rsc->checkList.list.count; i++) {
+ fnah = rsc->checkList.list.array[i];
+ error = validate_filename(fnah->fileName);
+ if (error)
+ return error;
+ if (asn_fprint(stdout, &asn_DEF_FileNameAndHash, fnah) != 0) {
+ error = errno;
+ return pr_val_errno(error,
+ "Error printing FileNameAndHash");
+ }
+ }
+
+ return 0;
+}
+
+static int
+validate_resources_asID(struct resources *parent, struct AsList *asid)
+{
+ return 0;
+ /* TODO (RSC) ? */
+
+// struct ASIdOrRange *aor;
+// int a;
+//
+// if (asid == NULL)
+// return 0;
+// if (asid->list.array == NULL)
+// return pr_val_err("rsc->resources.asID contains a NULL array.");
+//
+// for (a = 0; a < asid->list.count; a++) {
+// aor = asid->list.array[a];
+//
+// switch (aor->choice) {
+// case ASIdOrRange_PR_NOTHING:
+// return pr_val_err("ASIdOrRange is neither id nor range.");
+// case ASIdOrRange_PR_id:
+// // aor->choice.id;
+// break;
+// case ASIdOrRange_PR_range:
+//
+// }
+// }
+}
+
+static int
+validate_prefix4(struct resources *parent, struct IPAddressFamilyItem *iafi)
+{
+ struct ipv4_prefix prefix;
+ int error;
+
+ error = prefix4_decode(&iafi->iPAddressOrRange.choice.addressPrefix,
+ &prefix);
+ if (error)
+ return error;
+
+ if (!resources_contains_ipv4(parent, &prefix)) {
+ return pr_val_err("RSC is not allowed to contain %s/%u.",
+ v4addr2str(&prefix.addr), prefix.len);
+ }
+
+ pr_val_debug("%s/%u: Approved.", v4addr2str(&prefix.addr), prefix.len);
+ return 0;
+}
+
+static int
+validate_prefix6(struct resources *parent, struct IPAddressFamilyItem *iafi)
+{
+ struct ipv6_prefix prefix;
+ int error;
+
+ error = prefix6_decode(&iafi->iPAddressOrRange.choice.addressPrefix,
+ &prefix);
+ if (error)
+ return error;
+
+ if (!resources_contains_ipv6(parent, &prefix)) {
+ return pr_val_err("RSC is not allowed to contain %s/%u.",
+ v6addr2str(&prefix.addr), prefix.len);
+ }
+
+ pr_val_debug("%s/%u: Approved.", v6addr2str(&prefix.addr), prefix.len);
+ return 0;
+}
+
+static int
+validate_range4(struct resources *parent, struct IPAddressFamilyItem *iafi)
+{
+ struct ipv4_range range;
+ int error;
+
+ error = range4_decode(&iafi->iPAddressOrRange.choice.addressRange,
+ &range);
+ if (error)
+ return error;
+
+ if (!resources_contains_range4(parent, &range)) {
+ return pr_val_err("RSC is not allowed to contain %s-%s.",
+ v4addr2str(&range.min), v4addr2str2(&range.max));
+ }
+
+ pr_val_debug("%s-%s: Approved.", v4addr2str(&range.min),
+ v4addr2str2(&range.max));
+ return 0;
+}
+
+static int
+validate_range6(struct resources *parent, struct IPAddressFamilyItem *iafi)
+{
+ struct ipv6_range range;
+ int error;
+
+ error = range6_decode(&iafi->iPAddressOrRange.choice.addressRange,
+ &range);
+ if (error)
+ return error;
+
+ if (!resources_contains_range6(parent, &range)) {
+ return pr_val_err("RSC is not allowed to contain %s-%s.",
+ v6addr2str(&range.min), v6addr2str2(&range.max));
+ }
+
+ pr_val_debug("%s-%s: Approved.", v6addr2str(&range.min),
+ v6addr2str2(&range.max));
+ return 0;
+}
+
+static int
+validate_resources_ipAddrBlocks(struct resources *parent, struct IPList *ips)
+{
+ struct IPAddressFamilyItem *iafi;
+ int error;
+ int i;
+
+ if (ips == NULL)
+ return 0;
+ if (ips->list.array == NULL)
+ return pr_val_err("rsc->resources.ipAddrBlocks contains a NULL array.");
+
+ error = 0;
+ for (i = 0; i < ips->list.count; i++) {
+ iafi = ips->list.array[i];
+
+ if (iafi == NULL)
+ return pr_val_err("IPAddressFamilyItem array element is NULL.");
+
+ if (iafi->addressFamily.size != 2)
+ goto family_error;
+ if (iafi->addressFamily.buf[0] != 0)
+ goto family_error;
+
+ /* TODO (RSC) what about resources->policy? */
+ switch (iafi->addressFamily.buf[1]) {
+ case 1:
+ switch (iafi->iPAddressOrRange.present) {
+ case IPAddressOrRange_PR_addressPrefix:
+ error = validate_prefix4(parent, iafi);
+ break;
+ case IPAddressOrRange_PR_addressRange:
+ error = validate_range4(parent, iafi);
+ break;
+ case IPAddressOrRange_PR_NOTHING:
+ goto pr_nothing;
+ }
+ break;
+ case 2:
+ switch (iafi->iPAddressOrRange.present) {
+ case IPAddressOrRange_PR_addressPrefix:
+ error = validate_prefix6(parent, iafi);
+ break;
+ case IPAddressOrRange_PR_addressRange:
+ error = validate_range6(parent, iafi);
+ break;
+ case IPAddressOrRange_PR_NOTHING:
+ goto pr_nothing;
+ }
+ break;
+ default:
+ goto family_error;
+ }
+ }
+
+ return error;
+
+family_error:
+ return pr_val_err("IPAddressFamilyItem's IP family is not v4 or v6.");
+pr_nothing:
+ return pr_val_err("IPAddressFamilyItem has neither a prefix nor a range.");
+}
+
+static int
+__handle_checklist(struct RpkiSignedChecklist *rsc, struct resources *parent)
+{
+ unsigned long version;
+ int error;
+
+ pr_val_debug("eContent {");
+ if (rsc->version != NULL) {
+ error = asn_INTEGER2ulong(rsc->version, &version);
+ if (error) {
+ if (errno)
+ pr_val_errno(errno, "Error casting RSC's version");
+ error = pr_val_err("The RSC's version isn't a valid long");
+ goto end;
+ }
+ /* draft#section-4.1 */
+ if (version != 0) {
+ error = pr_val_err("RSC's version (%lu) is nonzero.",
+ version);
+ goto end;
+ }
+ }
+
+ /* draft#section-4.2 */
+ error = validate_resources_asID(parent, rsc->resources.asID);
+ if (error)
+ goto end;
+ error = validate_resources_ipAddrBlocks(parent,
+ rsc->resources.ipAddrBlocks);
+ if (error)
+ goto end;
+
+ /* draft#section-4.3 */
+ error = validate_cms_hashing_algorithm(&rsc->digestAlgorithm,
+ "digestAlgorithm");
+ if (error)
+ return error;
+
+ /* draft#section-4.4 */
+ error = print_checklist(rsc);
+ /* Fall through */
+
+end:
+ pr_val_debug("}");
+ return error;
+}
+
+void
+rsc_traverse(struct rpp *pp)
+{
+ static OID oid = OID_SIGNED_CHECKLIST;
+ struct oid_arcs arcs = OID2ARCS("signed checklist", oid);
+ char const *rsc_uri;
+ struct signed_object sobj;
+ struct signed_object_args sobj_args;
+ struct RpkiSignedChecklist *checklist;
+ STACK_OF(X509_CRL) *crl;
+ int error;
+
+ rsc_uri = config_get_rsc();
+
+ /* Prepare */
+ pr_val_debug("Signed Checklist '%s' {", rsc_uri);
+ fnstack_push(rsc_uri);
+
+ /* Decode */
+ error = signed_object_decode(&sobj, rsc_uri);
+ if (error)
+ goto revert_log;
+ error = decode_checklist(&sobj, &checklist);
+ if (error)
+ goto revert_sobj;
+
+ /* Prepare validation arguments */
+ error = rpp_crl(pp, &crl);
+ if (error)
+ goto revert_checklist;
+ error = signed_object_args_init(&sobj_args, crl, false);
+ if (error)
+ goto revert_checklist;
+ sobj_args.cert_type = EE_CHECKLIST;
+
+ /* Validate everything */
+ error = signed_object_validate(&sobj, &arcs, &sobj_args);
+ if (error)
+ goto revert_args;
+ error = __handle_checklist(checklist, sobj_args.res);
+ if (error)
+ goto revert_args;
+ /*
+ * TODO (RSC) why is this validated last? The hashes were already
+ * printed.
+ */
+ error = refs_validate_ee_checklist(&sobj_args.refs, pp);
+
+revert_args:
+ signed_object_args_cleanup(&sobj_args);
+revert_checklist:
+ ASN_STRUCT_FREE(asn_DEF_RpkiSignedChecklist, checklist);
+revert_sobj:
+ signed_object_cleanup(&sobj);
+revert_log:
+ fnstack_pop();
+ pr_val_debug("}");
+}
--- /dev/null
+#ifndef SRC_OBJECT_RSC_H_
+#define SRC_OBJECT_RSC_H_
+
+#include "rpp.h"
+
+int rsc_store_aias(void);
+void rsc_traverse(struct rpp *);
+
+#endif /* SRC_OBJECT_RSC_H_ */
#include "asn1/content_info.h"
int
-signed_object_decode(struct signed_object *sobj, struct rpki_uri *uri)
+signed_object_decode(struct signed_object *sobj, char const *luri)
{
int error;
- error = content_info_load(uri, &sobj->cinfo);
+ error = content_info_load(luri, &sobj->cinfo);
if (error)
return error;
struct signed_data sdata;
};
-int signed_object_decode(struct signed_object *, struct rpki_uri *);
+int signed_object_decode(struct signed_object *, char const *);
int signed_object_validate(struct signed_object *, struct oid_arcs const *,
struct signed_object_args *);
void signed_object_cleanup(struct signed_object *);
#include "rtr/db/vrps.h"
#include "rrdp/db/db_rrdp.h"
+#include "object/rsc.h" /* TODO (RSC) delete */
+
#define TAL_FILE_EXTENSION ".tal"
typedef int (*foreach_uri_cb)(struct tal *, struct rpki_uri *, void *);
if (error)
return ENSURE_NEGATIVE(error);
+ /* TODO (RSC) dumb hack; move this. */
+ if (config_get_rsc() != NULL) {
+ error = rsc_store_aias();
+ if (error)
+ goto end;
+ }
+
if (thread_arg->sync_files) {
if (uri_is_rsync(uri)) {
if (!config_get_rsync_enabled()) {
struct validation_thread *thread;
int error, t_error;
+ /* TODO why is this stored in the heap? */
param = malloc(sizeof(struct tal_param));
if (param == NULL)
return pr_enomem();
int
resources_add_asn(struct resources *resources, struct ASIdentifiers *ids,
- bool allow_inherit)
+ enum cert_type type)
{
if (ids->asnum == NULL)
return pr_val_err("ASN extension lacks 'asnum' element.");
switch (ids->asnum->present) {
case ASIdentifierChoice_PR_inherit:
- if (!allow_inherit)
+ if (type == BGPSEC)
return pr_val_err("ASIdentifierChoice %u isn't allowed",
ids->asnum->present);
return inherit_asiors(resources);
return res6_contains_prefix(res->ip6s, prefix);
}
+bool
+resources_contains_range4(struct resources *res, struct ipv4_range *range)
+{
+ return res4_contains_range(res->ip4s, range);
+}
+
+bool
+resources_contains_range6(struct resources *res, struct ipv6_range *range)
+{
+ return res6_contains_range(res->ip6s, range);
+}
+
enum rpki_policy
resources_get_policy(struct resources *res)
{
void resources_destroy(struct resources *);
int resources_add_ip(struct resources *, struct IPAddressFamily *);
-int resources_add_asn(struct resources *, struct ASIdentifiers *, bool);
+enum cert_type;
+int resources_add_asn(struct resources *, struct ASIdentifiers *,
+ enum cert_type);
bool resources_empty(struct resources *);
bool resources_contains_asn(struct resources *, unsigned long);
bool resources_contains_ipv4(struct resources *, struct ipv4_prefix *);
bool resources_contains_ipv6(struct resources *, struct ipv6_prefix *);
+bool resources_contains_range4(struct resources *, struct ipv4_range *);
+bool resources_contains_range6(struct resources *, struct ipv6_range *);
enum rpki_policy resources_get_policy(struct resources *);
void resources_set_policy(struct resources *, enum rpki_policy);
*/
__cert_traverse(pp);
+ if (config_get_rsc() != NULL)
+ return; /* In RSC runs, ROAs and Ghostbusters don't matter. */
+
/* Validate ROAs, apply validation_handler on them. */
ARRAYLIST_FOREACH(&pp->roas, uri, i)
roa_traverse(*uri, pp);
char addr_buffer2[INET6_ADDRSTRLEN];
struct validation_handler validation_handler;
+
+ /**
+ * URI pointer array. If RSC validation is enabled, these are the Signed
+ * Checklist's EE certificate's AIA URLs. Otherwise NULL.
+ *
+ * Fort needs to look for a CA certificate that matches one of these
+ * URIs.
+ */
+ struct rpki_uri **rsc_uris;
+ /** Size of the rsc_uris array. */
+ unsigned int rsc_uris_size;
};
/*
{
return state->rrdp_workspace;
}
+
+int
+validation_foreach_rsc(struct validation *state, foreach_rsc_cb cb, void *arg)
+{
+ unsigned int i;
+ int status;
+
+ for (i = 0; i < state->rsc_uris_size; i++) {
+ status = cb(state->rsc_uris[i], arg);
+ if (status != 0)
+ return status;
+ }
+
+ return 0;
+}
+
+void
+validation_set_rsc_uris(struct validation *state, struct rpki_uri **uris,
+ unsigned int count)
+{
+ state->rsc_uris = uris;
+ state->rsc_uris_size = count;
+}
struct db_rrdp_uri *validation_get_rrdp_uris(struct validation *);
char const *validation_get_rrdp_workspace(struct validation *);
+typedef int (*foreach_rsc_cb)(struct rpki_uri const *, void *);
+int validation_foreach_rsc(struct validation *, foreach_rsc_cb, void *);
+void validation_set_rsc_uris(struct validation *, struct rpki_uri **,
+ unsigned int);
+
#endif /* SRC_STATE_H_ */
}
char const *
-uri_get_global(struct rpki_uri *uri)
+uri_get_global(struct rpki_uri const *uri)
{
return uri->global;
}
char const *
-uri_get_local(struct rpki_uri *uri)
+uri_get_local(struct rpki_uri const *uri)
{
return uri->local;
}
size_t
-uri_get_global_len(struct rpki_uri *uri)
+uri_get_global_len(struct rpki_uri const *uri)
{
return uri->global_len;
}
bool
-uri_equals(struct rpki_uri *u1, struct rpki_uri *u2)
+uri_equals(struct rpki_uri const *u1, struct rpki_uri const *u2)
{
return strcmp(u1->global, u2->global) == 0;
}
/* @ext must include the period. */
bool
-uri_has_extension(struct rpki_uri *uri, char const *ext)
+uri_has_extension(struct rpki_uri const *uri, char const *ext)
{
size_t ext_len;
int cmp;
}
bool
-uri_is_certificate(struct rpki_uri *uri)
+uri_is_certificate(struct rpki_uri const *uri)
{
return uri_has_extension(uri, ".cer");
}
bool
-uri_is_rsync(struct rpki_uri *uri)
+uri_is_rsync(struct rpki_uri const *uri)
{
return uri->type == URI_RSYNC;
}
}
static char const *
-uri_get_printable(struct rpki_uri *uri, enum filename_format format)
+uri_get_printable(struct rpki_uri const *uri, enum filename_format format)
{
switch (format) {
case FNF_GLOBAL:
}
char const *
-uri_val_get_printable(struct rpki_uri *uri) {
+uri_val_get_printable(struct rpki_uri const *uri) {
enum filename_format format;
format = config_get_val_log_filename_format();
}
char const *
-uri_op_get_printable(struct rpki_uri *uri) {
+uri_op_get_printable(struct rpki_uri const *uri) {
enum filename_format format;
format = config_get_op_log_filename_format();
* Note that, if you intend to print some URI, you're likely supposed to use
* uri_get_printable() instead.
*/
-char const *uri_get_global(struct rpki_uri *);
-char const *uri_get_local(struct rpki_uri *);
-size_t uri_get_global_len(struct rpki_uri *);
+char const *uri_get_global(struct rpki_uri const *);
+char const *uri_get_local(struct rpki_uri const *);
+size_t uri_get_global_len(struct rpki_uri const *);
-bool uri_equals(struct rpki_uri *, struct rpki_uri *);
-bool uri_has_extension(struct rpki_uri *, char const *);
-bool uri_is_certificate(struct rpki_uri *);
-bool uri_is_rsync(struct rpki_uri *);
+bool uri_equals(struct rpki_uri const *, struct rpki_uri const *);
+bool uri_has_extension(struct rpki_uri const *, char const *);
+bool uri_is_certificate(struct rpki_uri const *);
+bool uri_is_rsync(struct rpki_uri const *);
-char const *uri_val_get_printable(struct rpki_uri *);
-char const *uri_op_get_printable(struct rpki_uri *);
+char const *uri_val_get_printable(struct rpki_uri const *);
+char const *uri_op_get_printable(struct rpki_uri const *);
#endif /* SRC_URI_H_ */
error = visited_uris_to_arr(uris, &roots);
if (error)
- goto err;
+ goto end;
if (roots.len == 0)
- goto success;
+ goto end; /* success */
error = delete_dir_daemon_start(roots.array, roots.len, workspace);
- if (error)
- goto err;
-success:
- uris_roots_cleanup(&roots, uris_root_destroy);
- return 0;
-err:
+ /* Fall through*/
+
+end:
uris_roots_cleanup(&roots, uris_root_destroy);
return error;
}