]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Implement address block parsing (rfc3779, section 2.1)
authorAlberto Leiva Popper <ydahhrk@gmail.com>
Wed, 7 Nov 2018 16:14:20 +0000 (10:14 -0600)
committerAlberto Leiva Popper <ydahhrk@gmail.com>
Wed, 7 Nov 2018 16:14:33 +0000 (10:14 -0600)
Also, move the signed code decoding to its own module to prevent
duplicate code elsewhere

26 files changed:
src/Makefile.am
src/asn1/content_info.c
src/asn1/decode.c
src/asn1/decode.h
src/asn1/manifest.h [deleted file]
src/asn1/oid.c
src/asn1/oid.h
src/asn1/roa.c [deleted file]
src/asn1/roa.h [deleted file]
src/asn1/signed_data.c
src/certificate.h [deleted file]
src/common.h
src/main.c [deleted file]
src/main2.c
src/manifest.c [deleted file]
src/manifest.h [deleted file]
src/object/certificate.c [moved from src/certificate.c with 98% similarity]
src/object/certificate.h [new file with mode: 0644]
src/object/manifest.c [moved from src/asn1/manifest.c with 57% similarity]
src/object/manifest.h [new file with mode: 0644]
src/object/roa.c [new file with mode: 0644]
src/object/roa.h [new file with mode: 0644]
src/object/signed_object.c [new file with mode: 0644]
src/object/signed_object.h [new file with mode: 0644]
src/object/tal.c [moved from src/tal.c with 100% similarity]
src/object/tal.h [moved from src/tal.h with 74% similarity]

index 78c13a2fef705f347729b3e81e8dd38f971ae7d3..c3b4faf2a4310e04a2c8f2db0ec927e37b1eef17 100644 (file)
@@ -1,21 +1,26 @@
+# 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)
index fb79850d595ab89144ac93c68328dc458a3c7f3e..a9de4350722ad52baea517d9e344cbace17d9c71 100644 (file)
@@ -10,6 +10,7 @@
 static int
 validate(struct ContentInfo *info)
 {
+       static const OID oid_sdata = OID_SIGNED_DATA;
        struct oid_arcs arcs;
        int error;
 
@@ -19,7 +20,7 @@ validate(struct ContentInfo *info)
        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;
        }
index d0f9e4c976e5b3ad47bb5a8ff89f6f6731a3e0dd..0e6c2a93c106f58030843748685a70c192c7bba4 100644 (file)
@@ -5,7 +5,7 @@
 #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;
@@ -25,7 +25,7 @@ validate(asn_TYPE_descriptor_t *descriptor, void *result)
 
 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;
@@ -34,6 +34,7 @@ asn1_decode(const void *buffer, size_t buffer_size,
 
        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);
@@ -50,20 +51,24 @@ asn1_decode(const void *buffer, size_t buffer_size,
 }
 
 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);
index 8c9c8d9683d619fc8eb4288f26044769e0d88cf7..e20f878d86bf52b7f67549d871a4504ab203d7a5 100644 (file)
@@ -5,10 +5,11 @@
 #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_ */
diff --git a/src/asn1/manifest.h b/src/asn1/manifest.h
deleted file mode 100644 (file)
index 48434ce..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#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_ */
index 3a2fb3cbd41c9e08ac9d6e13125902c0d6bc93c2..6089ba934497b6e26984dcec4f86ffeb0186cfce 100644 (file)
@@ -83,7 +83,7 @@ static bool __arcs_equal(asn_oid_arc_t const *a, size_t a_count,
        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);
 }
@@ -93,9 +93,3 @@ bool arcs_equal_oids(struct oid_arcs *arcs, asn_oid_arc_t const *oids,
 {
        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);
-}
index 187bc0b57c1f3094a3363f0c8cbc00700af9ae54..8dbc630bcae968e39f19750f814378af5cddedd2 100644 (file)
@@ -11,6 +11,8 @@ struct oid_arcs {
        size_t count;
 };
 
+#define OID2ARCS(oid) { .arcs = oid, .count = ARRAY_LEN(oid) }
+
 void free_arcs(struct oid_arcs *);
 
 typedef asn_oid_arc_t OID[];
@@ -21,25 +23,24 @@ 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);
 
@@ -49,6 +50,4 @@ 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_ */
diff --git a/src/asn1/roa.c b/src/asn1/roa.c
deleted file mode 100644 (file)
index 3417d45..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-#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);
-}
diff --git a/src/asn1/roa.h b/src/asn1/roa.h
deleted file mode 100644 (file)
index 1404734..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#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_ */
index c07fca6c3d6ef069989dc337879030195e6bca8d..9d20ef90503d293160666ac3ac70874350751878 100644 (file)
@@ -8,6 +8,15 @@
 
 /* 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*.
@@ -22,10 +31,10 @@ is_digest_algorithm(AlgorithmIdentifier_t *aid, bool *result)
        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;
@@ -107,7 +116,7 @@ validate_signed_attrs(struct SignerInfo *sinfo, EncapsulatedContentInfo_t *eci)
                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;
@@ -115,7 +124,7 @@ validate_signed_attrs(struct SignerInfo *sinfo, EncapsulatedContentInfo_t *eci)
                        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;
@@ -123,7 +132,7 @@ validate_signed_attrs(struct SignerInfo *sinfo, EncapsulatedContentInfo_t *eci)
                        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;
@@ -131,7 +140,7 @@ validate_signed_attrs(struct SignerInfo *sinfo, EncapsulatedContentInfo_t *eci)
                        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;
@@ -298,8 +307,9 @@ validate(struct SignedData *sdata)
                return -EINVAL;
        }
 
-       /* rfc6488#section-3.2 TODO */
-       /* rfc6488#section-3.3 TODO */
+       /* rfc6488#section-3.2 */
+       /* rfc6488#section-3.3 */
+       /* TODO */
 
        return 0;
 }
