]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
setup-app-layer.py: integrate detect buffer setup
authorJason Ish <ish@unx.ca>
Wed, 19 Sep 2018 05:51:37 +0000 (23:51 -0600)
committerVictor Julien <victor@inliniac.net>
Wed, 19 Sep 2018 19:02:35 +0000 (21:02 +0200)
Add --detect to setup a detect buffer.

Obsoletes setup-app-layer-detect.sh.

scripts/setup-app-layer-detect.sh [deleted file]
scripts/setup-app-layer.py

diff --git a/scripts/setup-app-layer-detect.sh b/scripts/setup-app-layer-detect.sh
deleted file mode 100755 (executable)
index ff5aab6..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-#! /usr/bin/env bash
-#
-# Script to provision a new application layer detector and parser.
-
-set -e
-
-# Fail if "ed" is not available.
-if ! which ed > /dev/null 2>&1; then
-    echo "error: the program \"ed\" is required for this script"
-    exit 1
-fi
-
-function usage() {
-    cat <<EOF
-
-usage: $0 <protocol name> <buffer name>
-
-This script will provision content inspection for app-layer decoded
-buffers.
-
-Examples:
-
-    $0 Gopher Buffer
-    $0 DNP3 Buffer
-    $0 Http Etag
-
-EOF
-}
-
-# Make sure we are running from the correct directory.
-set_dir() {
-    if [ -e ./suricata.c ]; then
-       cd ..
-    elif [ -e ./src/suricata.c ]; then
-       # Do nothing.
-       true
-    else
-       echo "error: this does not appear to be a suricata source directory."
-       exit 1
-    fi
-}
-
-fail_if_exists() {
-    path="$1"
-    if test -e "${path}"; then
-       echo "error: ${path} already exists."
-       exit 1
-    fi
-}
-
-function copy_template_file() {
-    src="$1"
-    dst="$2"
-
-    echo "Creating ${dst}."
-
-    sed -e '/TEMPLATE_START_REMOVE/,/TEMPLATE_END_REMOVE/d' \
-       -e "s/TEMPLATE_BUFFER/${protoname_upper}_${buffername_upper}/g" \
-       -e "s/TEMPLATE/${protoname_upper}/g" \
-       -e "s/template-buffer/${protoname_lower}-${buffername_lower}/g" \
-       -e "s/template/${protoname_lower}/g" \
-       -e "s/TemplateBuffer/${protoname}${buffername}/g" \
-       -e "s/Template/${protoname}/g" \
-       > ${dst} < ${src}
-}
-
-function copy_templates() {
-    detect_h_dst="src/detect-${protoname_lower}-${buffername_lower}.h"
-    detect_c_dst="src/detect-${protoname_lower}-${buffername_lower}.c"
-    tests_detect_c_dst="src/tests/detect-${protoname_lower}-${buffername_lower}.c"
-
-    fail_if_exists ${detect_h_dst}
-    fail_if_exists ${detect_c_dst}
-    fail_if_exists ${tests_detect_c_dst}
-
-    copy_template_file "src/detect-template-buffer.h" ${detect_h_dst}
-    copy_template_file "src/detect-template-buffer.c" ${detect_c_dst}
-    copy_template_file "src/tests/detect-template-buffer.c" ${tests_detect_c_dst}
-}
-
-function patch() {
-    filename="src/Makefile.am"
-    echo "Patching ${filename}."
-    ed -s ${filename} > /dev/null <<EOF
-/^detect-template-buffer.c
-t-
-s/template-buffer/${protoname_lower}-${buffername_lower}/g
-w
-EOF
-
-    filename="src/detect-engine-register.c"
-    echo "Patching ${filename}."
-
-    ed -s ${filename} > /dev/null <<EOF
-/#include "detect-template-buffer.h"
-t-
-s/template-buffer/${protoname_lower}-${buffername_lower}/
-w
-EOF
-
-    ed -s ${filename} > /dev/null <<EOF
-/DetectTemplateBufferRegister
-t-
-s/TemplateBuffer/${protoname}${buffername}/
-w
-EOF
-
-    filename="src/detect-engine-register.h"
-    echo "Patching ${filename}."
-    ed -s ${filename} > /dev/null <<EOF
-/DETECT_AL_TEMPLATE_BUFFER
-t-
-s/TEMPLATE_BUFFER/${protoname_upper}_${buffername_upper}/
-w
-EOF
-}
-
-set_dir
-
-protoname="$1"
-buffername="$2"
-
-if [ "${protoname}" = "" ] || [ "${buffername}" = "" ]; then
-    usage
-    exit 1
-fi
-
-# Make sure the protocol name looks like a proper name (starts with a
-# capital letter).
-case "${protoname}" in
-
-    [[:upper:]]*)
-       # OK.
-       ;;
-
-    "")
-       usage
-       exit 1
-       ;;
-
-    *)
-       echo "error: protocol name must beging with an upper case letter"
-       exit 1
-       ;;
-
-esac
-
-protoname_lower=$(printf ${protoname} | tr '[:upper:]' '[:lower:]')
-protoname_upper=$(printf ${protoname} | tr '[:lower:]' '[:upper:]')
-buffername_lower=$(printf ${buffername} | tr '[:upper:]' '[:lower:]')
-buffername_upper=$(printf ${buffername} | tr '[:lower:]' '[:upper:]')
-
-copy_templates
-patch
-
-cat <<EOF
-
-The following files have been created and linked into the build:
-
-    detect-${protoname_lower}-${buffername_lower}.h detect-${protoname_lower}-${buffername_lower}.c
-
-        The setup for the content inspection sticky buffer keyword.
-
-Please fix in src/detect.h the values for:
-    SIG_MASK_REQUIRE_${protoname_upper}_STATE
-    SIG_MASK_REQUIRE_TEMPLATE_STATE
-
-EOF
index f20b4d98840daa2c6fe0d88553179ea22b5e63b6..200e94ec9c6e9af8d25fa6e75dce91ce7a97041e 100755 (executable)
@@ -22,7 +22,7 @@ def fail_if_exists(filename):
     if os.path.exists(filename):
         raise SetupError("%s already exists" % (filename))
 
