]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Add sequence BIO
authorAlberto Leiva Popper <ydahhrk@gmail.com>
Wed, 8 May 2024 16:48:09 +0000 (10:48 -0600)
committerAlberto Leiva Popper <ydahhrk@gmail.com>
Wed, 8 May 2024 16:48:09 +0000 (10:48 -0600)
It's a BIO that concatenates two other BIOs when reading.
Needed so the file parser can read the file header twice, without using
rewind(3).

(Which can't be used while piping, as it turns out.)

This allows printing a subfile from a delta or snapshot:

$ xmlstarlet sel -t -v "//_:publish[2]" delta.xml |
base64 --decode |
fort --mode=print

src/Makefile.am
src/asn1/asn1c/CRL.c
src/asn1/asn1c/CRL.h
src/asn1/asn1c/Certificate.c
src/asn1/asn1c/Certificate.h
src/asn1/asn1c/ROAIPAddressFamily.c
src/print_file.c
src/types/bio_seq.c [new file with mode: 0644]
src/types/bio_seq.h [new file with mode: 0644]

index 8c0aa1fb4047b2475b217f24f8f7f4fe4bff90c3..987acb4bfa567b53d373e864de4f5432f4aabc94 100644 (file)
@@ -40,6 +40,7 @@ fort_SOURCES += asn1/oid.h asn1/oid.c
 fort_SOURCES += asn1/signed_data.h asn1/signed_data.c
 
 fort_SOURCES += types/address.h types/address.c
+fort_SOURCES += types/bio_seq.c types/bio_seq.h
 fort_SOURCES += types/delta.c types/delta.h
 fort_SOURCES += types/router_key.c types/router_key.h
 fort_SOURCES += types/serial.h types/serial.c
index f84ac734c641d46ecd5a23c14c8dd8ec7de74add..e0c3a05536cdaf1771490df6946706a2ed6367f9 100644 (file)
@@ -108,12 +108,12 @@ fail:     json_decref(root);
 }
 
 json_t *
-CRL_file2json(FILE *file)
+CRL_bio2json(BIO *bio)
 {
        X509_CRL *crl;
        json_t *root;
 
-       crl = d2i_X509_CRL_fp(file, NULL);
+       crl = d2i_X509_CRL_bio(bio, NULL);
        if (crl == NULL)
                return NULL;
 
index c49c8b8c1407bc5717a9096fed5d0ef8f3c538bd..7f7c7d23b98db3936aa88f5941eb25e91a4b1dca 100644 (file)
@@ -1,9 +1,9 @@
 #ifndef SRC_ASN1_ASN1C_CRL_H_
 #define SRC_ASN1_ASN1C_CRL_H_
 
-#include <stdio.h>
 #include <jansson.h>
+#include <openssl/bio.h>
 
-json_t *CRL_file2json(FILE *);
+json_t *CRL_bio2json(BIO *bio);
 
 #endif /* SRC_ASN1_ASN1C_CRL_H_ */
index 0defcac8e80285507d93b799536a1794117b6800..571f487d15a97ee9a775b7f9d9a81e3f89b629dd 100644 (file)
@@ -190,12 +190,12 @@ Certificate_any2json(ANY_t *ber)
 }
 
 json_t *