@@ -360,7 +370,7 @@ get_content_type_attr(struct SignedData *sdata, OBJECT_IDENTIFIER_t **result)
                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)
diff --git a/src/certificate.h b/src/certificate.h
deleted file mode 100644 (file)
index e5a8869..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#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_ */
index d51bf6eba2f5d783d6f1194d710379a725685e84..d37cb306ec42afe5ae0697a86105b89cfd19c806 100644 (file)
@@ -26,6 +26,8 @@ extern int NID_rpkiNotify;
 #define warnxerrno(msg, ...) \
        warnxerror(errno, msg, ##__VA_ARGS__)
 
+#ifdef DEBUG
+
 #define pr_debug(msg, ...) {                   \
        printf("DBG: ");                        \
        pr_indent();                            \
@@ -54,6 +56,17 @@ extern int NID_rpkiNotify;
        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);
diff --git a/src/main.c b/src/main.c
deleted file mode 100644 (file)
index a5a2069..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-#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;
-}
index f06d65ceed885ae33a16b7562e4c8c8ebdb45871..c3e1a2c3432a8f7cd78ea8325b8b410bee384b10 100644 (file)
@@ -3,11 +3,11 @@
 #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.
diff --git a/src/manifest.c b/src/manifest.c
deleted file mode 100644 (file)
index 3571b43..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-#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;
-}
diff --git a/src/manifest.h b/src/manifest.h
deleted file mode 100644 (file)
index a26c879..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#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_ */
similarity index 98%
rename from src/certificate.c
rename to src/object/certificate.c
index 78cef2f5576894d1b091fad96498675b8f1e8405..a09ee6e124324df0deb2e21f2b6468635e2b8b89 100644 (file)
@@ -99,7 +99,7 @@ handle_extensions(X509 *cert)
 
                } 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);
diff --git a/src/object/certificate.h b/src/object/certificate.h
new file mode 100644 (file)
index 0000000..9e89fc2
--- /dev/null
@@ -0,0 +1,9 @@
+#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_ */
similarity index 57%
rename from src/asn1/manifest.c
rename to src/object/manifest.c
index 88b5fb90acb9caf598ed88ab2b9bde871a36658d..8bc791014fa06dae2f28a2fd3d8befea9c9eb2d8 100644 (file)
@@ -1,54 +1,18 @@
-#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
@@ -61,6 +25,7 @@ validate_dates(GeneralizedTime_t *this, GeneralizedTime_t *next)
 static int
 is_hash_algorithm(OBJECT_IDENTIFIER_t *aid, bool *result)
 {
+       static const OID sha_oid = OID_SHA256;
        struct oid_arcs arcs;
        int error;
 
@@ -68,13 +33,13 @@ is_hash_algorithm(OBJECT_IDENTIFIER_t *aid, bool *result)
        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;
@@ -150,40 +115,102 @@ validate_manifest(struct Manifest *manifest)
        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;
 }
diff --git a/src/object/manifest.h b/src/object/manifest.h
new file mode 100644 (file)
index 0000000..00156fa
--- /dev/null
@@ -0,0 +1,9 @@
+#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_ */
diff --git a/src/object/roa.c b/src/object/roa.c
new file mode 100644 (file)
index 0000000..c2a4a7f
--- /dev/null
@@ -0,0 +1,143 @@
+#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;
+}
diff --git a/src/object/roa.h b/src/object/roa.h
new file mode 100644 (file)
index 0000000..9795c39
--- /dev/null
@@ -0,0 +1,9 @@
+#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_ */
diff --git a/src/object/signed_object.c b/src/object/signed_object.c
new file mode 100644 (file)
index 0000000..3fe3062
--- /dev/null
@@ -0,0 +1,97 @@
+#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;
+}
diff --git a/src/object/signed_object.h b/src/object/signed_object.h
new file mode 100644 (file)
index 0000000..9311d1f
--- /dev/null
@@ -0,0 +1,9 @@
+#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_ */
similarity index 100%
rename from src/tal.c
rename to src/object/tal.c
similarity index 74%
rename from src/tal.h
rename to src/object/tal.h
index 6ef5ad249663de6664ecd4025f1c98a1ca0c9951..9e8970428e8f2f3a8228ddf7d00df66a79b058eb 100644 (file)
--- a/src/tal.h
@@ -1,5 +1,5 @@
-#ifndef TAL_H_
-#define TAL_H_
+#ifndef TAL_OBJECT_H_
+#define TAL_OBJECT_H_
 
 /* This is RFC 7730. */
 
@@ -11,4 +11,4 @@ void tal_destroy(struct tal *);
 typedef int (*foreach_uri_cb)(char const *);
 int foreach_uri(struct tal *, foreach_uri_cb);
 
-#endif /* TAL_H_ */
+#endif /* TAL_OBJECT_H_ */