]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect/base64: Use Rust defined modes everywhere 11353/head
authorJeff Lucovsky <jlucovsky@oisf.net>
Thu, 21 Mar 2024 14:23:36 +0000 (10:23 -0400)
committerVictor Julien <victor@inliniac.net>
Sat, 22 Jun 2024 13:54:36 +0000 (15:54 +0200)
Issue: 6487

To avoid ambiguity, a single definition for base 64 decoding modes will
be used. The Rust base64 transform contains the definitions for the
existing mode types: Strict, RFC2045, RFC4648

rust/src/detect/transform_base64.rs
src/datasets.c
src/detect-base64-decode.c
src/tests/fuzz/fuzz_decodebase64.c
src/util-base64.c
src/util-base64.h

index e90ed221fd1be121b7eb1b90e6566461fe928efc..1fae2915a404a702c9980ffc9d5f136eea6e977c 100644 (file)
@@ -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)));
     }
index 01ef5bb47c90a337139d97c593227f2ebfadf3cb..31fa6b398ca20fff9a853cab9b204eba041ea41c 100644 (file)
@@ -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;
             }
index 2794509a430f5152199f77e628c26159138e69e8..2e4a16e68a8d7dac6be2390e96efde5a0cfab976 100644 (file)
@@ -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);
index 9288f4fec1842ac54aed4f3b49b7850180d0ad87..6ab7f57a0f82542d22ed51dac90d64acb9786dea 100644 (file)
@@ -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;
 
index ad42c9a703bc156cc054e4d18a478cbefa1b4244..104659eb9ed4d87181eba62025c4d0a53c3b4f32 100644 (file)
@@ -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);
index 744b849d87fd1acd5e5f6a025df983d2bd533617..4431d48a9e54e17f7bf5425731a171ffb81b843e 100644 (file)
 #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