]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Add --file-type
authorAlberto Leiva Popper <ydahhrk@gmail.com>
Tue, 30 Apr 2024 21:43:41 +0000 (15:43 -0600)
committerAlberto Leiva Popper <ydahhrk@gmail.com>
Tue, 30 Apr 2024 21:44:53 +0000 (15:44 -0600)
Allows the user to bypass the file type guesser. For example, to force
the ROA parser:

$ fort --mode=print --file-type roa abcd.bin

Progress for #122.

src/Makefile.am
src/config.c
src/config.h
src/config/file_type.c [new file with mode: 0644]
src/config/file_type.h [new file with mode: 0644]
src/print_file.c

index a6d44c5432795dba4bb5394294a8fa30c9377177..8c0aa1fb4047b2475b217f24f8f7f4fe4bff90c3 100644 (file)
@@ -49,6 +49,7 @@ fort_SOURCES += types/vrp.c types/vrp.h
 fort_SOURCES += cache/local_cache.c cache/local_cache.h
 
 fort_SOURCES += config/boolean.c config/boolean.h
+fort_SOURCES += config/file_type.h config/file_type.c
 fort_SOURCES += config/filename_format.h config/filename_format.c
 fort_SOURCES += config/log_conf.h config/log_conf.c
 fort_SOURCES += config/mode.c config/mode.h
index 224596d2235b38db9297ac9566d50ce036c297d1..0843a679f48fd346335a2769b31eb2e85342146e 100644 (file)
@@ -193,6 +193,7 @@ struct rpki_config {
                } validation;
        } thread_pool;
 
+       enum file_type ft;
        char *payload;
 };
 
@@ -767,6 +768,13 @@ static const struct option_field options[] = {
                .max = 100,
        },
 
+       {
+               .id = 13000,
+               .name = "file-type",
+               .type = &gt_file_type,
+               .offset = offsetof(struct rpki_config, ft),
+               .doc = "Parser for --mode=print",
+       },
        { 0 },
 };
 
@@ -1458,6 +1466,12 @@ config_get_thread_pool_server_max(void)
        return rpki_config.thread_pool.server.max;
 }
 
