]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect/asn1: Update asn1 C files to use rust code
authorEmmanuel Thompson <eet6646@gmail.com>
Tue, 28 Apr 2020 15:12:04 +0000 (11:12 -0400)
committerVictor Julien <victor@inliniac.net>
Wed, 8 Jul 2020 14:50:38 +0000 (16:50 +0200)
Mark rust extern "C" functions as pub in asn1 module to expose via cbindgen
Update detect-asn1.c/h to use rust functions

rust/src/asn1/mod.rs
rust/src/asn1/parse_rules.rs
src/detect-asn1.c
src/detect-asn1.h

index c88bcdfc86b7f9e33f15e46a0273a49cc6436281..cadbc0c1644be469f0b0f134d89ee373205b6866 100644 (file)
@@ -234,7 +234,7 @@ fn asn1_decode(
 /// input must be a valid buffer of at least input_len bytes
 /// pointer must be freed using `rs_asn1_free`
 #[no_mangle]
-pub(crate) unsafe extern "C" fn rs_asn1_decode(
+pub unsafe extern "C" fn rs_asn1_decode(
     input: *const u8,
     input_len: u32,
     ad_ptr: *const DetectAsn1Data,
@@ -278,7 +278,7 @@ pub unsafe extern "C" fn rs_asn1_free(ptr: *mut Asn1) {
 ///
 /// Returns 1 if any of the options match, 0 if not
 #[no_mangle]
-pub(crate) unsafe extern "C" fn rs_asn1_checks(
+pub unsafe extern "C" fn rs_asn1_checks(
     ptr: *const Asn1,
     ad_ptr: *const DetectAsn1Data,
 ) -> u8 {
index c1cfae66c07c46f1aeaa01ad9539086b961b0c50..592b8b6cac40c023d93edecef9887367e6d78dfb 100644 (file)
@@ -34,7 +34,7 @@ const ASN1_DEFAULT_MAX_FRAMES: u16 = 30;
 ///
 /// pointer must be free'd using `rs_detect_asn1_free`
 #[no_mangle]
-pub(crate) unsafe extern "C" fn rs_detect_asn1_parse(input: *const c_char) -> *mut DetectAsn1Data {
+pub unsafe extern "C" fn rs_detect_asn1_parse(input: *const c_char) -> *mut DetectAsn1Data {
     if input.is_null() {
         return std::ptr::null_mut();
     }
@@ -71,7 +71,7 @@ pub(crate) unsafe extern "C" fn rs_detect_asn1_parse(input: *const c_char) -> *m
 ///
 /// ptr must be a valid object obtained using `rs_detect_asn1_parse`
 #[no_mangle]
-pub(crate) unsafe extern "C" fn rs_detect_asn1_free(ptr: *mut DetectAsn1Data) {
+pub unsafe extern "C" fn rs_detect_asn1_free(ptr: *mut DetectAsn1Data) {
     if ptr.is_null() {
         return;
     }
@@ -80,7 +80,7 @@ pub(crate) unsafe extern "C" fn rs_detect_asn1_free(ptr: *mut DetectAsn1Data) {
 
 /// Struct to hold parsed asn1 keyword options
 #[derive(Debug, PartialEq)]
-pub(crate) struct DetectAsn1Data {
+pub struct DetectAsn1Data {
     pub bitstring_overflow: bool,
     pub double_overflow: bool,
     pub oversize_length: Option<u32>,
index f0c2ab3dd351f051fc10300adbd642ae5c053a98..964987da5c44954daa3580ddaa63f35fee323852 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2010 Open Information Security Foundation
+/* Copyright (C) 2020 Open Information Security Foundation
  *
  * You can copy, redistribute or modify this Program under the terms of
  * the GNU General Public License version 2 as published by the Free
 /**
  * \file detect-asn1.c
  *
- * \author Pablo Rincon Crespo <pablo.rincon.crespo@gmail.com>
- *
  * Implements "asn1" keyword
  */
 
 #include "suricata-common.h"
 #include "debug.h"
 #include "decode.h"
+#include "rust.h"
 
 #include "detect.h"
 #include "detect-parse.h"
 #include "util-unittest-helper.h"
 #include "util-byte.h"
 #include "util-debug.h"
-#include "util-decode-asn1.h"
-
-/* delimiters for functions/arguments */
-const char *ASN_DELIM = " \t,\n";
 
 static int DetectAsn1Match(DetectEngineThreadCtx *, Packet *,
                      const Signature *, const SigMatchCtx *);
@@ -62,80 +57,17 @@ void DetectAsn1Register(void)
     return;
 }
 
-/**
- * \brief The main checks are done here
- *        This function implements the detection of the following options:
- *          - oversize_length
- *          - bitstring_overflow
- *          - double_overflow
- *        We can add more checks here easily since we have all the data of the
- *        node avaliable. If we need all the tree, we can just pass the
- *        ASN1 ctx as argument and perform the checks here
- * \param node pointer to the Asn1Node to inspect
- * \param ad pointer to the parsed options of the asn1 keyword (which hold the
- *           checks that we want to perform, and the lenght of oversize check
- * \retval 1 if any of the options match, 0 if not
- */
-static uint8_t DetectAsn1Checks(Asn1Node *node, const DetectAsn1Data *ad)
-{
-
-    /* oversize_length will check if a node has a length greater than
-     * the user supplied length */
-    if (ad->flags & ASN1_OVERSIZE_LEN) {
-        if (node->len.len > ad->oversize_length
-            || node->data.len > ad->oversize_length)
-            return 1;
-    }
-
-    /* 8.6 */
-    /* bitstring_overflow check a malformed option where the number of bits
-     * to ignore is greater than the length decoded (in bits) */
-    if (ad->flags & ASN1_BITSTRING_OVF) {
-        if (node->id.class_tag == ASN1_BER_CLASS_UNIV &&
-            node->id.tag_num == ASN1_UNITAG_BIT_STRING &&
-            node->id.tag_type == ASN1_TAG_TYPE_PRIMITIVE)
-        {
-            if (node->len.len > 0 && node->data.ptr != NULL
-                && (node->len.len) * 8 < (uint8_t) *node->data.ptr)
-            {
-                return 1;
-            }
-        }
-    }
-
-    /* double_overflow checks a known issue that affect the MSASN1 library
-     * when decoding double/real types. If the endoding is ASCII,
-     * and the buffer is greater than 256, the array is overflown
-     */
-    if (ad->flags & ASN1_DOUBLE_OVF) {
-        if (node->id.class_tag == ASN1_BER_CLASS_UNIV &&
-            node->id.tag_num == ASN1_UNITAG_REAL &&
-            node->id.tag_type == ASN1_TAG_TYPE_PRIMITIVE)
-        {
-            if (node->len.len > 0 && node->data.ptr != NULL
-                && !((uint8_t) *node->data.ptr & 0xC0)
-                && (node->len.len > 256 || node->data.len > 256))
-            {
-                return 1;
-            }
-        }
-    }
-
-    /* Good to know :) */
-    return 0;
-}
-
 /**
  * \brief This function will decode the asn1 data and inspect the resulting
  *        nodes to detect if any of the specified checks match this data
  *
- * \param t pointer to thread vars
- * \param det_ctx pointer to the pattern matcher thread
+ * \param det_ctx pointer to the detect engine thread context
  * \param p pointer to the current packet
- * \param m pointer to the sigmatch that we will cast into DetectAsn1Data
+ * \param s pointer to the signature
+ * \param ctx pointer to the sigmatch that we will cast into `DetectAsn1Data`
  *
- * \retval 0 no match
  * \retval 1 match
+ * \retval 0 no match
  */
 static int DetectAsn1Match(DetectEngineThreadCtx *det_ctx, Packet *p,
                     const Signature *s, const SigMatchCtx *ctx)
@@ -148,171 +80,46 @@ static int DetectAsn1Match(DetectEngineThreadCtx *det_ctx, Packet *p,
     }
 
     const DetectAsn1Data *ad = (const DetectAsn1Data *)ctx;
-    uint16_t offset;
-    if (ad->flags & ASN1_ABSOLUTE_OFFSET) {
-        offset = ad->absolute_offset;
-    } else if (ad->flags & ASN1_RELATIVE_OFFSET) {
-        // relative offset in regards to the last content match
 
-        // This range check is done when relative_offset
-        BUG_ON(ad->relative_offset > UINT16_MAX || ad->relative_offset < -UINT16_MAX);
+    Asn1 *asn1 = rs_asn1_decode(p->payload, p->payload_len, ad);
 
-        int64_t tmp_offset = det_ctx->buffer_offset + ad->relative_offset;
+    ret = rs_asn1_checks(asn1, ad);
 
-        // check for under/overflow before downcasting
-        if (tmp_offset < 0 || tmp_offset > UINT16_MAX) {
-            return 0;
-        }
+    rs_asn1_free(asn1);
 
-        offset = (uint16_t)tmp_offset;
-    } else {
-        offset = 0;
-    }
-
-    if (offset >= p->payload_len) {
-        return 0;
-    }
-
-    Asn1Ctx *ac = SCAsn1CtxNew();
-    if (ac == NULL)
-        return 0;
-
-    SCAsn1CtxInit(ac, p->payload + offset, p->payload_len - offset);
-    SCAsn1Decode(ac, ac->cur_frame);
-
-    /* Ok, now we have all the data. Let's check the nodes */
-
-    if (ac->cur_frame > 0 || (ac->asn1_stack[0] != NULL && ac->asn1_stack[0]->id.ptr != NULL)) {
-        /* We spect at least one node */
-        uint16_t n_iter = 0;
-        ret = 0;
-
-        for (; n_iter <= ac->cur_frame; n_iter++) {
-            Asn1Node *node = ASN1CTX_GET_NODE(ac, n_iter);
-
-            if (node == NULL || node->id.ptr == NULL)
-                continue; /* Should not happen */
-
-            ret = DetectAsn1Checks(node, ad);
-            /* Got a match? */
-            if (ret == 1)
-                break;
-        }
-    }
-
-    SCAsn1CtxDestroy(ac);
     return ret;
 }
 
 /**
  * \brief This function is used to parse asn1 options passed via asn1: keyword
  *
- * \param asn1str Pointer to the user provided asn1 options
+ * \param asn1str pointer to the user provided asn1 options
  *
- * \retval fd pointer to DetectAsn1Data on success
+ * \retval pointer to `DetectAsn1Data` on success
  * \retval NULL on failure
  */
-static DetectAsn1Data *DetectAsn1Parse(const char *instr)
+static DetectAsn1Data *DetectAsn1Parse(const char *asn1str)
 {
-    DetectAsn1Data *fd = NULL;
-    char *tok = NULL;
-    uint32_t ov_len = 0;
-    uint16_t abs_off = 0;
-    int32_t rel_off = 0;
-    uint8_t flags = 0;
-    char *saveptr = NULL;
-
-    char *asn1str = SCStrdup(instr);
-    if (asn1str == NULL)
-        return NULL;
-
-    tok = strtok_r(asn1str, ASN_DELIM, &saveptr);
-    if (tok == NULL) {
+    DetectAsn1Data *ad = rs_detect_asn1_parse(asn1str);
+
+    if (ad == NULL) {
         SCLogError(SC_ERR_INVALID_VALUE, "Malformed asn1 argument: %s",
                    asn1str);
-        SCFree(asn1str);
-        return NULL;
-    }
-
-    while (tok != NULL) {
-        if (strcasecmp("bitstring_overflow", tok) == 0) {
-            /* No arg here, just set the flag */
-            flags |= ASN1_BITSTRING_OVF;
-        } else if (strcasecmp("double_overflow", tok) == 0) {
-            /* No arg here, just set the flag */
-            flags |= ASN1_DOUBLE_OVF;
-        } else if (strcasecmp("oversize_length", tok) == 0) {
-            flags |= ASN1_OVERSIZE_LEN;
-            /* get the param */
-            tok = strtok_r(NULL, ASN_DELIM, &saveptr);
-            if ( tok == NULL ||
-                StringParseUint32(&ov_len, 10, 0, tok) <= 0)
-            {
-                SCLogError(SC_ERR_INVALID_VALUE, "Malformed value for "
-                           "oversize_length: %s", tok);
-                goto error;
-            }
-        } else if (strcasecmp("absolute_offset", tok) == 0) {
-            flags |= ASN1_ABSOLUTE_OFFSET;
-            /* get the param */
-            tok = strtok_r(NULL, ASN_DELIM, &saveptr);
-            if (tok == NULL ||
-                StringParseUint16(&abs_off, 10, 0, tok) <= 0)
-            {
-                SCLogError(SC_ERR_INVALID_VALUE, "Malformed value for "
-                           "absolute_offset: %s", tok);
-                goto error;
-            }
-        } else if (strcasecmp("relative_offset",tok) == 0) {
-            flags |= ASN1_RELATIVE_OFFSET;
-            /* get the param */
-            tok = strtok_r(NULL, ASN_DELIM, &saveptr);
-
-            // Range check on uint16_t max as uint16_t is the type of the buffer
-            // the offset is relative to
-            if (tok == NULL ||
-                StringParseI32RangeCheck(&rel_off, 10, 0, tok, -UINT16_MAX, UINT16_MAX) <= 0)
-            {
-                SCLogError(SC_ERR_INVALID_VALUE, "Malformed value for "
-                           "relative_offset: %s", tok);
-                goto error;
-            }
-        } else {
-            SCLogError(SC_ERR_INVALID_VALUE, "Malformed asn1 argument: %s",
-                       asn1str);
-            goto error;
-        }
-        tok = strtok_r(NULL, ASN_DELIM, &saveptr);
-    }
-
-    fd = SCMalloc(sizeof(DetectAsn1Data));
-    if (unlikely(fd == NULL)) {
-        goto error;
     }
-    memset(fd, 0x00, sizeof(DetectAsn1Data));
-
-    fd->flags = flags;
-    fd->oversize_length = ov_len;    /* Length argument if needed */
-    fd->absolute_offset = abs_off;   /* Length argument if needed */
-    fd->relative_offset = rel_off;   /* Length argument if needed */
-    SCFree(asn1str);
-    return fd;
 
-error:
-    SCFree(asn1str);
-    return NULL;
+    return ad;
 }
 
 /**
  * \brief this function is used to add the parsed asn1 data into
  *        the current signature
  *
- * \param de_ctx pointer to the Detection Engine Context
- * \param s pointer to the Current Signature
+ * \param de_ctx pointer to the detection engine context
+ * \param s pointer to the current signature
  * \param asn1str pointer to the user provided asn1 options
  *
- * \retval 0 on Success
- * \retval -1 on Failure
+ * \retval 0 on success
+ * \retval -1 on failure
  */
 static int DetectAsn1Setup(DetectEngineCtx *de_ctx, Signature *s, const char *asn1str)
 {
@@ -320,7 +127,8 @@ static int DetectAsn1Setup(DetectEngineCtx *de_ctx, Signature *s, const char *as
     SigMatch *sm = NULL;
 
     ad = DetectAsn1Parse(asn1str);
-    if (ad == NULL) goto error;
+    if (ad == NULL)
+        goto error;
 
     /* Okay so far so good, lets get this into a SigMatch
      * and put it in the Signature. */
@@ -336,720 +144,27 @@ static int DetectAsn1Setup(DetectEngineCtx *de_ctx, Signature *s, const char *as
     return 0;
 
 error:
-    if (ad != NULL)
-        DetectAsn1Free(de_ctx, ad);
     if (sm != NULL)
         SCFree(sm);
+    if (ad != NULL)
+        DetectAsn1Free(de_ctx, ad);
     return -1;
-
 }
 
 /**
- * \brief this function will free memory associated with DetectAsn1Data
+ * \brief this function will free memory associated with `DetectAsn1Data`
  *
- * \param ad pointer to DetectAsn1Data
+ * \param de_ctx pointer to the detection engine context
+ * \param ptr point to `DetectAsn1Data`
  */
 static void DetectAsn1Free(DetectEngineCtx *de_ctx, void *ptr)
 {
     DetectAsn1Data *ad = (DetectAsn1Data *)ptr;
-    SCFree(ad);
+    rs_detect_asn1_free(ad);
 }
 
 #ifdef UNITTESTS
 
-/**
- * \test DetectAsn1TestParse01 check that we parse oversize_length correctly
- */
-static int DetectAsn1TestParse01(void)
-{
-    int result = 0;
-    char str[] = "oversize_length 1024";
-    DetectAsn1Data *ad = NULL;
-
-    ad = DetectAsn1Parse(str);
-    if (ad != NULL) {
-        if (ad->oversize_length == 1024 && (ad->flags & ASN1_OVERSIZE_LEN)) {
-            result = 1;
-        }
-        DetectAsn1Free(NULL, ad);
-    }
-
-    return result;
-}
-
-/**
- * \test DetectAsn1TestParse02 check that we parse absolute_offset correctly
- */
-static int DetectAsn1TestParse02(void)
-{
-    int result = 0;
-    DetectAsn1Data *ad = NULL;
-    char str[] = "absolute_offset 1024";
-
-    ad = DetectAsn1Parse(str);
-    if (ad != NULL && ad->absolute_offset == 1024
-        && (ad->flags & ASN1_ABSOLUTE_OFFSET)) {
-        DetectAsn1Free(NULL, ad);
-        result = 1;
-    }
-
-    return result;
-}
-
-/**
- * \test DetectAsn1TestParse03 check that we parse relative_offset correctly
- */
-static int DetectAsn1TestParse03(void)
-{
-    int result = 0;
-    char str[] = "relative_offset     1024";
-    DetectAsn1Data *ad = NULL;
-
-    ad = DetectAsn1Parse(str);
-    if (ad != NULL && ad->relative_offset == 1024
-        && (ad->flags & ASN1_RELATIVE_OFFSET)) {
-        DetectAsn1Free(NULL, ad);
-        result = 1;
-    }
-
-    return result;
-}
-
-/**
- * \test DetectAsn1TestParse04 check that we parse bitstring_overflow correctly
- */
-static int DetectAsn1TestParse04(void)
-{
-    int result = 0;
-    char str[] = "bitstring_overflow";
-    DetectAsn1Data *ad = NULL;
-
-    ad = DetectAsn1Parse(str);
-    if (ad != NULL && (ad->flags & ASN1_BITSTRING_OVF)) {
-        DetectAsn1Free(NULL, ad);
-        result = 1;
-    }
-
-    return result;
-}
-
-/**
- * \test DetectAsn1TestParse05 check that we parse double_overflow correctly
- */
-static int DetectAsn1TestParse05(void)
-{
-    int result = 0;
-    char str[] = "double_overflow";
-    DetectAsn1Data *ad = NULL;
-
-    ad = DetectAsn1Parse(str);
-    if (ad != NULL && (ad->flags & ASN1_DOUBLE_OVF)) {
-        DetectAsn1Free(NULL, ad);
-        result = 1;
-    }
-
-    return result;
-}
-
-/**
- * \test DetectAsn1TestParse06 check that we fail if a needed arg is not given
- */
-static int DetectAsn1TestParse06(void)
-{
-    int result = 1;
-    char str[] = "absolute_offset";
-    DetectAsn1Data *ad = NULL;
-
-    ad = DetectAsn1Parse(str);
-    if (ad != NULL) {
-        DetectAsn1Free(NULL, ad);
-        result = 0;
-    }
-
-    return result;
-}
-
-/**
- * \test DetectAsn1TestParse07 check that we fail if a needed arg is not given
- */
-static int DetectAsn1TestParse07(void)
-{
-    int result = 1;
-    char str[] = "relative_offset";
-    DetectAsn1Data *ad = NULL;
-
-    ad = DetectAsn1Parse(str);
-    if (ad != NULL) {
-        DetectAsn1Free(NULL, ad);
-        result = 0;
-    }
-
-    return result;
-}
-
-/**
- * \test DetectAsn1TestParse08 check that we fail if a needed arg is not given
- */
-static int DetectAsn1TestParse08(void)
-{
-    int result = 1;
-    char str[] = "oversize_length";
-    DetectAsn1Data *ad = NULL;
-
-    ad = DetectAsn1Parse(str);
-    if (ad != NULL) {
-        DetectAsn1Free(NULL, ad);
-        result = 0;
-    }
-
-    return result;
-}
-
-
-
-/**
- * \test DetectAsn1TestParse09 test that we break on invalid options
- */
-static int DetectAsn1TestParse09(void)
-{
-    int result = 1;
-    DetectAsn1Data *fd = NULL;
-    char str[] = "oversize_length 1024, lalala 360";
-
-    fd = DetectAsn1Parse(str);
-    if (fd != NULL) {
-        result = 0;
-        DetectAsn1Free(NULL, fd);
-    }
-
-    return result;
-}
-
-/**
- * \test DetectAsn1TestParse10 test that we break with a empty string
- */
-static int DetectAsn1TestParse10(void)
-{
-    int result = 1;
-    DetectAsn1Data *fd = NULL;
-    char str[] = "";
-
-    fd = DetectAsn1Parse(str);
-    if (fd != NULL) {
-        result = 0;
-        DetectAsn1Free(NULL, fd);
-    }
-
-    return result;
-}
-
-/**
- * \test DetectAsn1TestParse11 check for combinations of keywords
- */
-static int DetectAsn1TestParse11(void)
-{
-    int result = 0;
-    char str[] = "oversize_length 1024, relative_offset 10";
-    DetectAsn1Data *ad = NULL;
-
-    ad = DetectAsn1Parse(str);
-    if (ad != NULL && ad->oversize_length == 1024
-        && (ad->flags & ASN1_OVERSIZE_LEN)
-        && ad->relative_offset == 10
-        && (ad->flags & ASN1_RELATIVE_OFFSET))
-    {
-        DetectAsn1Free(NULL, ad);
-        result = 1;
-    }
-
-    return result;
-}
-
-/**
- * \test DetectAsn1TestParse12 check for combinations of keywords
- */
-static int DetectAsn1TestParse12(void)
-{
-    int result = 0;
-    char str[] = "oversize_length 1024 absolute_offset 10";
-    DetectAsn1Data *ad = NULL;
-
-    ad = DetectAsn1Parse(str);
-    if (ad != NULL && ad->oversize_length == 1024
-        && (ad->flags & ASN1_OVERSIZE_LEN)
-        && ad->absolute_offset == 10
-        && (ad->flags & ASN1_ABSOLUTE_OFFSET))
-    {
-        DetectAsn1Free(NULL, ad);
-        result = 1;
-    }
-
-    return result;
-}
-
-/**
- * \test DetectAsn1TestParse13 check for combinations of keywords
- */
-static int DetectAsn1TestParse13(void)
-{
-    int result = 0;
-    char str[] = "oversize_length 1024 absolute_offset 10, bitstring_overflow";
-    DetectAsn1Data *ad = NULL;
-
-    ad = DetectAsn1Parse(str);
-    if (ad != NULL && ad->oversize_length == 1024
-        && (ad->flags & ASN1_OVERSIZE_LEN)
-        && (ad->flags & ASN1_BITSTRING_OVF)
-        && ad->absolute_offset == 10
-        && (ad->flags & ASN1_ABSOLUTE_OFFSET))
-    {
-        DetectAsn1Free(NULL, ad);
-        result = 1;
-    }
-
-    return result;
-}
-
-/**
- * \test DetectAsn1TestParse14 check for combinations of keywords
- */
-static int DetectAsn1TestParse14(void)
-{
-    int result = 0;
-    char str[] = "double_overflow, oversize_length 1024 absolute_offset 10,"
-                 " bitstring_overflow";
-    DetectAsn1Data *ad = NULL;
-
-    ad = DetectAsn1Parse(str);
-    if (ad != NULL && ad->oversize_length == 1024
-        && (ad->flags & ASN1_OVERSIZE_LEN)
-        && (ad->flags & ASN1_BITSTRING_OVF)
-        && (ad->flags & ASN1_DOUBLE_OVF)
-        && ad->absolute_offset == 10
-        && (ad->flags & ASN1_ABSOLUTE_OFFSET))
-    {
-        DetectAsn1Free(NULL, ad);
-        result = 1;
-    }
-
-    return result;
-}
-
-/**
- * \test DetectAsn1TestParse15 check for combinations of keywords
- */
-static int DetectAsn1TestParse15(void)
-{
-    int result = 0;
-    char str[] = "double_overflow, oversize_length 1024 relative_offset 10,"
-                 " bitstring_overflow";
-    DetectAsn1Data *ad = NULL;
-
-    ad = DetectAsn1Parse(str);
-    if (ad != NULL && ad->oversize_length == 1024
-        && (ad->flags & ASN1_OVERSIZE_LEN)
-        && (ad->flags & ASN1_BITSTRING_OVF)
-        && (ad->flags & ASN1_DOUBLE_OVF)
-        && ad->relative_offset == 10
-        && (ad->flags & ASN1_RELATIVE_OFFSET))
-    {
-        DetectAsn1Free(NULL, ad);
-        result = 1;
-    }
-
-    return result;
-}
-
-/**
- * \test DetectAsn1Test01 Ensure that the checks work when they should
- */
-static int DetectAsn1Test01(void)
-{
-    /* Match if any of the nodes after offset 0 has greater length than 10 */
-    char str[] = "oversize_length 132 absolute_offset 0";
-
-    DetectAsn1Data *ad = DetectAsn1Parse(str);
-    FAIL_IF_NULL(ad);
-    FAIL_IF_NOT(ad->oversize_length == 132);
-    FAIL_IF_NOT(ad->flags & ASN1_OVERSIZE_LEN);
-    FAIL_IF_NOT(ad->absolute_offset == 0);
-    FAIL_IF_NOT(ad->flags & ASN1_ABSOLUTE_OFFSET);
-
-    // Example from the specification X.690-0207 Appendix A.3
-    char buf[] = "\x60\x81\x85\x61\x10\x1A\x04""John""\x1A\x01"
-        "P""\x1A\x05""Smith""\xA0\x0A\x1A\x08""Director"
-        "\x42\x01\x33\xA1\x0A\x43\x08""19710917"
-        "\xA2\x12\x61\x10\x1A\x04""Mary""\x1A\x01""T""\x1A\x05"
-        "Smith""\xA3\x42\x31\x1F\x61\x11\x1A\x05""Ralph""\x1A\x01"
-        "T""\x1A\x05""Smith""\xA0\x0A\x43\x08""19571111"
-        "\x31\x1F\x61\x11\x1A\x05""Susan""\x1A\x01""B""\x1A\x05"
-        "Jones""\xA0\x0A\x43\x08""19590717";
-
-    Asn1Ctx *ac = SCAsn1CtxNew();
-    FAIL_IF_NULL(ac);
-
-    uint16_t len = strlen((char *)buf)-1;
-
-    SCAsn1CtxInit(ac, (uint8_t *)buf, len);
-    SCAsn1Decode(ac, ac->cur_frame);
-
-    /* The first node has length 133, so it should match the oversize */
-    FAIL_IF_NOT(ac->cur_frame > 0);
-
-    /* We spect at least one node */
-    uint16_t n_iter = 0;
-    int result = 0;
-    for (; n_iter <= ac->cur_frame; n_iter++) {
-        Asn1Node *node = ASN1CTX_GET_NODE(ac, n_iter);
-
-        if (node == NULL || node->id.ptr == NULL)
-            continue; /* Should not happen */
-
-        result = DetectAsn1Checks(node, ad);
-        /* Got a match? */
-        if (result == 1)
-            break;
-    }
-    FAIL_IF(result != 1);
-
-    SCAsn1CtxDestroy(ac);
-    DetectAsn1Free(NULL, ad);
-
-    PASS;
-}
-
-/**
- * \test DetectAsn1Test02 Ensure that the checks work when they should
- */
-static int DetectAsn1Test02(void)
-{
-    int result = 0;
-    /* Match if any of the nodes has the bitstring overflow condition */
-    char str[] = "oversize_length 133, absolute_offset 0";
-    DetectAsn1Data *ad = NULL;
-
-    ad = DetectAsn1Parse(str);
-    if (ad != NULL && ad->oversize_length == 133
-        && (ad->flags & ASN1_OVERSIZE_LEN)
-        && ad->absolute_offset == 0
-        && (ad->flags & ASN1_ABSOLUTE_OFFSET))
-    {
-       // Example from the specification X.690-0207 Appendix A.3
-        uint8_t *buf = (uint8_t*) "\x60\x81\x85\x61\x10\x1A\x04""John""\x1A\x01"
-                   "P""\x1A\x05""Smith""\xA0\x0A\x1A\x08""Director"
-                   "\x42\x01\x33\xA1\x0A\x43\x08""19710917"
-                   "\xA2\x12\x61\x10\x1A\x04""Mary""\x1A\x01""T""\x1A\x05"
-                   "Smith""\xA3\x42\x31\x1F\x61\x11\x1A\x05""Ralph""\x1A\x01"
-                   "T""\x1A\x05""Smith""\xA0\x0A\x43\x08""19571111"
-                   "\x31\x1F\x61\x11\x1A\x05""Susan""\x1A\x01""B""\x1A\x05"
-                   "Jones""\xA0\x0A\x43\x08""19590717";
-
-        Asn1Ctx *ac = SCAsn1CtxNew();
-        if (ac == NULL)
-            return 0;
-
-        uint16_t len = strlen((char *)buf)-1;
-
-        SCAsn1CtxInit(ac, buf, len);
-
-        SCAsn1Decode(ac, ac->cur_frame);
-
-        /* The first node has length 133, so it should match the oversize */
-        if (ac->cur_frame > 0) {
-            /* We spect at least one node */
-            uint16_t n_iter = 0;
-
-            for (; n_iter <= ac->cur_frame; n_iter++) {
-                Asn1Node *node = ASN1CTX_GET_NODE(ac, n_iter);
-
-                if (node == NULL || node->id.ptr == NULL)
-                    continue; /* Should not happen */
-
-                result |= DetectAsn1Checks(node, ad);
-            }
-        }
-
-        /* Got a match? We don't have nodes greater than 133, it should not */
-        if (result == 1) {
-            printf("Error, oversize_length should not match"
-                   " any of the nodes: ");
-            result = 0;
-        } else {
-            result = 1;
-        }
-
-        SCAsn1CtxDestroy(ac);
-        DetectAsn1Free(NULL, ad);
-
-    }
-
-    return result;
-}
-
-/**
- * \test DetectAsn1Test03 Ensure that the checks work when they should
- */
-static int DetectAsn1Test03(void)
-{
-    int result = 0;
-    /* Match if any of the nodes after offset 0 has a bitstring overflow */
-    char str[] = "bitstring_overflow, absolute_offset 0";
-    DetectAsn1Data *ad = NULL;
-
-    ad = DetectAsn1Parse(str);
-    if (ad != NULL && (ad->flags & ASN1_BITSTRING_OVF)
-        && ad->absolute_offset == 0
-        && (ad->flags & ASN1_ABSOLUTE_OFFSET))
-    {
-        /* Let's say tagnum bitstring, primitive, and as universal tag,
-         * and then length = 1 octet, but the next octet specify to ignore
-         * the last  256 bits... (let's match!) */
-        uint8_t *buf = (uint8_t*) "\x03\x01\xFF";
-
-        Asn1Ctx *ac = SCAsn1CtxNew();
-        if (ac == NULL)
-            return 0;
-
-        uint16_t len = 3;
-
-        SCAsn1CtxInit(ac, buf, len);
-
-        SCAsn1Decode(ac, ac->cur_frame);
-
-        if (ac->cur_frame > 0 || ac->asn1_stack[0]->id.ptr != NULL) {
-            /* We spect at least one node */
-            uint16_t n_iter = 0;
-
-            for (; n_iter <= ac->cur_frame; n_iter++) {
-                Asn1Node *node = ASN1CTX_GET_NODE(ac, n_iter);
-
-                if (node == NULL || node->id.ptr == NULL)
-                    continue; /* Should not happen */
-
-                result = DetectAsn1Checks(node, ad);
-                /* Got a match? */
-                if (result == 1)
-                    break;
-            }
-        }
-
-        SCAsn1CtxDestroy(ac);
-        DetectAsn1Free(NULL, ad);
-
-    }
-
-    if (result == 0) {
-        printf("Error, bitstring_overflow should match the first node: ");
-    }
-
-    return result;
-}
-
-/**
- * \test DetectAsn1Test04 Ensure that the checks work when they should
- */
-static int DetectAsn1Test04(void)
-{
-    int result = 0;
-    /* Match if any of the nodes after offset 0 has a bitstring overflow */
-    char str[] = "bitstring_overflow, absolute_offset 0";
-    DetectAsn1Data *ad = NULL;
-
-    ad = DetectAsn1Parse(str);
-    if (ad != NULL && (ad->flags & ASN1_BITSTRING_OVF)
-        && ad->absolute_offset == 0
-        && (ad->flags & ASN1_ABSOLUTE_OFFSET))
-    {
-        /* Let's say tagnum bitstring, primitive, and as universal tag,
-         * and then length = 1 octet, but the next octet specify to ignore
-         * the last  7 bits... (should not match) */
-        uint8_t *buf = (uint8_t*) "\x03\x01\x07";
-
-        Asn1Ctx *ac = SCAsn1CtxNew();
-        if (ac == NULL)
-            return 0;
-
-        uint16_t len = 3;
-
-        SCAsn1CtxInit(ac, buf, len);
-
-        SCAsn1Decode(ac, ac->cur_frame);
-
-        if (ac->cur_frame > 0 || ac->asn1_stack[0]->id.ptr != NULL) {
-            /* We spect at least one node */
-            uint16_t n_iter = 0;
-
-            for (; n_iter <= ac->cur_frame; n_iter++) {
-                Asn1Node *node = ASN1CTX_GET_NODE(ac, n_iter);
-
-                if (node == NULL || node->id.ptr == NULL)
-                    continue; /* Should not happen */
-
-                result = DetectAsn1Checks(node, ad);
-                /* Got a match? */
-                if (result == 1)
-                    break;
-            }
-        }
-
-        SCAsn1CtxDestroy(ac);
-        DetectAsn1Free(NULL, ad);
-
-    }
-
-    if (result == 1) {
-        printf("Error, bitstring_overflog should not match any node: ");
-        result = 0;
-    } else {
-        result = 1;
-    }
-
-    return result;
-}
-
-/**
- * \test DetectAsn1Test05 Ensure that the checks work when they should
- */
-static int DetectAsn1Test05(void)
-{
-    int result = 0;
-    /* Match if any of the nodes after offset 0 has a double overflow */
-    char str[] = "double_overflow, absolute_offset 0";
-    DetectAsn1Data *ad = NULL;
-
-    ad = DetectAsn1Parse(str);
-    if (ad != NULL && (ad->flags & ASN1_DOUBLE_OVF)
-        && ad->absolute_offset == 0
-        && (ad->flags & ASN1_ABSOLUTE_OFFSET))
-    {
-        /* Let's say tag num 9 (type Real), and encoded as ASCII, with length
-         * 257, then we must match */
-        uint8_t buf[261];
-        /* universal class, primitive type, tag_num = 9 (Data type Real) */
-        buf[0] = '\x09';
-        /* length, definite form, 2 octets */
-        buf[1] = '\x82';
-        /* length is the sum of the following octets (257): */
-        buf[2] = '\xFE';
-        buf[3] = '\x03';
-
-        /* Fill the content of the number */
-        uint16_t i = 4;
-        for (; i < 257;i++)
-            buf[i] = '\x05';
-
-        Asn1Ctx *ac = SCAsn1CtxNew();
-        if (ac == NULL)
-            return 0;
-
-        uint16_t len = 261;
-
-        SCAsn1CtxInit(ac, buf, len);
-
-        SCAsn1Decode(ac, ac->cur_frame);
-
-        if (ac->cur_frame > 0 || ac->asn1_stack[0]->id.ptr != NULL) {
-            /* We spect at least one node */
-            uint16_t n_iter = 0;
-
-            for (; n_iter <= ac->cur_frame; n_iter++) {
-                Asn1Node *node = ASN1CTX_GET_NODE(ac, n_iter);
-
-                if (node == NULL || node->id.ptr == NULL)
-                    continue; /* Should not happen */
-
-                result = DetectAsn1Checks(node, ad);
-                /* Got a match? */
-                if (result == 1)
-                    break;
-            }
-        }
-
-        SCAsn1CtxDestroy(ac);
-        DetectAsn1Free(NULL, ad);
-
-    }
-
-    if (result == 0) {
-        printf("Error, double_overflow should match the first node: ");
-    }
-
-    return result;
-}
-
-/**
- * \test DetectAsn1Test06 Ensure that the checks work when they should
- */
-static int DetectAsn1Test06(void)
-{
-    int result = 0;
-    /* Match if any of the nodes after offset 0 has a double overflow */
-    char str[] = "double_overflow, absolute_offset 0";
-    DetectAsn1Data *ad = NULL;
-
-    ad = DetectAsn1Parse(str);
-    if (ad != NULL && (ad->flags & ASN1_DOUBLE_OVF)
-        && ad->absolute_offset == 0
-        && (ad->flags & ASN1_ABSOLUTE_OFFSET))
-    {
-        /* Let's say tag num 9 (type Real), and encoded as ASCII, with length
-         * 256, which fit in the buffer, so it should not match */
-        uint8_t buf[260];
-        /* universal class, primitive type, tag_num = 9 (Data type Real) */
-        buf[0] = '\x09';
-        /* length, definite form, 2 octets */
-        buf[1] = '\x82';
-        /* length is the sum of the following octets (256): */
-        buf[2] = '\xFE';
-        buf[3] = '\x02';
-
-        /* Fill the content of the number */
-        uint16_t i = 4;
-        for (; i < 256;i++)
-            buf[i] = '\x05';
-
-        Asn1Ctx *ac = SCAsn1CtxNew();
-        if (ac == NULL)
-            return 0;
-
-        uint16_t len = 260;
-
-        SCAsn1CtxInit(ac, buf, len);
-
-        SCAsn1Decode(ac, ac->cur_frame);
-
-        if (ac->cur_frame > 0 || ac->asn1_stack[0]->id.ptr != NULL) {
-            /* We spect at least one node */
-            uint16_t n_iter = 0;
-
-            for (; n_iter <= ac->cur_frame; n_iter++) {
-                Asn1Node *node = ASN1CTX_GET_NODE(ac, n_iter);
-
-                if (node == NULL || node->id.ptr == NULL)
-                    continue; /* Should not happen */
-
-                result = DetectAsn1Checks(node, ad);
-                /* Got a match? */
-                if (result == 1)
-                    break;
-            }
-        }
-
-        SCAsn1CtxDestroy(ac);
-        DetectAsn1Free(NULL, ad);
-
-    }
-
-    if (result == 1) {
-        printf("Error, double_overflow should not match any node: ");
-        result = 0 ;
-    } else {
-        result = 1;
-    }
-
-    return result;
-}
-
 /**
  * \test DetectAsn1TestReal01 Ensure that all works together
  */
@@ -1108,7 +223,7 @@ static int DetectAsn1TestReal01(void)
              "content:\"Pablo\"; asn1:absolute_offset 0, "
              "oversize_length 130; sid:1;)";
     sigs[1]= "alert ip any any -> any any (msg:\"Testing id 2\"; "
-             "content:\"AA\"; asn1:relative_offset 0, "
+             "content:\"AA\"; asn1:relative_offset 2, "
              "oversize_length 130; sid:2;)";
     sigs[2]= "alert ip any any -> any any (msg:\"Testing id 3\"; "
              "content:\"lalala\"; asn1: oversize_length 2000; sid:3;)";
@@ -1187,7 +302,7 @@ static int DetectAsn1TestReal02(void)
              "content:\"Pablo\"; asn1:absolute_offset 0, "
              "oversize_length 140; sid:1;)";
     sigs[1]= "alert ip any any -> any any (msg:\"Testing id 2\"; "
-             "content:\"AA\"; asn1:relative_offset 0, "
+             "content:\"AA\"; asn1:relative_offset 2, "
              "oversize_length 140; sid:2;)";
     sigs[2]= "alert ip any any -> any any (msg:\"Testing id 3\"; "
              "content:\"lalala\"; asn1: oversize_length 2000; sid:3;)";
@@ -1218,8 +333,8 @@ static int DetectAsn1TestReal03(void)
     /* length, definite form, 2 octets */
     buf[1] = '\x82';
     /* length is the sum of the following octets (257): */
-    buf[2] = '\xFE';
-    buf[3] = '\x03';
+    buf[2] = '\x01';
+    buf[3] = '\x01';
 
     /* Fill the content of the number */
     uint16_t i = 4;
@@ -1268,7 +383,7 @@ end:
 /**
  * \test DetectAsn1TestReal04 like the real test 02, but modified the
  *       relative offset to check negative offset values, in this case
- *       start decoding from -11 bytes respect the content match "John"
+ *       start decoding from -7 bytes respect the content match "John"
  */
 static int DetectAsn1TestReal04(void)
 {
@@ -1325,7 +440,7 @@ static int DetectAsn1TestReal04(void)
              "content:\"Pablo\"; asn1:absolute_offset 0, "
              "oversize_length 140; sid:1;)";
     sigs[1]= "alert ip any any -> any any (msg:\"Testing id 2\"; "
-             "content:\"John\"; asn1:relative_offset -11, "
+             "content:\"John\"; asn1:relative_offset -7, "
              "oversize_length 140; sid:2;)";
     sigs[2]= "alert ip any any -> any any (msg:\"Testing id 3\"; "
              "content:\"lalala\"; asn1: oversize_length 2000; sid:3;)";
@@ -1344,64 +459,6 @@ end:
     return result;
 }
 
-/**
- * \test DetectAsn1TestReal05 like the real test 04, but modified the
- *       relative offset to check offset values which could read past the bounds
- *       of the buffer
- */
-static int DetectAsn1TestReal05(void)
-{
-    int result = 0;
-    /* Check the start with AA (this is to test the relative_offset keyword) */
-    uint8_t *buf = (uint8_t *) "AA\x60\x81\x85\x61\x10\x1A\x04""John""\x1A\x01"
-                   "P""\x1A\x05""Smith""\xA0\x0A\x1A\x08""Director"
-                   "\x42\x01\x33\xA1\x0A\x43\x08""19710917"
-                   "\xA2\x12\x61\x10\x1A\x04""Mary""\x1A\x01""T""\x1A\x05"
-                   "Smith""\xA3\x42\x31\x1F\x61\x11\x1A\x05""Ralph""\x1A\x01"
-                   "T""\x1A\x05""Smith""\xA0\x0A\x43\x08""19571111"
-                   "\x31\x1F\x61\x11\x1A\x05""Susan""\x1A\x01""B""\x1A\x05"
-                   "Jones""\xA0\x0A\x43\x08""19590717"
-                   "\x60\x81\x85\x61\x10\x1A\x04""John""\x1A\x01""P"
-                   "\x1A\x05""Smith""\xA0\x0A\x1A\x08""Director"
-                   "\x42\x01\x33\xA1\x0A\x43\x08""19710917"
-                   "\xA2\x12\x61\x10\x1A\x04""Mary""\x1A\x01""T""\x1A\x05"
-                   "Smith""\xA3\x42\x31\x1F\x61\x11\x1A\x05""Ralph""\x1A\x01"
-                   "T""\x1A\x05""Smith""\xA0\x0A\x43\x08""19571111""\x31\x1F"
-                   "\x61\x11\x1A\x05""Susan""\x1A\x01""B""\x1A\x05""Jones"
-                   "\xA0\x0A\x43\x08""19590717";
-
-    uint16_t buflen = strlen((char *)buf) - 1;
-
-    Packet *p[1];
-
-    p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
-
-    if (p[0] == NULL)
-        goto end;
-
-    const char *sigs[3];
-    sigs[0]= "alert ip any any -> any any (msg:\"Testing id 1\"; "
-             "content:\"John\"; asn1:relative_offset -100, "
-             "oversize_length 132; sid:1;)";
-    sigs[1]= "alert ip any any -> any any (msg:\"Testing id 2\"; "
-             "content:\"John\"; asn1:relative_offset -11, "
-             "oversize_length 132; sid:2;)";
-    sigs[2]= "alert ip any any -> any any (msg:\"Testing id 3\"; "
-             "content:\"John\"; asn1:  relative_offset 5000, "
-             "oversize_length 132; sid:3;)";
-
-    uint32_t sid[3] = {1, 2, 3};
-
-    // The second signature should match
-    uint32_t results[1][3] = {{0, 1, 0}};
-
-    result = UTHGenericTest(p, 1, sigs, sid, (uint32_t *) results, 3);
-
-    UTHFreePackets(p, 1);
-end:
-    return result;
-}
-
 #endif /* UNITTESTS */
 
 /**
@@ -1410,35 +467,10 @@ end:
 static void DetectAsn1RegisterTests(void)
 {
 #ifdef UNITTESTS
-    UtRegisterTest("DetectAsn1TestParse01", DetectAsn1TestParse01);
-    UtRegisterTest("DetectAsn1TestParse02", DetectAsn1TestParse02);
-    UtRegisterTest("DetectAsn1TestParse03", DetectAsn1TestParse03);
-
-    UtRegisterTest("DetectAsn1TestParse04", DetectAsn1TestParse04);
-    UtRegisterTest("DetectAsn1TestParse05", DetectAsn1TestParse05);
-    UtRegisterTest("DetectAsn1TestParse06", DetectAsn1TestParse06);
-
-    UtRegisterTest("DetectAsn1TestParse07", DetectAsn1TestParse07);
-    UtRegisterTest("DetectAsn1TestParse08", DetectAsn1TestParse08);
-    UtRegisterTest("DetectAsn1TestParse09", DetectAsn1TestParse09);
-
-    UtRegisterTest("DetectAsn1TestParse10", DetectAsn1TestParse10);
-    UtRegisterTest("DetectAsn1TestParse11", DetectAsn1TestParse11);
-    UtRegisterTest("DetectAsn1TestParse12", DetectAsn1TestParse12);
-    UtRegisterTest("DetectAsn1TestParse13", DetectAsn1TestParse13);
-    UtRegisterTest("DetectAsn1TestParse14", DetectAsn1TestParse14);
-    UtRegisterTest("DetectAsn1TestParse15", DetectAsn1TestParse15);
-    UtRegisterTest("DetectAsn1Test01 - oversize_len", DetectAsn1Test01);
-    UtRegisterTest("DetectAsn1Test02 - oversize_len", DetectAsn1Test02);
-    UtRegisterTest("DetectAsn1Test03 - bitstring_ovf", DetectAsn1Test03);
-    UtRegisterTest("DetectAsn1Test04 - bitstring_ovf", DetectAsn1Test04);
-    UtRegisterTest("DetectAsn1Test05 - double_ovf", DetectAsn1Test05);
-    UtRegisterTest("DetectAsn1Test06 - double_ovf", DetectAsn1Test06);
     UtRegisterTest("DetectAsn1TestReal01", DetectAsn1TestReal01);
     UtRegisterTest("DetectAsn1TestReal02", DetectAsn1TestReal02);
     UtRegisterTest("DetectAsn1TestReal03", DetectAsn1TestReal03);
     UtRegisterTest("DetectAsn1TestReal04", DetectAsn1TestReal04);
-    UtRegisterTest("DetectAsn1TestReal05", DetectAsn1TestReal05);
 
 #endif /* UNITTESTS */
 }
index 9f350e25b131b6d74856b9535bee729766874bb4..eda36d4c2a383125d98a081263b4a332fadedead 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2010 Open Information Security Foundation
+/* Copyright (C) 2020 Open Information Security Foundation
  *
  * You can copy, redistribute or modify this Program under the terms of
  * the GNU General Public License version 2 as published by the Free
 /**
  * \file detect-asn1.h
  *
- * \author Pablo Rincon Crespo <pablo.rincon.crespo@gmail.com>
- *
  * Implements "asn1" keyword
  */
 #ifndef __DETECT_ASN1_H__
 #define __DETECT_ASN1_H__
 
-
-/* Function check flags */
-#define         ASN1_BITSTRING_OVF       0x01
-#define         ASN1_DOUBLE_OVF          0x02
-#define         ASN1_OVERSIZE_LEN        0x04
-#define         ASN1_ABSOLUTE_OFFSET     0x10
-#define         ASN1_RELATIVE_OFFSET     0x20
-
-typedef struct DetectAsn1Data_ {
-    uint8_t flags;     /* flags indicating the checks loaded */
-    uint32_t oversize_length;   /* Length argument if needed */
-    uint16_t absolute_offset;   /* Length argument if needed */
-    int32_t relative_offset;   /* Length argument if needed */
-} DetectAsn1Data;
-
 /* prototypes */
 void DetectAsn1Register (void);