setup-app-layer.py: integrate detect buffer setup

Add --detect to setup a detect buffer.

Obsoletes setup-app-layer-detect.sh.
pull/3487/head
Jason Ish 7 years ago committed by Victor Julien
parent 35fd10bc2e
commit 7ec7d85ecc

@ -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

@ -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".

Loading…
Cancel
Save