-def common_copy_templates(proto, pairs):
+def common_copy_templates(proto, pairs, replacements=()):
     upper = proto.upper()
     lower = proto.lower()
 
@@ -48,6 +48,9 @@ def common_copy_templates(proto, pairs):
                 if skip:
                     continue
 
+                for (old, new) in replacements:
+                    line = line.replace(old, new)
+
                 line = re.sub("TEMPLATE(_RUST)?", upper, line)
                 line = re.sub("template(-rust)?", lower, line)
                 line = re.sub("Template(Rust)?", proto, line)
@@ -67,6 +70,8 @@ def copy_app_layer_templates(proto, rust):
              "src/app-layer-%s.h" % (lower)),
             ("rust/src/applayertemplate/mod.rs",
              "rust/src/applayer%s/mod.rs" % (lower)),
+            ("rust/src/applayertemplate/template.rs",
+             "rust/src/applayer%s/gopher.rs" % (lower)),
             ("rust/src/applayertemplate/parser.rs",
              "rust/src/applayer%s/parser.rs" % (lower)),
         )
@@ -288,6 +293,90 @@ def logger_patch_util_profiling_c(proto):
             output.write(line)
     open(filename, "w").write(output.getvalue())
 
+def detect_copy_templates(proto, buffername, rust):
+    lower = proto.lower()
+    buffername_lower = buffername.lower()
+
+    if rust:
+        pairs = (
+            ("src/detect-template-rust-buffer.h",
+             "src/detect-%s-%s.h" % (lower, buffername_lower)),
+            ("src/detect-template-rust-buffer.c",
+             "src/detect-%s-%s.c" % (lower, buffername_lower)),
+        )
+        replacements = (
+            ("TEMPLATE_RUST_BUFFER", "%s_%s" % (
+                proto.upper(), buffername.upper())),
+            ("template-rust-buffer", "%s-%s" % (
+                proto.lower(), buffername.lower())),
+            ("template_rust_buffer", "%s_%s" % (
+                proto.lower(), buffername.lower())),
+            ("TemplateRustBuffer", "%s%s" % (proto, buffername)),
+        )
+    else:
+        pairs = (
+            ("src/detect-template-buffer.h",
+             "src/detect-%s-%s.h" % (lower, buffername_lower)),
+            ("src/detect-template-buffer.c",
+             "src/detect-%s-%s.c" % (lower, buffername_lower)),
+        )
+        replacements = (
+            ("TEMPLATE_BUFFER", "%s_%s" % (proto.upper(), buffername.upper())),
+            ("template-buffer", "%s-%s" % (proto.lower(), buffername.lower())),
+            ("template_buffer", "%s_%s" % (proto.lower(), buffername.lower())),
+            ("TemplateBuffer", "%s%s" % (proto, buffername)),
+        )
+
+    common_copy_templates(proto, pairs, replacements)
+
+def detect_patch_makefile_am(protoname, buffername):
+    filename = "src/Makefile.am"
+    print("Patching %s." % (filename))
+    output = io.StringIO()
+    with open(filename) as infile:
+        for line in infile:
+            if line.startswith("detect-template-buffer.c"):
+                new = line.replace("template-buffer", "%s-%s" % (
+                    protoname.lower(), buffername.lower()))
+                output.write(new)
+            output.write(line)
+    open(filename, "w").write(output.getvalue())
+
+def detect_patch_detect_enginer_register_c(protoname, buffername):
+    filename = "src/detect-engine-register.c"
+    print("Patching %s." % (filename))
+    output = io.StringIO()
+    with open(filename) as infile:
+        for line in infile:
+
+            if line.find("detect-template-buffer.h") > -1:
+                new = line.replace("template-buffer", "%s-%s" % (
+                    protoname.lower(), buffername.lower()))
+                output.write(new)
+
+            if line.find("DetectTemplateBufferRegister") > -1:
+                new = line.replace("TemplateBuffer", "%s%s" % (
+                    protoname, buffername))
+                output.write(new)
+
+            output.write(line)
+    open(filename, "w").write(output.getvalue())
+
+def detect_patch_detect_enginer_register_h(protoname, buffername):
+    filename = "src/detect-engine-register.h"
+    print("Patching %s." % (filename))
+    output = io.StringIO()
+    with open(filename) as infile:
+        for line in infile:
+
+            if line.find("DETECT_AL_TEMPLATE_BUFFER") > -1:
+                new = line.replace("TEMPLATE_BUFFER", "%s_%s" % (
+                    protoname.upper(), buffername.upper()))
+                output.write(new)
+
+            output.write(line)
+    open(filename, "w").write(output.getvalue())
+
 def proto_exists(proto):
     upper = proto.upper()
     for line in open("src/app-layer-protos.h"):
@@ -308,6 +397,13 @@ Examples:
 
     %(progname)s DNP3
     %(progname)s Gopher
+
+This script can also setup a detect buffer. This is a separate
+operation that must be done after creating the parser.
+
+Examples:
+
+    %(progname)s --detect Gopher Request
 """ % { "progname": progname, }
 
 def main():
@@ -320,7 +416,11 @@ def main():
                         help="Generate logger.")
     parser.add_argument("--parser", action="store_true", default=False,
                         help="Generate parser.")
+    parser.add_argument("--detect", action="store_true", default=False,
+                        help="Generate detect module.")
     parser.add_argument("proto", help="Name of protocol")
+    parser.add_argument("buffer", help="Name of buffer (for --detect)",
+                        nargs="?")
     args = parser.parse_args()
 
     proto = args.proto
@@ -332,14 +432,20 @@ def main():
     # Determine what to generate.
     parser = False
     logger = False
+    detect = False
 
     # If no --parser or no --logger, generate both.
-    if not args.parser and not args.logger:
+    if not args.parser and not args.logger and not args.detect:
         parser = True
         logger = True
     else:
         parser = args.parser
         logger = args.logger
+        detect = args.detect
+
+    if detect:
+        if args.buffer is None:
+            raise SetupError("--detect requires a buffer name")
 
     # Make sure we are in the correct directory.
     if os.path.exists("./suricata.c"):
@@ -373,6 +479,14 @@ def main():
         logger_patch_suricata_yaml_in(proto)
         logger_patch_util_profiling_c(proto)
 
+    if detect:
+        if not proto_exists(proto):
+            raise SetupError("no app-layer parser exists for %s" % (proto))
+        detect_copy_templates(proto, args.buffer, args.rust)
+        detect_patch_makefile_am(proto, args.buffer)
+        detect_patch_detect_enginer_register_c(proto, args.buffer)
+        detect_patch_detect_enginer_register_h(proto, args.buffer)
+
     if parser:
         if args.rust:
             print("""
@@ -416,6 +530,17 @@ A JSON application layer transaction logger for the protocol
             "proto_lower": proto.lower(),
         })
 
+    if detect:
+        print("""
+The following files have been created and linked into the build:
+
+    detect-%(protoname_lower)s-%(buffername_lower)s.h
+    detect-%(protoname_lower)s-%(buffername_lower)s.c
+""" % {
+    "protoname_lower": proto.lower(),
+    "buffername_lower": args.buffer.lower(),
+})
+
     if parser or logger:
         print("""
 Suricata should now build cleanly. Try running "make".