-Certificate_file2json(FILE *file)
+Certificate_bio2json(BIO *bio)
 {
        X509 *cert;
        json_t *root;
 
-       cert = d2i_X509_fp(file, NULL);
+       cert = d2i_X509_bio(bio, NULL);
        if (cert == NULL)
                return NULL;
 
index 6400f31a1afd0dda0019b99a9dc2cc86b750f4e3..1eeac081ca2871aacf36d56285361b1036124171 100644 (file)
@@ -1,11 +1,11 @@
 #ifndef SRC_ASN1_ASN1C_CERTIFICATE_H_
 #define SRC_ASN1_ASN1C_CERTIFICATE_H_
 
-#include <stdio.h>
 #include <jansson.h>
+#include <openssl/bio.h>
 #include "asn1/asn1c/ANY.h"
 
 json_t *Certificate_any2json(ANY_t *);
-json_t *Certificate_file2json(FILE *);
+json_t *Certificate_bio2json(BIO *);
 
 #endif /* SRC_ASN1_ASN1C_CERTIFICATE_H_ */
index 3b78b14fdd5f59ae867674685b2f3507bedde47f..c62ae1e0d0046ad01c72928058fd74f9361147b0 100644 (file)
@@ -61,23 +61,16 @@ AddrBlock2json(struct ROAIPAddressFamily const *riaf, char const *ipname,
     json_t *(*pref2json)(struct ROAIPAddress *))
 {
        json_t *root;
-       json_t *family, *addresses;
+       json_t *addrs;
        int i;
 
        root = json_object();
        if (root == NULL)
                return NULL;
 
-       family = json_string(ipname);
-       if (family == NULL)
+       if (json_object_set_new(root, "addressFamily", json_string(ipname)) < 0)
                goto fail;
-       if (json_object_set_new(root, "addressFamily", family) < 0)
-               goto fail;
-
-       addresses = json_array();
-       if (addresses == NULL)
-               goto fail;
-       if (json_object_set_new(root, "addresses", addresses) < 0)
+       if (json_object_set_new(root, "addresses", addrs = json_array()) < 0)
                goto fail;
 
        for (i = 0; i < riaf->addresses.list.count; i++) {
@@ -85,14 +78,10 @@ AddrBlock2json(struct ROAIPAddressFamily const *riaf, char const *ipname,
                json_t *prefix, *maxlen;
 
                prefix = pref2json(src);
-               if (prefix == NULL)
-                       goto fail;
-               if (json_array_append_new(addresses, prefix))
+               if (json_array_append_new(addrs, prefix))
                        goto fail;
 
                maxlen = asn_DEF_INTEGER.op->json_encoder(&asn_DEF_INTEGER, src->maxLength);
-               if (maxlen == NULL)
-                       goto fail;
                if (json_object_set_new(prefix, "maxLength", maxlen))
                        goto fail;
        }
index 7bb4572cf80207dc381a4104bdadbaa7d4c588ad..c5d92e619b1c8117895b0c3f307b5a5a765072a9 100644 (file)
@@ -8,6 +8,7 @@
 #include "asn1/content_info.h"
 #include "asn1/asn1c/Certificate.h"
 #include "asn1/asn1c/CRL.h"
+#include "types/bio_seq.h"
 
 #define HDRSIZE 32
 
@@ -31,34 +32,33 @@ skip_integer(unsigned char *buf, unsigned char *cursor)
        ssize_t len_len;
 
        len_len = ber_fetch_length(0, cursor, HDRSIZE - (cursor - buf), &len);
-       if (len_len <= 0) {
-               pr_op_debug("aoe");
+       if (len_len <= 0)
                return NULL;
-       }
        cursor += len_len + len;
        return (cursor <= (buf + HDRSIZE)) ? cursor : NULL;
 }
 
 static int
-guess_file_type(FILE *file)
+guess_file_type(BIO **bio, unsigned char *hdrbuf)
 {
-       unsigned char buf[HDRSIZE];
        unsigned char *ptr;
+       size_t consumed;
 
        if (config_get_file_type() != FT_UNK)
                return config_get_file_type();
 
-       if (fread(buf, 1, HDRSIZE, file) != HDRSIZE) {
-               pr_op_debug("File is too small or generic IO error.");
-               return FT_UNK;
-       }
-       rewind(file);
+       if (!BIO_read_ex(*bio, hdrbuf, HDRSIZE, &consumed))
+               return op_crypto_err("Cannot guess file type; IO error.");
+
+       *bio = BIO_new_seq(BIO_new_mem_buf(hdrbuf, consumed), *bio);
+       if ((*bio) == NULL)
+               return op_crypto_err("BIO_new_seq() returned NULL.");
 
-       if (buf[0] != 0x30) {
+       if (hdrbuf[0] != 0x30) {
                pr_op_debug("File doesn't start with a SEQUENCE.");
                return FT_UNK;
        }
-       ptr = skip_sequence(buf, buf + 1);
+       ptr = skip_sequence(hdrbuf, hdrbuf + 1);
        if (ptr == NULL) {
                pr_op_debug("Cannot skip first sequence length.");
                return FT_UNK;
@@ -73,12 +73,12 @@ guess_file_type(FILE *file)
                return FT_UNK;
        }
 
-       ptr = skip_sequence(buf, ptr + 1);
+       ptr = skip_sequence(hdrbuf, ptr + 1);
        if (ptr == NULL) {
                pr_op_debug("Cannot skip second sequence length.");
                return FT_UNK;
        }
-       ptr = skip_integer(buf, ptr + 1);
+       ptr = skip_integer(hdrbuf, ptr + 1);
        if (ptr == NULL) {
                pr_op_debug("Cannot skip version number.");
                return FT_UNK;
@@ -98,44 +98,37 @@ guess_file_type(FILE *file)
 }
 
 static struct ContentInfo *
-file2ci(FILE *file)
+bio2ci(BIO *bio)
 {
-#define BUFFER_SIZE 1024
+#define BUFFER_SIZE 4096
        struct ContentInfo *ci = NULL;
        unsigned char buffer[BUFFER_SIZE];
        size_t consumed;
-       bool eof;
+//     bool eof;
        asn_dec_rval_t res;
 
-       eof = false;
+//     eof = false;
        do {
-               consumed = fread(buffer, 1, BUFFER_SIZE, file);
-               if (consumed < BUFFER_SIZE) {
-                       if (feof(file)) {
-                               eof = true;
-                       } else if (ferror(file)) {
-                               pr_op_err("ferror.");
-                               return NULL;
-                       } else {
-                               pr_op_err("?");
-                               return NULL;
-                       }
+               if (!BIO_read_ex(bio, buffer, BUFFER_SIZE, &consumed)) {
+                       op_crypto_err("IO error.");
+                       return NULL;
                }
 
-               res = ber_decode(NULL, &asn_DEF_ContentInfo, (void **)&ci, buffer, consumed);
+               res = ber_decode(NULL, &asn_DEF_ContentInfo, (void **)&ci,
+                                buffer, consumed);
                pr_op_debug("Consumed: %zu", res.consumed);
 
                switch (res.code) {
                case RC_OK:
-                       if (!eof)
-                               pr_op_warn("File has trailing bytes.");
+//                     if (!buf->eof)
+//                             pr_op_warn("File has trailing bytes.");
                        return ci;
 
                case RC_WMORE:
-                       if (eof) {
-                               pr_op_err("File ended prematurely.");
-                               return NULL;
-                       }
+//                     if (buf->eof) {
+//                             pr_op_err("File ended prematurely.");
+//                             return NULL;
+//                     }
                        break;
 
                case RC_FAIL:
@@ -146,12 +139,12 @@ file2ci(FILE *file)
 }
 
 static json_t *
-asn1c2json(FILE *file)
+asn1c2json(BIO *bio)
 {
        struct ContentInfo *ci;
        json_t *json;
 
-       ci = file2ci(file);
+       ci = bio2ci(bio);
        if (ci == NULL)
                return NULL;
 
@@ -161,43 +154,41 @@ asn1c2json(FILE *file)
        return json;
 }
 
-int
-print_file(void)
+static int
+__print_file(void)
 {
-       char const *filename = config_get_payload();
-       FILE *file;
+       char const *filename;
+       BIO *bio;
+       unsigned char hdrbuf[HDRSIZE];
        json_t *json = NULL;
-       int error = 0;
+       int error;
 
-       if (filename == NULL || strcmp(filename, "-") == 0) {
-               file = stdin;
-       } else {
-               file = fopen(filename, "rb");
-               if (file == NULL)
-                       return pr_op_err("Cannot open file: %s", strerror(errno));
-       }
+       filename = config_get_payload();
+       bio = (filename == NULL || strcmp(filename, "-") == 0)
+           ? BIO_new_fp(stdin, BIO_NOCLOSE)
+           : BIO_new_file(filename, "rb");
+       if (bio == NULL)
+               return pr_op_err("BIO_new_*() returned NULL.");
 
-       switch (guess_file_type(file)) {
+       switch (guess_file_type(&bio, hdrbuf)) {
        case FT_UNK:
-               error = pr_op_err("Unrecognized file type.");
-               break;
+               BIO_free_all(bio);
+               return pr_op_err("Unrecognized file type.");
+
        case FT_ROA:
        case FT_MFT:
        case FT_GBR:
-               json = asn1c2json(file);
+               json = asn1c2json(bio);
                break;
        case FT_CER:
-               json = Certificate_file2json(file);
+               json = Certificate_bio2json(bio);
                break;
        case FT_CRL:
-               json = CRL_file2json(file);
+               json = CRL_bio2json(bio);
                break;
        }
 
-       if (file != stdin)
-               fclose(file);
-       if (error)
-               return error;
+       BIO_free_all(bio);
        if (json == NULL)
                return pr_op_err("Unable to parse.");
 
@@ -208,11 +199,27 @@ print_file(void)
                        pr_op_err("Error writing JSON to file: %s", strerror(error));
                else
                        pr_op_err("Unknown error writing JSON to file.");
-               goto end;
+
+       } else {
+               error = 0;
+               printf("\n");
        }
 
-       error = 0;
-       printf("\n");
-end:   json_decref(json);
+       json_decref(json);
+       return error;
+}
+
+int
+print_file(void)
+{
+       int error;
+
+       error = bioseq_setup();
+       if (error)
+               return error;
+
+       error = __print_file();
+
+       bioseq_teardown();
        return error;
 }
diff --git a/src/types/bio_seq.c b/src/types/bio_seq.c
new file mode 100644 (file)
index 0000000..c11c377
--- /dev/null
@@ -0,0 +1,99 @@
+#include "types/bio_seq.h"
+
+#include "log.h"
+#include "alloc.h"
+
+static BIO_METHOD *method;
+
+struct bioseq_priv {
+       BIO *prefix;
+       BIO *suffix;
+};
+
+static int
+bioseq_read_ex(BIO *bio, char *data, size_t len, size_t *consumed)
+{
+       struct bioseq_priv *priv = BIO_get_data(bio);
+       int res;
+
+       if (priv->prefix != NULL) {
+               res = BIO_read_ex(priv->prefix, data, len, consumed);
+               if (res == 1 && BIO_eof(priv->prefix)) {
+                       BIO_free_all(priv->prefix);
+                       priv->prefix = NULL;
+               }
+               return res;
+       }
+
+       return BIO_read_ex(priv->suffix, data, len, consumed);
+}
+
+static int
+bioseq_destroy(BIO *bio)
+{
+       struct bioseq_priv *priv;
+
+       if (bio == NULL)
+               return 0;
+
+       priv = BIO_get_data(bio);
+       BIO_free(priv->prefix);
+       BIO_free(priv->suffix);
+       free(priv);
+
+       BIO_set_data(bio, NULL);
+       BIO_set_init(bio, 0);
+
+       return 1;
+}
+
+int
+bioseq_setup(void)
+{
+       int type;
+
+       type = BIO_get_new_index();
+       if (type == -1)
+               return op_crypto_err("BIO_get_new_index() returned -1.");
+
+       method = BIO_meth_new(type | BIO_TYPE_FILTER, "seq");
+       if (method == NULL)
+               return op_crypto_err("BIO_meth_new() returned NULL.");
+
+       if (!BIO_meth_set_read_ex(method, bioseq_read_ex) ||
+           !BIO_meth_set_destroy(method, bioseq_destroy)) {
+               BIO_meth_free(method);
+               method = NULL;
+               return op_crypto_err("BIO_meth_set_*() returned 0.");
+       }
+
+       return 0;
+}
+
+void
+bioseq_teardown(void)
+{
+       BIO_meth_free(method);
+}
+
+BIO *
+BIO_new_seq(BIO *prefix, BIO *suffix)
+{
+       BIO *bio;
+       struct bioseq_priv *priv;
+
+       if (prefix == NULL || suffix == NULL)
+               return NULL;
+
+       bio = BIO_new(method);
+       if (bio == NULL)
+               return NULL;
+
+       priv = pmalloc(sizeof(struct bioseq_priv));
+       priv->prefix = prefix;
+       priv->suffix = suffix;
+
+       BIO_set_data(bio, priv);
+       BIO_set_init(bio, 1);
+       return bio;
+}
diff --git a/src/types/bio_seq.h b/src/types/bio_seq.h
new file mode 100644 (file)
index 0000000..ad3ba81
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef TEST_TYPES_BIO_SEQ_H_
+#define TEST_TYPES_BIO_SEQ_H_
+
+#include <openssl/bio.h>
+
+int bioseq_setup(void);
+void bioseq_teardown(void);
+
+BIO *BIO_new_seq(BIO *, BIO *);
+
+#endif /* TEST_TYPES_BIO_SEQ_H_ */