From: Alberto Leiva Popper Date: Tue, 30 Apr 2024 21:43:41 +0000 (-0600) Subject: Add --file-type X-Git-Tag: 1.6.2~32 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e7f04a1f645fefe5022e010d2ebc9cd53a5b8205;p=thirdparty%2FFORT-validator.git Add --file-type 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. --- diff --git a/src/Makefile.am b/src/Makefile.am index a6d44c54..8c0aa1fb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 diff --git a/src/config.c b/src/config.c index 224596d2..0843a679 100644 --- a/src/config.c +++ b/src/config.c @@ -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 = >_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) { diff --git a/src/config.h b/src/config.h index 18cfa23f..f4a480f3 100644 --- a/src/config.h +++ b/src/config.h @@ -6,6 +6,7 @@ #include #include +#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 index 00000000..5c2535a0 --- /dev/null +++ b/src/config/file_type.c @@ -0,0 +1,82 @@ +#include "config/file_type.h" + +#include + +#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 index 00000000..d995e546 --- /dev/null +++ b/src/config/file_type.h @@ -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_ */ diff --git a/src/print_file.c b/src/print_file.c index 2e08a1ca..b310d41c 100644 --- a/src/print_file.c +++ b/src/print_file.c @@ -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: