+# Comment these out during releases.
+CFLAGS_DEBUG = -DDEBUG
+LDFLAGS_DEBUG = -rdynamic
+
bin_PROGRAMS = rpki_validator
rpki_validator_SOURCES = main2.c
-rpki_validator_SOURCES += certificate.h certificate.c
rpki_validator_SOURCES += common.h common.c
rpki_validator_SOURCES += debug.h debug.c
rpki_validator_SOURCES += file.h file.c
rpki_validator_SOURCES += line_file.h line_file.c
-rpki_validator_SOURCES += manifest.h manifest.c
-rpki_validator_SOURCES += tal.h tal.c
+
rpki_validator_SOURCES += asn1/content_info.h asn1/content_info.c
rpki_validator_SOURCES += asn1/decode.h asn1/decode.c
-rpki_validator_SOURCES += asn1/manifest.h asn1/manifest.c
rpki_validator_SOURCES += asn1/oid.h asn1/oid.c
-rpki_validator_SOURCES += asn1/roa.h asn1/roa.c
rpki_validator_SOURCES += asn1/signed_data.h asn1/signed_data.c
-rpki_validator_CFLAGS = -pedantic -Wall -std=gnu11 -O0 -g
-# Remove -rdynamic during the release.
-rpki_validator_LDFLAGS = -rdynamic
+rpki_validator_SOURCES += object/certificate.h object/certificate.c
+rpki_validator_SOURCES += object/manifest.h object/manifest.c
+rpki_validator_SOURCES += object/roa.h object/roa.c
+rpki_validator_SOURCES += object/signed_object.h object/signed_object.c
+rpki_validator_SOURCES += object/tal.h object/tal.c
+
+rpki_validator_CFLAGS = -pedantic -Wall -std=gnu11 -O0 -g $(CFLAGS_DEBUG)
+rpki_validator_LDFLAGS = $(LDFLAGS_DEBUG)
static int
validate(struct ContentInfo *info)
{
+ static const OID oid_sdata = OID_SIGNED_DATA;
struct oid_arcs arcs;
int error;
if (error)
return error;
- if (!ARCS_EQUAL_OIDS(&arcs, SIGNED_DATA_OID)) {
+ if (!ARCS_EQUAL_OIDS(&arcs, oid_sdata)) {
fprintf(stderr, "Incorrect content-type.");
return -EINVAL;
}
#include "common.h"
static int
-validate(asn_TYPE_descriptor_t *descriptor, void *result)
+validate(asn_TYPE_descriptor_t const *descriptor, void *result)
{
char error_msg[256];
size_t error_msg_size;
int
asn1_decode(const void *buffer, size_t buffer_size,
- asn_TYPE_descriptor_t *descriptor, void **result)
+ asn_TYPE_descriptor_t const *descriptor, void **result)
{
asn_dec_rval_t rval;
int error;
rval = ber_decode(0, descriptor, result, buffer, buffer_size);
if (rval.code != RC_OK) {
+ /* TODO if rval.code == RC_WMORE (1), more work is needed */
warnx("Error decoding ASN.1 object: %d", rval.code);
/* Must free partial object according to API contracts. */
ASN_STRUCT_FREE(*descriptor, *result);
}
int
-asn1_decode_any(ANY_t *any, asn_TYPE_descriptor_t *descriptor, void **result)
+asn1_decode_any(ANY_t *any,
+ asn_TYPE_descriptor_t const *descriptor,
+ void **result)
{
return asn1_decode(any->buf, any->size, descriptor, result);
}
int
asn1_decode_octet_string(OCTET_STRING_t *string,
- asn_TYPE_descriptor_t *descriptor, void **result)
+ asn_TYPE_descriptor_t const *descriptor,
+ void **result)
{
return asn1_decode(string->buf, string->size, descriptor, result);
}
int
-asn1_decode_fc(struct file_contents *fc, asn_TYPE_descriptor_t *descriptor,
+asn1_decode_fc(struct file_contents *fc,
+ asn_TYPE_descriptor_t const *descriptor,
void **result)
{
return asn1_decode(fc->buffer, fc->buffer_size, descriptor, result);
#include <libcmscodec/constr_TYPE.h>
#include "file.h"
-/* TODO use this more. */
-int asn1_decode(const void *, size_t, asn_TYPE_descriptor_t *, void **);
-int asn1_decode_any(ANY_t *, asn_TYPE_descriptor_t *, void **);
-int asn1_decode_octet_string(OCTET_STRING_t *, asn_TYPE_descriptor_t *, void **);
-int asn1_decode_fc(struct file_contents *, asn_TYPE_descriptor_t *, void **);
+int asn1_decode(const void *, size_t, asn_TYPE_descriptor_t const *, void **);
+int asn1_decode_any(ANY_t *, asn_TYPE_descriptor_t const *, void **);
+int asn1_decode_octet_string(OCTET_STRING_t *, asn_TYPE_descriptor_t const *,
+ void **);
+int asn1_decode_fc(struct file_contents *, asn_TYPE_descriptor_t const *,
+ void **);
#endif /* SRC_ASN1_DECODE_H_ */
+++ /dev/null
-#ifndef SRC_ASN1_MANIFEST_H_
-#define SRC_ASN1_MANIFEST_H_
-
-#include <libcmscodec/Manifest.h>
-#include <libcmscodec/SignedData.h>
-
-int manifest_decode(struct SignedData *sdata, struct Manifest **mf);
-void manifest_free(struct Manifest *mf);
-
-#endif /* SRC_ASN1_MANIFEST_H_ */
return true;
}
-bool arcs_equal(struct oid_arcs *a, struct oid_arcs *b)
+bool arcs_equal(struct oid_arcs const *a, struct oid_arcs const *b)
{
return __arcs_equal(a->arcs, a->count, b->arcs, b->count);
}
{
return __arcs_equal(arcs->arcs, arcs->count, oids, oids_len);
}
-
-void
-oid_print(OBJECT_IDENTIFIER_t *oid)
-{
- asn_fprint(stdout, &asn_DEF_OBJECT_IDENTIFIER, oid);
-}
size_t count;
};
+#define OID2ARCS(oid) { .arcs = oid, .count = ARRAY_LEN(oid) }
+
void free_arcs(struct oid_arcs *);
typedef asn_oid_arc_t OID[];
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
-static const OID SIGNED_DATA_OID = { 1, 2, 840, 113549, 1, 7, 2 };
-static const OID CONTENT_TYPE_ATTR_OID = { 1, 2, 840, 113549, 1, 9, 3 };
-static const OID MESSAGE_DIGEST_ATTR_OID = { 1, 2, 840, 113549, 1, 9, 4 };
-static const OID SIGNING_TIME_ATTR_OID = { 1, 2, 840, 113549, 1, 9, 5 };
-static const OID BINARY_SIGNING_TIME_ATTR_OID = { 1, 2, 840, 113549, 1, 9, 16,
- 2, 46 };
+#define OID_SIGNED_DATA { 1, 2, 840, 113549, 1, 7, 2 }
+#define OID_CONTENT_TYPE_ATTR { 1, 2, 840, 113549, 1, 9, 3 }
+#define OID_MESSAGE_DIGEST_ATTR { 1, 2, 840, 113549, 1, 9, 4 }
+#define OID_SIGNING_TIME_ATTR { 1, 2, 840, 113549, 1, 9, 5 }
+#define OID_BINARY_SIGNING_TIME_ATTR { 1, 2, 840, 113549, 1, 9, 16, 2, 46 }
-static const OID ROA_OID = { 1, 2, 840, 113549, 1, 9, 16, 1, 24 };
-static const OID MANIFEST_OID = { 1, 2, 840, 113549, 1, 9, 16, 1, 26 };
+#define OID_ROA { 1, 2, 840, 113549, 1, 9, 16, 1, 24 }
+#define OID_MANIFEST { 1, 2, 840, 113549, 1, 9, 16, 1, 26 }
-static const OID OID_SHA224 = { 2, 16, 840, 1, 101, 3, 4, 2, 4 };
-static const OID OID_SHA256 = { 2, 16, 840, 1, 101, 3, 4, 2, 1 };
-static const OID OID_SHA384 = { 2, 16, 840, 1, 101, 3, 4, 2, 2 };
-static const OID OID_SHA512 = { 2, 16, 840, 1, 101, 3, 4, 2, 3 };
+#define OID_SHA224 { 2, 16, 840, 1, 101, 3, 4, 2, 4 }
+#define OID_SHA256 { 2, 16, 840, 1, 101, 3, 4, 2, 1 }
+#define OID_SHA384 { 2, 16, 840, 1, 101, 3, 4, 2, 2 }
+#define OID_SHA512 { 2, 16, 840, 1, 101, 3, 4, 2, 3 }
int oid2arcs(OBJECT_IDENTIFIER_t *, struct oid_arcs *);
int any2arcs(ANY_t *, struct oid_arcs *);
-bool arcs_equal(struct oid_arcs *, struct oid_arcs *);
+bool arcs_equal(struct oid_arcs const *, struct oid_arcs const *);
/* Use ARCS_EQUAL_OID() instead. */
bool arcs_equal_oids(struct oid_arcs *, asn_oid_arc_t const *, size_t);
*/
#define ARCS_EQUAL_OIDS(a, b) arcs_equal_oids(a, b, ARRAY_LEN(b))
-void oid_print(OBJECT_IDENTIFIER_t *oid);
-
#endif /* SRC_OID_H_ */
+++ /dev/null
-#include "roa.h"
-
-#include <err.h>
-#include <errno.h>
-#include <stdbool.h>
-#include "oid.h"
-#include "asn1/decode.h"
-#include "asn1/signed_data.h"
-
-static int
-validate_eContentType(struct SignedData *sdata)
-{
- struct oid_arcs arcs;
- bool equals;
- int error;
-
- error = oid2arcs(&sdata->encapContentInfo.eContentType, &arcs);
- if (error)
- return error;
- equals = ARCS_EQUAL_OIDS(&arcs, ROA_OID);
- free_arcs(&arcs);
- if (!equals) {
- warnx("SignedObject lacks the OID of a ROA.");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int
-validate_content_type(struct SignedData *sdata)
-{
- OBJECT_IDENTIFIER_t *ctype;
- struct oid_arcs arcs;
- bool equals;
- int error;
-
- error = get_content_type_attr(sdata, &ctype);
- if (error)
- return error;
- error = oid2arcs(ctype, &arcs);
- ASN_STRUCT_FREE(asn_DEF_OBJECT_IDENTIFIER, ctype);
- if (error)
- return error;
- equals = ARCS_EQUAL_OIDS(&arcs, ROA_OID);
- free_arcs(&arcs);
- if (!equals) {
- warnx("SignedObject's content type doesn't match its encapContentInfo's eContent.");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int
-validate_roa(struct RouteOriginAttestation *roa)
-{
- struct ROAIPAddressFamily *family;
- struct ROAIPAddress *addr;
- int b; /* block counter */
- int a; /* address counter */
-
- /* rfc6482#section-3.1 */
- if (roa->version != 0) {
- warnx("ROA's version (%ld) is not zero.", roa->version);
- return -EINVAL;
- }
-
- /* rfc6482#section-3.2 */
- if (roa->ipAddrBlocks.list.array == NULL)
- return -EINVAL;
-
- for (b = 0; b < roa->ipAddrBlocks.list.count; b++) {
- family = roa->ipAddrBlocks.list.array[0];
- if (family == NULL)
- return -EINVAL;
-
- if (family->addressFamily.size != 2)
- return -EINVAL;
- if (family->addressFamily.buf[0] != 0)
- return -EINVAL;
- if (family->addressFamily.buf[1] != 1
- && family->addressFamily.buf[1] != 2)
- return -EINVAL;
-
- if (family->addresses.list.array == NULL)
- return -EINVAL;
- for (a = 0; a < family->addresses.list.count; a++) {
- addr = family->addresses.list.array[a];
- /*
- * TODO I don't understand where the prefix length is.
- * The bit string's size is measured in bytes...
- */
- printf("%ld\n", addr->maxLength
- ? (*addr->maxLength)
- : -1);
- }
- }
-
- return 0;
-}
-
-int
-roa_decode(struct SignedData *sdata, struct RouteOriginAttestation **result)
-{
- struct RouteOriginAttestation *roa;
- int error;
-
- /* rfc6482#section-2: eContentType */
- error = validate_eContentType(sdata);
- if (error)
- return error;
-
- /* rfc6482#section-2: content-type */
- error = validate_content_type(sdata);
- if (error)
- return error;
-
- error = asn1_decode_octet_string(sdata->encapContentInfo.eContent,
- &asn_DEF_RouteOriginAttestation, (void **) &roa);
- if (error)
- return -EINVAL;
-
- error = validate_roa(roa);
- if (error) {
- ASN_STRUCT_FREE(asn_DEF_RouteOriginAttestation, roa);
- return error;
- }
-
- *result = roa;
- return 0;
-}
-
-void roa_free(struct RouteOriginAttestation *roa)
-{
- ASN_STRUCT_FREE(asn_DEF_RouteOriginAttestation, roa);
-}
+++ /dev/null
-#ifndef SRC_ROA_H_
-#define SRC_ROA_H_
-
-#include <libcmscodec/RouteOriginAttestation.h>
-#include <libcmscodec/SignedData.h>
-
-int roa_decode(struct SignedData *, struct RouteOriginAttestation **);
-void roa_free(struct RouteOriginAttestation *);
-
-#endif /* SRC_ROA_H_ */
/* TODO more consistent and informative error/warning messages.*/
+static const OID oid_sha224 = OID_SHA224;
+static const OID oid_sha256 = OID_SHA256;
+static const OID oid_sha384 = OID_SHA384;
+static const OID oid_sha512 = OID_SHA512;
+static const OID oid_cta = OID_CONTENT_TYPE_ATTR;
+static const OID oid_mda = OID_MESSAGE_DIGEST_ATTR;
+static const OID oid_sta = OID_SIGNING_TIME_ATTR;
+static const OID oid_bst = OID_BINARY_SIGNING_TIME_ATTR;
+
/*
* The correctness of this function depends on @MAX_ARCS being faithful to all
* the known OIDs declared *in the project*.
if (error)
return error;
- *result = ARCS_EQUAL_OIDS(&arcs, OID_SHA224)
- || ARCS_EQUAL_OIDS(&arcs, OID_SHA256)
- || ARCS_EQUAL_OIDS(&arcs, OID_SHA384)
- || ARCS_EQUAL_OIDS(&arcs, OID_SHA512);
+ *result = ARCS_EQUAL_OIDS(&arcs, oid_sha224)
+ || ARCS_EQUAL_OIDS(&arcs, oid_sha256)
+ || ARCS_EQUAL_OIDS(&arcs, oid_sha384)
+ || ARCS_EQUAL_OIDS(&arcs, oid_sha512);
free_arcs(&arcs);
return 0;
if (error)
return error;
- if (ARCS_EQUAL_OIDS(&attrType, CONTENT_TYPE_ATTR_OID)) {
+ if (ARCS_EQUAL_OIDS(&attrType, oid_cta)) {
if (content_type_found) {
warnx("Multiple ContentTypes found.");
goto illegal_attrType;
error = validate_content_type_attribute(attr->attrValues.list.array[0], eci);
content_type_found = true;
- } else if (ARCS_EQUAL_OIDS(&attrType, MESSAGE_DIGEST_ATTR_OID)) {
+ } else if (ARCS_EQUAL_OIDS(&attrType, oid_mda)) {
if (message_digest_found) {
warnx("Multiple MessageDigests found.");
goto illegal_attrType;
error = validate_message_digest_attribute(attr->attrValues.list.array[0]);
message_digest_found = true;
- } else if (ARCS_EQUAL_OIDS(&attrType, SIGNING_TIME_ATTR_OID)) {
+ } else if (ARCS_EQUAL_OIDS(&attrType, oid_sta)) {
if (signing_time_found) {
warnx("Multiple SigningTimes found.");
goto illegal_attrType;
error = 0; /* No validations needed for now. */
signing_time_found = true;
- } else if (ARCS_EQUAL_OIDS(&attrType, BINARY_SIGNING_TIME_ATTR_OID)) {
+ } else if (ARCS_EQUAL_OIDS(&attrType, oid_bst)) {
if (binary_signing_time_found) {
warnx("Multiple BinarySigningTimes found.");
goto illegal_attrType;
return -EINVAL;
}
- /* rfc6488#section-3.2 TODO */
- /* rfc6488#section-3.3 TODO */
+ /* rfc6488#section-3.2 */
+ /* rfc6488#section-3.3 */
+ /* TODO */
return 0;
}
error = oid2arcs(&attr->attrType, &arcs);
if (error)
return -EINVAL;
- equal = ARCS_EQUAL_OIDS(&arcs, CONTENT_TYPE_ATTR_OID);
+ equal = ARCS_EQUAL_OIDS(&arcs, oid_cta);
free_arcs(&arcs);
if (equal) {
if (attr->attrValues.list.array == NULL)
+++ /dev/null
-#ifndef SRC_CERTIFICATE_H_
-#define SRC_CERTIFICATE_H_
-
-#include <stdbool.h>
-
-bool is_certificate(char const *file_name);
-int handle_certificate(char const *);
-
-#endif /* SRC_CERTIFICATE_H_ */
#define warnxerrno(msg, ...) \
warnxerror(errno, msg, ##__VA_ARGS__)
+#ifdef DEBUG
+
#define pr_debug(msg, ...) { \
printf("DBG: "); \
pr_indent(); \
pr_debug0(msg); \
}
+#else /* #ifdef DEBUG */
+
+#define pr_debug(msg, ...)
+#define pr_debug_add(msg, ...)
+#define pr_debug_rm(msg, ...)
+#define pr_debug0(msg)
+#define pr_debug0_add(msg)
+#define pr_debug0_rm(msg)
+
+#endif /* #ifdef DEBUG */
+
void pr_indent(void);
void pr_add_indent(void);
void pr_rm_indent(void);
+++ /dev/null
-#include <errno.h>
-
-#include "common.h"
-#include "manifest.h"
-#include "asn1/certificate.h"
-#include "asn1/content_info.h"
-#include "asn1/manifest.h"
-#include "asn1/roa.h"
-#include "asn1/signed_data.h"
-
-int
-try_roa(char *file_name)
-{
- struct ContentInfo *cinfo;
- struct SignedData *sdata;
- struct RouteOriginAttestation *roa;
- int error;
-
- error = content_info_load(file_name, &cinfo);
- if (error)
- return error;
-
- error = signed_data_decode(&cinfo->content, &sdata);
- if (error) {
- content_info_free(cinfo);
- return error;
- }
-
- error = roa_decode(sdata, &roa);
- if (error) {
- signed_data_free(sdata);
- content_info_free(cinfo);
- return error;
- }
-
- asn_fprint(stdout, &asn_DEF_RouteOriginAttestation, roa);
-
- roa_free(roa);
- signed_data_free(sdata);
- content_info_free(cinfo);
- return 0;
-}
-
-int
-try_manifest(char *file_name)
-{
- struct ContentInfo *cinfo;
- struct SignedData *sdata;
- struct Manifest *manifest;
- int error;
-
- error = content_info_load(file_name, &cinfo);
- if (error)
- return error;
-
- error = signed_data_decode(&cinfo->content, &sdata);
- if (error) {
- content_info_free(cinfo);
- return error;
- }
-
- error = manifest_decode(sdata, &manifest);
- if (error) {
- signed_data_free(sdata);
- content_info_free(cinfo);
- return error;
- }
-
- asn_fprint(stdout, &asn_DEF_Manifest, manifest);
-
- manifest_free(manifest);
- signed_data_free(sdata);
- content_info_free(cinfo);
- return 0;
-}
-
-int
-try_certificate(char *file_name)
-{
- struct Certificate *cert;
- int error;
-
- error = certificate_load(file_name, &cert);
- if (error)
- return error;
-
- asn_fprint(stdout, &asn_DEF_Certificate, cert);
-
- certificate_free(cert);
- return 0;
-}
-
-int
-main(int argc, char **argv)
-{
- int error;
-
- if (argc < 5) {
- pr_debug0("argc < 5");
- return -EINVAL;
- }
-
- error = try_roa(argv[1]);
- if (error)
- return error;
- error = try_manifest(argv[2]);
- if (error)
- return error;
- error = try_manifest(argv[3]);
- if (error)
- return error;
- error = try_certificate(argv[4]);
- if (error)
- return error;
-
- return 0;
-}
#include <stdlib.h>
#include <openssl/objects.h>
-#include "certificate.h"
#include "common.h"
#include "debug.h"
-#include "manifest.h"
-#include "tal.h"
+#include "object/certificate.h"
+#include "object/manifest.h"
+#include "object/tal.h"
/**
* Registers the RPKI-specific OIDs in the SSL library.
+++ /dev/null
-#include "manifest.h"
-
-#include <dirent.h>
-#include <errno.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "certificate.h"
-#include "common.h"
-#include "asn1/content_info.h"
-#include "asn1/signed_data.h"
-#include "asn1/manifest.h"
-
-bool
-is_manifest(char const *file_name)
-{
- return file_has_extension(file_name, "mft");
-}
-
-/**
- * Given manifest path @mft and its referenced file @file, returns a path
- * @file can be accessed with.
- *
- * ie. if @mft is "a/b/c.mft" and @file is "d/e/f.cer", returns "a/b/d/e/f.cer".
- *
- * The result needs to be freed in the end.
- */
-static int
-get_relative_file(char const *mft, char const *file, char **result)
-{
- char *joined;
- char *slash_pos;
- int dir_len;
-
- slash_pos = strrchr(mft, '/');
- if (slash_pos == NULL) {
- joined = malloc(strlen(file) + 1);
- if (!joined)
- return -ENOMEM;
- strcpy(joined, file);
- goto succeed;
- }
-
- dir_len = (slash_pos + 1) - mft;
- joined = malloc(dir_len + strlen(file) + 1);
- if (!joined)
- return -ENOMEM;
-
- strncpy(joined, mft, dir_len);
- strcpy(joined + dir_len, file);
-
-succeed:
- *result = joined;
- return 0;
-}
-
-static int
-handle_file(char const *mft, IA5String_t *string)
-{
- char *luri;
- int error;
-
- /* TODO This is probably not correct. */
- pr_debug_add("File %s {", string->buf);
-
- error = get_relative_file(mft, (char const *) string->buf, &luri);
- if (error)
- goto end;
-
- if (is_certificate(luri))
- error = handle_certificate(luri);
- else
- pr_debug0("Unhandled file type.");
-
- free(luri);
-end:
- pr_debug0_rm("}");
- return error;
-}
-
-static int
-__handle_manifest(char const *mft, struct Manifest *manifest)
-{
- int i;
- int error;
-
- for (i = 0; i < manifest->fileList.list.count; i++) {
- error = handle_file(mft,
- &manifest->fileList.list.array[i]->file);
- if (error)
- return error;
- }
-
- return 0;
-}
-
-int
-handle_manifest(char const *file_path)
-{
- struct ContentInfo *cinfo;
- struct SignedData *sdata;
- struct Manifest *manifest;
- int error;
-
- pr_debug_add("Manifest %s {", file_path);
-
- error = content_info_load(file_path, &cinfo);
- if (error)
- goto end1;
-
- error = signed_data_decode(&cinfo->content, &sdata);
- if (error)
- goto end2;
-
- error = manifest_decode(sdata, &manifest);
- if (error)
- goto end3;
-
- error = __handle_manifest(file_path, manifest);
-
- manifest_free(manifest);
-end3: signed_data_free(sdata);
-end2: content_info_free(cinfo);
-end1: pr_debug0_rm("}");
- return error;
-}
+++ /dev/null
-#ifndef SRC_MANIFEST_H_
-#define SRC_MANIFEST_H_
-
-#include <stdbool.h>
-
-bool is_manifest(char const *);
-int handle_manifest(char const *);
-
-#endif /* SRC_MANIFEST_H_ */
} else if (nid == NID_rpkiNotify) {
/* TODO Another fucking RFC... */
- pr_debug0("rpkiNotify");
+ pr_debug0("Unimplemented thingy: rpkiNotify");
} else if (nid == NID_caRepository) {
error = gn2uri(ad->location, &uri);
--- /dev/null
+#ifndef SRC_OBJECT_CERTIFICATE_H_
+#define SRC_OBJECT_CERTIFICATE_H_
+
+#include <stdbool.h>
+
+bool is_certificate(char const *);
+int handle_certificate(char const *);
+
+#endif /* SRC_OBJECT_CERTIFICATE_H_ */
-#include "asn1/manifest.h"
+#include "manifest.h"
-#include <err.h>
#include <errno.h>
-#include "asn1/decode.h"
+#include <libcmscodec/Manifest.h>
+
+#include "common.h"
#include "asn1/oid.h"
-#include "asn1/signed_data.h"
+#include "object/certificate.h"
+#include "object/roa.h"
+#include "object/signed_object.h"
-static int
-validate_eContentType(struct SignedData *sdata)
+bool
+is_manifest(char const *file_name)
{
- struct oid_arcs arcs;
- bool equals;
- int error;
-
- error = oid2arcs(&sdata->encapContentInfo.eContentType, &arcs);
- if (error)
- return error;
- equals = ARCS_EQUAL_OIDS(&arcs, MANIFEST_OID);
- free_arcs(&arcs);
- if (!equals) {
- warnx("SignedObject lacks the OID of a Manifest.");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int
-validate_content_type(struct SignedData *sdata)
-{
- OBJECT_IDENTIFIER_t *ctype;
- struct oid_arcs arcs;
- bool equals;
- int error;
-
- error = get_content_type_attr(sdata, &ctype);
- if (error)
- return error;
- error = oid2arcs(ctype, &arcs);
- ASN_STRUCT_FREE(asn_DEF_OBJECT_IDENTIFIER, ctype);
- if (error)
- return error;
- equals = ARCS_EQUAL_OIDS(&arcs, MANIFEST_OID);
- free_arcs(&arcs);
- if (!equals) {
- warnx("SignedObject's content type doesn't match its encapContentInfo's eContent.");
- return -EINVAL;
- }
-
- return 0;
+ return file_has_extension(file_name, "mft");
}
static int
static int
is_hash_algorithm(OBJECT_IDENTIFIER_t *aid, bool *result)
{
+ static const OID sha_oid = OID_SHA256;
struct oid_arcs arcs;
int error;
if (error)
return error;
- *result = ARCS_EQUAL_OIDS(&arcs, OID_SHA256);
+ *result = ARCS_EQUAL_OIDS(&arcs, sha_oid);
free_arcs(&arcs);
return 0;
}
-int
+static int
validate_manifest(struct Manifest *manifest)
{
int error;
return 0;
}
-int
-manifest_decode(struct SignedData *sdata, struct Manifest **result)
+/**
+ * Given manifest path @mft and its referenced file @file, returns a path
+ * @file can be accessed with.
+ *
+ * ie. if @mft is "a/b/c.mft" and @file is "d/e/f.cer", returns "a/b/d/e/f.cer".
+ *
+ * The result needs to be freed in the end.
+ */
+static int
+get_relative_file(char const *mft, char const *file, char **result)
{
- struct Manifest *manifest;
+ char *joined;
+ char *slash_pos;
+ int dir_len;
+
+ slash_pos = strrchr(mft, '/');
+ if (slash_pos == NULL) {
+ joined = malloc(strlen(file) + 1);
+ if (!joined)
+ return -ENOMEM;
+ strcpy(joined, file);
+ goto succeed;
+ }
+
+ dir_len = (slash_pos + 1) - mft;
+ joined = malloc(dir_len + strlen(file) + 1);
+ if (!joined)
+ return -ENOMEM;
+
+ strncpy(joined, mft, dir_len);
+ strcpy(joined + dir_len, file);
+
+succeed:
+ *result = joined;
+ return 0;
+}
+
+static int
+handle_file(char const *mft, IA5String_t *string)
+{
+ char *luri;
int error;
- /* rfc6486#section-4.1 */
- /* rfc6486#section-4.4.1 */
- error = validate_eContentType(sdata);
- if (error)
- return error;
+ /* TODO Treating string->buf as a C string is probably not correct. */
+ pr_debug_add("File %s {", string->buf);
- /* rfc6486#section-4.3 */
- error = validate_content_type(sdata);
+ error = get_relative_file(mft, (char const *) string->buf, &luri);
if (error)
- return error;
+ goto end;
+
+ if (is_certificate(luri))
+ error = handle_certificate(luri);
+ else if (is_roa(luri))
+ error = handle_roa(luri);
+ else
+ pr_debug0("Unhandled file type.");
+
+ free(luri);
+end:
+ pr_debug0_rm("}");
+ return error;
+}
- error = asn1_decode_octet_string(sdata->encapContentInfo.eContent,
- &asn_DEF_Manifest, (void **) &manifest);
- if (error)
- return -EINVAL;
+static int
+__handle_manifest(char const *mft, struct Manifest *manifest)
+{
+ int i;
+ int error;
- error = validate_manifest(manifest);
- if (error) {
- ASN_STRUCT_FREE(asn_DEF_Manifest, manifest);
- return error;
+ for (i = 0; i < manifest->fileList.list.count; i++) {
+ error = handle_file(mft,
+ &manifest->fileList.list.array[i]->file);
+ if (error)
+ return error;
}
- *result = manifest;
return 0;
}
-void
-manifest_free(struct Manifest *manifest)
+int
+handle_manifest(char const *file_path)
{
+ static OID oid = OID_MANIFEST;
+ struct oid_arcs arcs = OID2ARCS(oid);
+ struct Manifest *manifest;
+ int error;
+
+ error = signed_object_decode(file_path, &asn_DEF_Manifest, &arcs,
+ (void **) &manifest);
+ if (error)
+ return error;
+
+ error = validate_manifest(manifest);
+ if (!error)
+ error = __handle_manifest(file_path, manifest);
+
ASN_STRUCT_FREE(asn_DEF_Manifest, manifest);
+ return error;
}
--- /dev/null
+#ifndef SRC_OBJECT_MANIFEST_H_
+#define SRC_OBJECT_MANIFEST_H_
+
+#include <stdbool.h>
+
+bool is_manifest(char const *);
+int handle_manifest(char const *);
+
+#endif /* SRC_OBJECT_MANIFEST_H_ */
--- /dev/null
+#include "object/roa.h"
+
+#include <err.h>
+#include <errno.h>
+#include <arpa/inet.h>
+#include <libcmscodec/RouteOriginAttestation.h>
+
+#include "common.h"
+#include "asn1/oid.h"
+#include "object/signed_object.h"
+
+bool is_roa(char const *file_name)
+{
+ return file_has_extension(file_name, "roa");
+}
+
+static int
+validate_roa(struct RouteOriginAttestation *roa)
+{
+ /* rfc6482#section-3.1 */
+ if (roa->version != 0) {
+ warnx("ROA's version (%ld) is not zero.", roa->version);
+ return -EINVAL;
+ }
+
+ /* rfc6482#section-3.2 */
+ if (roa->ipAddrBlocks.list.array == NULL)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int
+print_addr(long asn, uint8_t family, struct ROAIPAddress *roa_addr)
+{
+ union {
+ struct in6_addr ip6;
+ struct in_addr ip4;
+ } addr;
+ union {
+ char ip6[INET6_ADDRSTRLEN];
+ char ip4[INET_ADDRSTRLEN];
+ } str;
+ int prefix_len;
+ const char *str2;
+ int error;
+
+ switch (family) {
+ case 1:
+ family = AF_INET;
+ break;
+ case 2:
+ family = AF_INET6;
+ break;
+ default:
+ warnx("Unknown family value: %u", family);
+ return -EINVAL;
+ }
+
+ /*
+ * TODO maybe validate roa_addr->address.size > 0,
+ * roa_addr->address.size <= actual address max size,
+ * roa_addr->address.bits_unused < 8,
+ * and roa_addr->address.buf lacks nonzero unused bits.
+ * Also test 0/0.
+ */
+
+ memset(&addr, 0, sizeof(addr));
+ memcpy(&addr, roa_addr->address.buf, roa_addr->address.size);
+ str2 = inet_ntop(family, &addr, str.ip6, sizeof(str));
+ if (str2 == NULL) {
+ error = errno;
+ warnxerrno0("Could not parse IP address");
+ return error;
+ }
+
+ prefix_len = 8 * roa_addr->address.size - roa_addr->address.bits_unused;
+
+ printf("%ld,%s/%d,", asn, str2, prefix_len);
+
+ if (roa_addr->maxLength != NULL)
+ printf("%ld", *roa_addr->maxLength);
+ else
+ printf("%d", prefix_len);
+
+ printf("\n");
+ return 0;
+}
+
+static int
+__handle_roa(struct RouteOriginAttestation *roa)
+{
+ struct ROAIPAddressFamily *block;
+ int b;
+ int a;
+ int error;
+
+ for (b = 0; b < roa->ipAddrBlocks.list.count; b++) {
+ block = roa->ipAddrBlocks.list.array[0];
+ if (block == NULL)
+ return -EINVAL;
+
+ if (block->addressFamily.size != 2)
+ return -EINVAL;
+ if (block->addressFamily.buf[0] != 0)
+ return -EINVAL;
+ if (block->addressFamily.buf[1] != 1
+ && block->addressFamily.buf[1] != 2)
+ return -EINVAL;
+
+ if (block->addresses.list.array == NULL)
+ return -EINVAL;
+ for (a = 0; a < block->addresses.list.count; a++) {
+ error = print_addr(roa->asID,
+ block->addressFamily.buf[1],
+ block->addresses.list.array[a]);
+ if (error)
+ return error;
+ }
+ }
+
+ return 0;
+}
+
+int handle_roa(char const *file)
+{
+ static OID oid = OID_ROA;
+ struct oid_arcs arcs = OID2ARCS(oid);
+ struct RouteOriginAttestation *roa;
+ int error;
+
+ error = signed_object_decode(file, &asn_DEF_RouteOriginAttestation,
+ &arcs, (void **) &roa);
+ if (error)
+ return error;
+
+ error = validate_roa(roa);
+ if (!error)
+ error = __handle_roa(roa);
+
+ ASN_STRUCT_FREE(asn_DEF_RouteOriginAttestation, roa);
+ return error;
+}
--- /dev/null
+#ifndef SRC_OBJECT_ROA_H_
+#define SRC_OBJECT_ROA_H_
+
+#include <stdbool.h>
+
+bool is_roa(char const *);
+int handle_roa(char const *);
+
+#endif /* SRC_OBJECT_ROA_H_ */
--- /dev/null
+#include "signed_object.h"
+
+#include <err.h>
+#include <errno.h>
+#include "asn1/content_info.h"
+#include "asn1/decode.h"
+#include "asn1/signed_data.h"
+
+static int
+validate_eContentType(struct SignedData *sdata,
+ asn_TYPE_descriptor_t const *descriptor,
+ struct oid_arcs const *oid)
+{
+ struct oid_arcs arcs;
+ bool equals;
+ int error;
+
+ error = oid2arcs(&sdata->encapContentInfo.eContentType, &arcs);
+ if (error)
+ return error;
+ equals = arcs_equal(&arcs, oid);
+ free_arcs(&arcs);
+ if (!equals) {
+ warnx("SignedObject's encapContentInfo lacks the OID of a %s.",
+ descriptor->name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int
+validate_content_type(struct SignedData *sdata,
+ asn_TYPE_descriptor_t const *descriptor,
+ struct oid_arcs const *oid)
+{
+ OBJECT_IDENTIFIER_t *ctype;
+ struct oid_arcs arcs;
+ bool equals;
+ int error;
+
+ error = get_content_type_attr(sdata, &ctype);
+ if (error)
+ return error;
+ error = oid2arcs(ctype, &arcs);
+ ASN_STRUCT_FREE(asn_DEF_OBJECT_IDENTIFIER, ctype);
+ if (error)
+ return error;
+ equals = arcs_equal(&arcs, oid);
+ free_arcs(&arcs);
+ if (!equals) {
+ warnx("SignedObject's content type attribute lacks the OID of a %s.",
+ descriptor->name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int
+signed_object_decode(char const *file,
+ asn_TYPE_descriptor_t const *descriptor,
+ struct oid_arcs const *oid,
+ void **result)
+{
+ struct ContentInfo *cinfo;
+ struct SignedData *sdata;
+ int error;
+
+ error = content_info_load(file, &cinfo);
+ if (error)
+ goto end1;
+
+ error = signed_data_decode(&cinfo->content, &sdata);
+ if (error)
+ goto end2;
+
+ /* rfc6482#section-2 */
+ /* rfc6486#section-4.1 */
+ /* rfc6486#section-4.4.1 */
+ error = validate_eContentType(sdata, descriptor, oid);
+ if (error)
+ goto end3;
+
+ /* rfc6482#section-2 */
+ /* rfc6486#section-4.3 */
+ error = validate_content_type(sdata, descriptor, oid);
+ if (error)
+ goto end3;
+
+ error = asn1_decode_octet_string(sdata->encapContentInfo.eContent,
+ descriptor, result);
+
+end3: signed_data_free(sdata);
+end2: content_info_free(cinfo);
+end1: return error;
+}
--- /dev/null
+#ifndef SRC_OBJECT_SIGNED_OBJECT_H_
+#define SRC_OBJECT_SIGNED_OBJECT_H_
+
+#include "asn1/oid.h"
+
+int signed_object_decode(char const *, asn_TYPE_descriptor_t const *,
+ struct oid_arcs const *, void **);
+
+#endif /* SRC_OBJECT_SIGNED_OBJECT_H_ */
-#ifndef TAL_H_
-#define TAL_H_
+#ifndef TAL_OBJECT_H_
+#define TAL_OBJECT_H_
/* This is RFC 7730. */
typedef int (*foreach_uri_cb)(char const *);
int foreach_uri(struct tal *, foreach_uri_cb);
-#endif /* TAL_H_ */
+#endif /* TAL_OBJECT_H_ */