From: pcarana Date: Mon, 28 Oct 2019 23:38:54 +0000 (-0600) Subject: Add 'asn1-decode-max-stack' arg to set max stack size when decoding ASN1 X-Git-Tag: v1.2.0~64 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=e13608b0038fa85ae22886e0be407c3eb3c9ce73;p=thirdparty%2FFORT-validator.git Add 'asn1-decode-max-stack' arg to set max stack size when decoding ASN1 --- diff --git a/docs/usage.md b/docs/usage.md index 7c8e4b13..d646c068 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -36,11 +36,12 @@ command: fort 21. [`--log.file-name-format`](#--logfile-name-format) 22. [`--output.roa`](#--outputroa) 23. [`--output.bgpsec`](#--outputbgpsec) - 24. [`--configuration-file`](#--configuration-file) - 25. [`rsync.program`](#rsyncprogram) - 26. [`rsync.arguments-recursive`](#rsyncarguments-recursive) - 27. [`rsync.arguments-flat`](#rsyncarguments-flat) - 28. [`incidences`](#incidences) + 24. [`--asn1-decode-max-stack`](#--asn1-decode-max-stack) + 25. [`--configuration-file`](#--configuration-file) + 26. [`rsync.program`](#rsyncprogram) + 27. [`rsync.arguments-recursive`](#rsyncarguments-recursive) + 28. [`rsync.arguments-flat`](#rsyncarguments-flat) + 29. [`incidences`](#incidences) ## Syntax @@ -465,6 +466,17 @@ Each line of the result is printed in the following order: _AS, Subject Key Iden If a value isn't specified, then the BGPsec Router Keys aren't printed. +### `--asn1-decode-max-stack` + +- **Type:** Integer +- **Availability:** `argv` and JSON +- **Default:** 4096 +- **Range:** 1--[`UINT_MAX`](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html) + +ASN1 decoder max allowed stack size in bytes, utilized to avoid a stack overflow when a large nested ASN1 object is parsed. + +This check is merely a caution, since ASN1 decoding functions are recursive and might cause a stack overflow. So, this argument probably won't be necessary in most cases, since the RPKI ASN1 objects don't have nested objects that require too much stack allocation (for now). + ### `--configuration-file` - **Type:** String (Path to file) diff --git a/examples/config.json b/examples/config.json index 6e1b7f1f..45f2b4e5 100644 --- a/examples/config.json +++ b/examples/config.json @@ -54,5 +54,6 @@ "output": { "roa": "/tmp/fort/roas.csv", "bgpsec": "/tmp/fort/bgpsec.csv" - } + }, + "asn1-decode-max-stack": 4096 } diff --git a/man/fort.8 b/man/fort.8 index 5f18690e..fcf0679a 100644 --- a/man/fort.8 +++ b/man/fort.8 @@ -541,6 +541,15 @@ value, eg. .B \-\-output.bgpsec=- .RE +.B \-\-asn1-decode-max-stack=\fIUNSIGNED_INTEGER\fR +.RS 4 +ASN1 decoder max allowed stack size in bytes, utilized to avoid a stack +overflow when a large nested ASN1 object is parsed. +.P +By default, it has a value of \fI4096\fR (4 kB). +.RE +.P + .SH EXAMPLES .B fort \-t /tmp/tal \-r /tmp/repository \-\-server.port 9323 .RS 4 @@ -645,7 +654,8 @@ to a specific value: "output": { "roa": "/tmp/fort/roas.csv", "bgpsec": "/tmp/fort/bgpsec.csv" - } + }, + "asn1-decode-max-stack": 4096 } .fi .RE diff --git a/src/asn1/decode.c b/src/asn1/decode.c index cc971ab4..6c28b09a 100644 --- a/src/asn1/decode.c +++ b/src/asn1/decode.c @@ -2,6 +2,7 @@ #include #include "common.h" +#include "config.h" #include "log.h" #define COND_LOG(log, pr) (log ? pr : -EINVAL) @@ -97,13 +98,15 @@ asn1_decode(const void *buffer, size_t buffer_size, asn_TYPE_descriptor_t const *descriptor, void **result, bool log, bool dec_as_der) { + asn_codec_ctx_t s_codec_ctx; asn_dec_rval_t rval; int error; *result = NULL; + s_codec_ctx.max_stack_size = config_get_asn1_decode_max_stack(); - /* TODO (next iteration) first argument is more or less important. */ - rval = ber_decode(0, descriptor, result, buffer, buffer_size); + rval = ber_decode(&s_codec_ctx, descriptor, result, buffer, + buffer_size); if (rval.code != RC_OK) { /* Must free partial object according to API contracts. */ ASN_STRUCT_FREE(*descriptor, *result); diff --git a/src/config.c b/src/config.c index 67b42c83..b96364ec 100644 --- a/src/config.c +++ b/src/config.c @@ -94,6 +94,9 @@ struct rpki_config { /** File where the validated BGPsec certs will be stored */ char *bgpsec; } output; + + /* ASN1 decoder max stack size allowed */ + unsigned int asn1_decode_max_stack; }; static void print_usage(FILE *, bool); @@ -376,6 +379,16 @@ static const struct option_field options[] = { .arg_doc = "", }, + { + .id = 8000, + .name = "asn1-decode-max-stack", + .type = >_uint, + .offset = offsetof(struct rpki_config, asn1_decode_max_stack), + .doc = "ASN1 decoder max stack size, utilized to avoid a stack overflow on large nested ASN1 objects", + .min = 1, + .max = UINT_MAX, + }, + { 0 }, }; @@ -579,6 +592,8 @@ set_default_values(void) rpki_config.output.roa = NULL; rpki_config.output.bgpsec = NULL; + rpki_config.asn1_decode_max_stack = 4096; /* 4kB */ + return 0; revert_recursive_array: @@ -878,6 +893,12 @@ config_get_output_bgpsec(void) return rpki_config.output.bgpsec; } +unsigned int +config_get_asn1_decode_max_stack(void) +{ + return rpki_config.asn1_decode_max_stack; +} + void free_rpki_config(void) { diff --git a/src/config.h b/src/config.h index 036a8ceb..0ec3d7ac 100644 --- a/src/config.h +++ b/src/config.h @@ -39,6 +39,7 @@ char *config_get_rsync_program(void); struct string_array const *config_get_rsync_args(bool); char const *config_get_output_roa(void); char const *config_get_output_bgpsec(void); +unsigned int config_get_asn1_decode_max_stack(void); /* Needed public by the JSON module */ void *get_rpki_config_field(struct option_field const *);