diff --git a/rust/src/detect/transform_base64.rs b/rust/src/detect/transform_base64.rs index e90ed221fd1b..1fae2915a404 100644 --- a/rust/src/detect/transform_base64.rs +++ b/rust/src/detect/transform_base64.rs @@ -32,9 +32,39 @@ use std::str; #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum DetectBase64Mode { Base64ModeRelax = 0, - Base64ModeRFC2045, + /* If the following strings were to be passed to the decoder with RFC2045 mode, + * the results would be as follows. See the unittest B64TestVectorsRFC2045 in + * src/util-base64.c + * + * BASE64("") = "" + * BASE64("f") = "Zg==" + * BASE64("fo") = "Zm8=" + * BASE64("foo") = "Zm9v" + * BASE64("foob") = "Zm9vYg==" + * BASE64("fooba") = "Zm9vYmE=" + * BASE64("foobar") = "Zm9vYmFy" + * BASE64("foobar") = "Zm 9v Ym Fy" <-- Notice how the spaces are ignored + * BASE64("foobar") = "Zm$9vYm.Fy" # According to RFC 2045, All line breaks or *other + * characters* not found in base64 alphabet must be ignored by decoding software + * */ + Base64ModeRFC2045, /* SPs are allowed during transfer but must be skipped by Decoder */ Base64ModeStrict, - Base64ModeRFC4648, + /* If the following strings were to be passed to the decoder with RFC4648 mode, + * the results would be as follows. See the unittest B64TestVectorsRFC4648 in + * src/util-base64.c + * + * BASE64("") = "" + * BASE64("f") = "Zg==" + * BASE64("fo") = "Zm8=" + * BASE64("foo") = "Zm9v" + * BASE64("foob") = "Zm9vYg==" + * BASE64("fooba") = "Zm9vYmE=" + * BASE64("foobar") = "Zm9vYmFy" + * BASE64("f") = "Zm 9v Ym Fy" <-- Notice how the processing stops once space is encountered + * BASE64("f") = "Zm$9vYm.Fy" <-- Notice how the processing stops once an invalid char is + * encountered + * */ + Base64ModeRFC4648, /* reject the encoded data if it contains characters outside the base alphabet */ } pub const TRANSFORM_FROM_BASE64_MODE_DEFAULT: DetectBase64Mode = DetectBase64Mode::Base64ModeRFC4648; @@ -120,8 +150,7 @@ fn parse_transform_base64( )(input)?; // Too many options? - if values.len() > DETECT_TRANSFORM_BASE64_MAX_PARAM_COUNT - { + if values.len() > DETECT_TRANSFORM_BASE64_MAX_PARAM_COUNT { return Err(make_error(format!("Incorrect argument string; at least 1 value must be specified but no more than {}: {:?}", DETECT_TRANSFORM_BASE64_MAX_PARAM_COUNT, input))); } diff --git a/src/datasets.c b/src/datasets.c index 01ef5bb47c90..31fa6b398ca2 100644 --- a/src/datasets.c +++ b/src/datasets.c @@ -23,6 +23,7 @@ #include "suricata-common.h" #include "suricata.h" +#include "rust.h" #include "conf.h" #include "datasets.h" #include "datasets-string.h" @@ -522,7 +523,7 @@ static int DatasetLoadString(Dataset *set) uint8_t decoded[strlen(line)]; uint32_t consumed = 0, num_decoded = 0; Base64Ecode code = DecodeBase64(decoded, strlen(line), (const uint8_t *)line, - strlen(line), &consumed, &num_decoded, BASE64_MODE_STRICT); + strlen(line), &consumed, &num_decoded, Base64ModeStrict); if (code == BASE64_ECODE_ERR) { FatalErrorOnInit("bad base64 encoding %s/%s", set->name, set->load); continue; @@ -543,7 +544,7 @@ static int DatasetLoadString(Dataset *set) uint8_t decoded[strlen(line)]; uint32_t consumed = 0, num_decoded = 0; Base64Ecode code = DecodeBase64(decoded, strlen(line), (const uint8_t *)line, - strlen(line), &consumed, &num_decoded, BASE64_MODE_STRICT); + strlen(line), &consumed, &num_decoded, Base64ModeStrict); if (code == BASE64_ECODE_ERR) { FatalErrorOnInit("bad base64 encoding %s/%s", set->name, set->load); continue; @@ -1606,7 +1607,7 @@ static int DatasetOpSerialized(Dataset *set, const char *string, DatasetOpFunc D uint8_t decoded[strlen(string)]; uint32_t consumed = 0, num_decoded = 0; Base64Ecode code = DecodeBase64(decoded, strlen(string), (const uint8_t *)string, - strlen(string), &consumed, &num_decoded, BASE64_MODE_STRICT); + strlen(string), &consumed, &num_decoded, Base64ModeStrict); if (code == BASE64_ECODE_ERR) { return -2; } diff --git a/src/detect-base64-decode.c b/src/detect-base64-decode.c index 2794509a430f..2e4a16e68a8d 100644 --- a/src/detect-base64-decode.c +++ b/src/detect-base64-decode.c @@ -96,7 +96,7 @@ int DetectBase64DecodeDoMatch(DetectEngineThreadCtx *det_ctx, const Signature *s uint32_t consumed = 0, num_decoded = 0; (void)DecodeBase64(det_ctx->base64_decoded, det_ctx->base64_decoded_len_max, payload, - decode_len, &consumed, &num_decoded, BASE64_MODE_RFC4648); + decode_len, &consumed, &num_decoded, Base64ModeRFC4648); det_ctx->base64_decoded_len = num_decoded; SCLogDebug("Decoded %d bytes from base64 data.", det_ctx->base64_decoded_len); diff --git a/src/tests/fuzz/fuzz_decodebase64.c b/src/tests/fuzz/fuzz_decodebase64.c index 9288f4fec184..6ab7f57a0f82 100644 --- a/src/tests/fuzz/fuzz_decodebase64.c +++ b/src/tests/fuzz/fuzz_decodebase64.c @@ -20,7 +20,7 @@ static void Base64FuzzTest(const uint8_t *src, size_t len, size_t dest_size) if (dest == NULL) return; - for (uint8_t mode = BASE64_MODE_RELAX; mode <= BASE64_MODE_RFC4648; mode++) { + for (uint8_t mode = Base64ModeRelax; mode <= Base64ModeRFC4648; mode++) { uint32_t consumed_bytes = 0; uint32_t decoded_bytes = 0; diff --git a/src/util-base64.c b/src/util-base64.c index ad42c9a703bc..104659eb9ed4 100644 --- a/src/util-base64.c +++ b/src/util-base64.c @@ -274,19 +274,19 @@ static inline Base64Ecode DecodeBase64RFC4648(uint8_t *dest, uint32_t dest_size, * \return Error code indicating success or failures with parsing */ Base64Ecode DecodeBase64(uint8_t *dest, uint32_t dest_size, const uint8_t *src, uint32_t len, - uint32_t *consumed_bytes, uint32_t *decoded_bytes, Base64Mode mode) + uint32_t *consumed_bytes, uint32_t *decoded_bytes, DetectBase64Mode mode) { *decoded_bytes = 0; Base64Ecode ret = BASE64_ECODE_OK; switch (mode) { - case BASE64_MODE_RFC4648: + case Base64ModeRFC4648: ret = DecodeBase64RFC4648( dest, dest_size, src, len, consumed_bytes, decoded_bytes, false); break; - case BASE64_MODE_RFC2045: + case Base64ModeRFC2045: ret = DecodeBase64RFC2045(dest, dest_size, src, len, consumed_bytes, decoded_bytes); break; - case BASE64_MODE_STRICT: + case Base64ModeStrict: ret = DecodeBase64RFC4648( dest, dest_size, src, len, consumed_bytes, decoded_bytes, true); break; @@ -303,7 +303,7 @@ Base64Ecode DecodeBase64(uint8_t *dest, uint32_t dest_size, const uint8_t *src, uint32_t consumed_bytes = 0, num_decoded = 0; \ uint8_t dst[dest_size]; \ Base64Ecode code = DecodeBase64(dst, dest_size, (const uint8_t *)src, strlen(src), \ - &consumed_bytes, &num_decoded, BASE64_MODE_RFC2045); \ + &consumed_bytes, &num_decoded, Base64ModeRFC2045); \ FAIL_IF(code != ecode); \ FAIL_IF(memcmp(dst, fin_str, strlen(fin_str)) != 0); \ FAIL_IF(num_decoded != exp_decoded); \ @@ -315,7 +315,7 @@ Base64Ecode DecodeBase64(uint8_t *dest, uint32_t dest_size, const uint8_t *src, uint32_t consumed_bytes = 0, num_decoded = 0; \ uint8_t dst[dest_size]; \ Base64Ecode code = DecodeBase64(dst, dest_size, (const uint8_t *)src, strlen(src), \ - &consumed_bytes, &num_decoded, BASE64_MODE_RFC4648); \ + &consumed_bytes, &num_decoded, Base64ModeRFC4648); \ FAIL_IF(code != ecode); \ FAIL_IF(memcmp(dst, fin_str, strlen(fin_str)) != 0); \ FAIL_IF(num_decoded != exp_decoded); \ @@ -387,7 +387,7 @@ static int B64DecodeStringEndingSpaces(void) uint32_t consumed_bytes = 0, num_decoded = 0; uint8_t dst[10]; Base64Ecode code = DecodeBase64(dst, sizeof(dst), (const uint8_t *)src, 9, &consumed_bytes, - &num_decoded, BASE64_MODE_RFC2045); + &num_decoded, Base64ModeRFC2045); FAIL_IF(code != BASE64_ECODE_OK); FAIL_IF(num_decoded != 3); FAIL_IF(consumed_bytes != 4); diff --git a/src/util-base64.h b/src/util-base64.h index 744b849d87fd..4431d48a9e54 100644 --- a/src/util-base64.h +++ b/src/util-base64.h @@ -26,49 +26,12 @@ #define SURICATA_UTIL_BASE64_H_ #include "suricata-common.h" +#include "rust.h" /* Constants */ #define ASCII_BLOCK 3 #define B64_BLOCK 4 -typedef enum { - BASE64_MODE_RELAX, - /* If the following strings were to be passed to the decoder with RFC2045 mode, - * the results would be as follows. See the unittest B64TestVectorsRFC2045 in - * src/util-base64.c - * - * BASE64("") = "" - * BASE64("f") = "Zg==" - * BASE64("fo") = "Zm8=" - * BASE64("foo") = "Zm9v" - * BASE64("foob") = "Zm9vYg==" - * BASE64("fooba") = "Zm9vYmE=" - * BASE64("foobar") = "Zm9vYmFy" - * BASE64("foobar") = "Zm 9v Ym Fy" <-- Notice how the spaces are ignored - * BASE64("foobar") = "Zm$9vYm.Fy" # According to RFC 2045, All line breaks or *other - * characters* not found in base64 alphabet must be ignored by decoding software - * */ - BASE64_MODE_RFC2045, /* SPs are allowed during transfer but must be skipped by Decoder */ - BASE64_MODE_STRICT, - /* If the following strings were to be passed to the decoder with RFC4648 mode, - * the results would be as follows. See the unittest B64TestVectorsRFC4648 in - * src/util-base64.c - * - * BASE64("") = "" - * BASE64("f") = "Zg==" - * BASE64("fo") = "Zm8=" - * BASE64("foo") = "Zm9v" - * BASE64("foob") = "Zm9vYg==" - * BASE64("fooba") = "Zm9vYmE=" - * BASE64("foobar") = "Zm9vYmFy" - * BASE64("f") = "Zm 9v Ym Fy" <-- Notice how the processing stops once space is encountered - * BASE64("f") = "Zm$9vYm.Fy" <-- Notice how the processing stops once an invalid char is - * encountered - * */ - BASE64_MODE_RFC4648, /* reject the encoded data if it contains characters outside the base - alphabet */ -} Base64Mode; - typedef enum { BASE64_ECODE_ERR = -1, BASE64_ECODE_OK = 0, @@ -77,7 +40,7 @@ typedef enum { /* Function prototypes */ Base64Ecode DecodeBase64(uint8_t *dest, uint32_t dest_size, const uint8_t *src, uint32_t len, - uint32_t *consumed_bytes, uint32_t *decoded_bytes, Base64Mode mode); + uint32_t *consumed_bytes, uint32_t *decoded_bytes, DetectBase64Mode mode); bool IsBase64Alphabet(uint8_t encoded_byte); #endif