+enum file_type
+config_get_file_type(void)
+{
+       return rpki_config.ft;
+}
+
 char const *
 config_get_payload(void)
 {
index 18cfa23f30d2f9ca9238093d5f91a98b9ce5dead..f4a480f3eb545a04da8c01346399d368a4c7a0a7 100644 (file)
@@ -6,6 +6,7 @@
 #include <netinet/in.h>
 #include <stdint.h>
 
+#include "config/file_type.h"
 #include "config/filename_format.h"
 #include "config/log_conf.h"
 #include "config/mode.h"
@@ -55,6 +56,7 @@ char const *config_get_output_bgpsec(void);
 enum output_format config_get_output_format(void);
 unsigned int config_get_asn1_decode_max_stack(void);
 unsigned int config_get_thread_pool_server_max(void);
+enum file_type config_get_file_type(void);
 char const *config_get_payload(void);
 
 /* Logging getters */
diff --git a/src/config/file_type.c b/src/config/file_type.c
new file mode 100644 (file)
index 0000000..5c2535a
--- /dev/null
@@ -0,0 +1,82 @@
+#include "config/file_type.h"
+
+#include <getopt.h>
+
+#include "log.h"
+#include "config/str.h"
+
+#define VALUE_ROA      "roa"
+#define VALUE_MFT      "mft"
+#define VALUE_GBR      "gbr"
+#define VALUE_CER      "cer"
+#define VALUE_CRL      "crl"
+
+#define DEREFERENCE(void_value) (*((enum file_type *) void_value))
+
+static void
+print_file_type(struct option_field const *field, void *value)
+{
+       char const *str = NULL;
+
+       switch (DEREFERENCE(value)) {
+       case FT_UNK:
+               break;
+       case FT_ROA:
+               str = VALUE_ROA;
+               break;
+       case FT_MFT:
+               str = VALUE_MFT;
+               break;
+       case FT_GBR:
+               str = VALUE_GBR;
+               break;
+       case FT_CER:
+               str = VALUE_CER;
+               break;
+       case FT_CRL:
+               str = VALUE_CRL;
+               break;
+       }
+
+       pr_op_info("%s: %s", field->name, str);
+}
+
+static int
+parse_argv_mode(struct option_field const *field, char const *str,
+    void *result)
+{
+       if (strcmp(str, VALUE_ROA) == 0)
+               DEREFERENCE(result) = FT_ROA;
+       else if (strcmp(str, VALUE_MFT) == 0)
+               DEREFERENCE(result) = FT_MFT;
+       else if (strcmp(str, VALUE_GBR) == 0)
+               DEREFERENCE(result) = FT_GBR;
+       else if (strcmp(str, VALUE_CER) == 0)
+               DEREFERENCE(result) = FT_CER;
+       else if (strcmp(str, VALUE_CRL) == 0)
+               DEREFERENCE(result) = FT_CRL;
+       else
+               return pr_op_err("Unknown file type: '%s'", str);
+
+       return 0;
+}
+
+static int
+parse_json_mode(struct option_field const *opt, struct json_t *json,
+    void *result)
+{
+       char const *string;
+       int error;
+
+       error = parse_json_string(json, opt->name, &string);
+       return error ? error : parse_argv_mode(opt, string, result);
+}
+
+const struct global_type gt_file_type = {
+       .has_arg = required_argument,
+       .size = sizeof(enum file_type),
+       .print = print_file_type,
+       .parse.argv = parse_argv_mode,
+       .parse.json = parse_json_mode,
+       .arg_doc = VALUE_ROA "|" VALUE_MFT "|" VALUE_GBR "|" VALUE_CER "|" VALUE_CRL,
+};
diff --git a/src/config/file_type.h b/src/config/file_type.h
new file mode 100644 (file)
index 0000000..d995e54
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef SRC_CONFIG_FILE_TYPE_H_
+#define SRC_CONFIG_FILE_TYPE_H_
+
+#include "config/types.h"
+
+enum file_type {
+       FT_UNK,
+       FT_ROA,
+       FT_MFT,
+       FT_GBR,
+       FT_CER,
+       FT_CRL,
+};
+
+extern const struct global_type gt_file_type;
+
+#endif /* SRC_CONFIG_FILE_TYPE_H_ */
index 2e08a1caabf0e1145c014f5b8274298c44c3c2ae..b310d41c7d6ac3825f97b8a9181cf1088a022f6d 100644 (file)
@@ -9,13 +9,6 @@
 #include "asn1/asn1c/Certificate.h"
 #include "asn1/asn1c/CRL.h"
 
-enum file_type {
-       FT_UNKNOWN,
-       FT_SIGNED_OBJECT,
-       FT_CERTIFICATE,
-       FT_CRL,
-};
-
 #define HDRSIZE 32
 
 static unsigned char *
@@ -52,45 +45,48 @@ guess_file_type(FILE *file)
        unsigned char buf[HDRSIZE];
        unsigned char *ptr;
 
+       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_UNKNOWN;
+               return FT_UNK;
        }
        rewind(file);
 
        if (buf[0] != 0x30) {
                pr_op_debug("File doesn't start with a SEQUENCE.");
-               return FT_UNKNOWN;
+               return FT_UNK;
        }
        ptr = skip_sequence(buf, buf + 1);
        if (ptr == NULL) {
                pr_op_debug("Cannot skip first sequence length.");
-               return FT_UNKNOWN;
+               return FT_UNK;
        }
 
        if (*ptr == 0x06) {
                pr_op_debug("SEQ containing OID.");
-               return FT_SIGNED_OBJECT;
+               return FT_ROA; /* Same parser for mfts and gbrs */
        }
        if (*ptr != 0x30) {
                pr_op_debug("SEQ containing unexpected: 0x%x", *ptr);
-               return FT_UNKNOWN;
+               return FT_UNK;
        }
 
        ptr = skip_sequence(buf, ptr + 1);
        if (ptr == NULL) {
                pr_op_debug("Cannot skip second sequence length.");
-               return FT_UNKNOWN;
+               return FT_UNK;
        }
        ptr = skip_integer(buf, ptr + 1);
        if (ptr == NULL) {
                pr_op_debug("Cannot skip version number.");
-               return FT_UNKNOWN;
+               return FT_UNK;
        }
 
        if (*ptr == 0x02) {
                pr_op_debug("SEQ containing SEQ containing (INT, INT).");
-               return FT_CERTIFICATE;
+               return FT_CER;
        }
        if (*ptr == 0x30) {
                pr_op_debug("SEQ containing SEQ containing (INT, SEQ).");
@@ -98,7 +94,7 @@ guess_file_type(FILE *file)
        }
 
        pr_op_debug("SEQ containing SEQ containing unexpected: 0x%x", *ptr);
-       return FT_UNKNOWN;
+       return FT_UNK;
 }
 
 static struct ContentInfo *
@@ -178,13 +174,15 @@ print_file(void)
                return pr_op_err("Cannot open file: %s", strerror(errno));
 
        switch (guess_file_type(file)) {
-       case FT_UNKNOWN:
+       case FT_UNK:
                error = pr_op_err("Unrecognized file type.");
                break;
-       case FT_SIGNED_OBJECT:
+       case FT_ROA:
+       case FT_MFT:
+       case FT_GBR:
                json = asn1c2json(file);
                break;
-       case FT_CERTIFICATE:
+       case FT_CER:
                json = Certificate_file2json(file);
                break;
        case FT_CRL: