]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
updated wizard
authorRuss Combs <rucombs@cisco.com>
Tue, 8 Jul 2014 19:25:39 +0000 (15:25 -0400)
committerRuss Combs <rucombs@cisco.com>
Tue, 8 Jul 2014 19:25:39 +0000 (15:25 -0400)
31 files changed:
ChangeLog
lua/snort.lua
src/file_api/file_service.cc
src/flow/flow.cc
src/flow/flow.h
src/flow/flow_control.cc
src/framework/inspector.h
src/framework/parameter.cc
src/ips_options/ips_content.cc
src/ips_options/ips_ipopts.cc
src/ips_options/ips_react.cc
src/ips_options/ips_replace.cc
src/ips_options/ips_rpc.cc
src/loggers/alert_syslog.cc
src/main/snort_types.h
src/managers/inspector_manager.cc
src/network_inspectors/binder/binder.cc
src/network_inspectors/binder/binder.h
src/network_inspectors/port_scan/port_scan.cc
src/search_engines/acsmx2.cc
src/service_inspectors/wizard/hexes.cc
src/service_inspectors/wizard/magic.h
src/service_inspectors/wizard/spells.cc
src/service_inspectors/wizard/wiz_module.cc
src/service_inspectors/wizard/wiz_module.h
src/service_inspectors/wizard/wizard.cc
src/stream/ip/ip_session.cc
src/stream/stream_api.cc
src/stream/tcp/tcp_session.cc
src/stream/udp/udp_session.cc
tools/CMakeLists.txt

index a008987d2c5261a6527373272e009ac7a74af2da..bf4bed8cd05c82b33a01120bd1c26d26f132b9bc 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,6 @@
+99
+-- updated wizard
+
 98
 -- initial wizard implementation
 
index 6d3a18613e1193cc8dd06f7ae9176b3282d96d3f..f578fc05b8ef47684506cd9b98831c189cb46881 100644 (file)
@@ -1,6 +1,5 @@
 ---------------------------------------------------------------------------
--- This file contains a sample snort configuration.  You should follow
--- the steps to create your own custom configuration.
+-- Snort++ prototype configuration
 --
 -- let install_dir be a variable indicating where you installed Snort++.
 -- then do:
@@ -9,7 +8,7 @@
 -- export SNORT_LUA_PATH=$install_dir/conf/
 ---------------------------------------------------------------------------
 
-require('snort_config')
+require('snort_config')  -- for loading
 
 -- useful constants
 K = 1024
@@ -17,7 +16,7 @@ M = K * K
 G = M * K
 
 ---------------------------------------------------------------------------
--- Step #1: Set paths, ports, and nets:
+-- Set paths, ports, and nets:
 --
 -- variables with 'PATH' in the name are vars
 -- variables with 'PORT' in the name are portvars
@@ -29,8 +28,6 @@ G = M * K
 -- paths
 ---------------------------------------------------------------------------
 -- Path to your rules files (this can be a relative path)
--- Note for Windows users:  You are advised to make this an absolute path,
--- such as:  c:\snort\rules
 
 RULE_PATH = '../rules'
 BUILTIN_RULE_PATH = '../preproc_rules'
@@ -129,39 +126,19 @@ GTP_PORTS = ' 2123 2152 3386'
 RPC_PORTS = 
     ' 111 32770 32771 32772 32773 32774 32775 32776 32777 32778 32779'
 
--- Configure ports to ignore 
---[[
-ignore_ports =
-{
-    tcp = ' 21 6667:6671 1356'
-    udp = ' 1:17 53'
-}
---]]
-
-tcp_client_ports = SSH_PORTS .. FTP_PORTS .. MAIL_PORTS .. RPC_PORTS ..
-[[
-    23 25 42 53 79 109 113 119 135 136 137 139 161 445 513 514 587 593 691
-    1433 1521 1741 3306 6070 6665 6666 6667 6668 6669 7000 8181 
-]]
-tcp_server_ports = ''
-tcp_both_ports = HTTP_PORTS ..
-[[
-    443 465 563 636 989 992 993 994 995 7907 7802 7801 7900 7901 7902 7903
-    7904 7905 7906 7908 7909 7910 7911 7912 7913 7914 7915 7916 7917 7918
-    7919 7920
-]]
-
 ---------------------------------------------------------------------------
--- Step #2: configure builtin features
+-- configure builtin features
 ---------------------------------------------------------------------------
 
+cd_udp = { gtp_ports = GTP_PORTS }
+
 -- Configure active response for non inline operation.
 active =
 {
     device = 'eth0',
     attempts = 2,
-    --max_active_responses = 2,
-    --min_response_seconds = 5
+    max_responses = 0,
+    min_interval = 1
 }
 
 -- Configure DAQ related options for inline operation.
@@ -191,14 +168,15 @@ search_engine =
     --search_method = 'lowmem_q',
     split_any_any = true,
     search_optimize = true,
-    max_pattern_len = 20
+    max_pattern_len = 20,
+    max_queue_events = 16
 }
 
 -- Configure the event queue.
 event_queue =
 {
-    max_queue = 8,
-    log = 5,
+    max_queue = 16,
+    log = 8,
     order_events = 'content_length'
 }
 
@@ -236,8 +214,9 @@ profile =
 }
 
 ---------------------------------------------------------------------------
--- Step #3: Configure inspectors
+-- configure inspectors
 ---------------------------------------------------------------------------
+
 normalize =
 { 
     ip4 = 
@@ -256,17 +235,6 @@ normalize =
     icmp6 = true
 }
 
---defrag_global = { max_frags = 65536 }
-
-defrag_engine =
-{
-    policy = 'windows', 
-    detect_anomalies = true,
-    overlap_limit = 10,
-    min_frag_length = 100,
-    timeout = 180
-}
-
 arp_spoof =
 {
     unicast = true,
@@ -279,10 +247,7 @@ arp_spoof =
 
 back_orifice = { }
 
-rpc_decode =
-{
-    ports = RPC_PORTS
-}
+rpc_decode = { }
 
 port_scan_global = { memcap = 10000000 }
 
@@ -320,10 +285,10 @@ perf_monitor =
 }
 
 ---------------------------------------------------------------------------
--- HTTP normalization and anomaly detection.
+-- http normalization and anomaly detection
 ---------------------------------------------------------------------------
 
-http_global =
+http_inspect =
 {
     unicode_map =
     {
@@ -345,45 +310,26 @@ default_http_methods =
 
 http_server =
 {
-    unicode_map =
-    {
-        map_file = '/etc/unicode.map',
-        code_page = 1252
-    },
     http_methods = default_http_methods,
     chunk_length = 500000,
     server_flow_depth = 0,
     client_flow_depth = 0,
     post_depth = 65495,
-    oversize_dir_length = 500,
-    max_header_length = 750,
-    max_headers = 100,
-    max_spaces = 200,
-    small_chunk_length = { size = 10, count = 5 },
-    ports = HTTP_PORTS,
-    non_rfc_chars = '0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07',
-    enable_cookies = true,
-    extended_response_inspection = true,
-    inspect_gzip = true,
-    normalize_utf = true,
-    unlimited_decompress = true,
-    normalize_javascript = true,
-    apache_whitespace = false,
-    ascii = false,
-    bare_byte = false,
-    directory = false,
-    double_decode = false,
-    iis_backslash = false,
-    iis_delimiter = false,
-    iis_unicode = false,
-    multi_slash = false,
-    utf_8 = false,
-    u_encode = true,
-    webroot = false
-}
-
----------------------------------------------------------------------------
--- FTP / Telnet normalization and anomaly detection.
+}
+
+hi_x =
+{
+    http_methods = default_http_methods,
+    chunk_length = 500000,
+    server_flow_depth = 1460,
+    client_flow_depth = 1460,
+    post_depth = 65495,
+}
+
+nhttp_inspect = { }
+
+---------------------------------------------------------------------------
+-- ftp / telnet normalization and anomaly detection
 ---------------------------------------------------------------------------
 
 telnet =
@@ -392,16 +338,9 @@ telnet =
     check_encrypted = true,
     ayt_attack_thresh = 20,
     normalize = true,
-    ports = '23',
     detect_anomalies = true
 }
 
-ftp_global =
-{
-    encrypted_traffic = false,
-    check_encrypted = true,
-}
-
 ftp_default_commands =
 [[
     ABOR ACCT ADAT ALLO APPE AUTH CCC CDUP CEL CLNT CMD CONF CWD DELE ENC
@@ -423,7 +362,6 @@ ftp_format_commands =
 
 ftp_server =
 {
-    ports = FTP_PORTS,
     def_max_param_len = 100,
 
     encrypted_traffic = false,
@@ -481,89 +419,70 @@ ftp_client =
 }
 
 ---------------------------------------------------------------------------
--- the following inspector configs are just prototypes
--- they are nominally validated but they are not actually loaded
----------------------------------------------------------------------------
----------------------------------------------------------------------------
--- Target-Based stateful inspection/stream reassembly.
+-- stream reassembly and anomaly detection
 ---------------------------------------------------------------------------
 
-stream_global =
+stream =
 {
-    tcp_memcap = 123456789,
-    show_rebuilt_packets = false,
-    prune_log_max = 0,
-    paf_max = 16384,
-    
-    tcp_cache = { max_sessions = 256 * K, idle_timeout = 60 },
-    udp_cache = { max_sessions = 128 * K, pruning_timeout = 30 },
-    ip_cache = { max_sessions = 64 * K },
-    icmp_cache = { max_sessions = 32 * K },
+    ip_cache = { max_sessions = 64000 },
+    icmp_cache = { max_sessions = 0 },
+    tcp_cache = { max_sessions = 256000, idle_timeout = 60 },
+    udp_cache = { max_sessions = 128000, pruning_timeout = 30 },
+}
 
-    active_response = 
-    {
-        max_responses = 0,
-        min_interval = 1
-    }
+stream_ip =
+{
+    session_timeout = 980,
+    policy = 'windows', 
+    max_overlaps = 10,
+    max_frags = 8191,
+    min_frag_length = 100
+}
+
+stream_icmp =
+{
+    session_timeout = 180,
 }
 
 stream_tcp =
 {
     policy = 'windows',
+    paf_max = 16384,
 
     session_timeout = 180,
-    require_3whs = 180,
-    flush_factor = 0,
+    --require_3whs = -1,
+    show_rebuilt_packets = false,
 
+    flush_factor = 0,
     overlap_limit = 10,
 
-    queue_limit =
-    {
-        max_bytes = 3,
-        max_segments = 1300,
-    },
-    small_segments = 
-    {
-        count = 10,
-        maximum_size = 128,
-        ignore_ports = '1 2 3'
-    },
-
     footprint = 0,
-    reassemble_async = false,
+    reassemble_async = true,
     ignore_any_rules = false,
-
-    client_ports = tcp_client_ports,
-    server_ports = tcp_server_ports,
-    both_ports = tcp_both_ports,
 }
 
-stream_udp =
-{
-    session_timeout = 180,
-    ignore_any_rules = false,
-}
-
-stream_icmp =
+tcp_x =
 {
+    policy = 'linux',
+    paf_max = 16384,
     session_timeout = 180,
 }
 
-stream_ip =
+stream_udp =
 {
     session_timeout = 180,
+    ignore_any_rules = false,
 }
 
 ---------------------------------------------------------------------------
--- Step #4: Configure loggers
+-- loggers
 ---------------------------------------------------------------------------
 
 -- alerts + packets
 unified2 =
 {
     file = 'u2.log',
-    limit = 128,
-    units = 'M',
+    limit = 128 * M,
     nostamp = true,
     mpls_event_types = true,
     vlan_event_types = true
@@ -580,9 +499,7 @@ alert_full = { }
 log_tcpdump = { file = 'snort++.pcap' }
 
 ---------------------------------------------------------------------------
--- Step #6: Customize your rule set
---
--- NOTE: All categories are enabled in this conf file
+-- ips rules and filters
 ---------------------------------------------------------------------------
 
 dir = os.getenv('SNORT_LUA_PATH')
@@ -591,27 +508,13 @@ if ( not dir ) then
     dir = ''
 end
 
-dofile(dir .. 'classification.lua')
-dofile(dir .. 'reference.lua')
+include '../lua/classification.lua'
 
---[[
-event_filter =
-{
-    { gid = 1, sid = 2, type = 'both', count = 1, seconds = 5 },
-    { gid = 1, sid = 1, type = 'both', count = 1, seconds = 5 }
-}
---]]
---
-suppress =
-{
-    { gid = 116, sid = 408 },
-    { gid = 116, sid = 412 },
-    { gid = 116, sid = 414 },
-}
+print 'Loading references'
+dofile(dir .. 'reference.lua')
 
 default_rules =
 [[
-#output unified2: filename snort.alert, limit 128, nostamp
 # snort-classic comments, includes, and rules with $VARIABLES
 # (rules files support the same syntax)
 
@@ -622,17 +525,49 @@ default_rules =
 
 # text rules
 #include $RULE_PATH/local.rules
-#include $RULE_PATH/app-detect.rules
-#include $RULE_PATH/attack-responses.rules
-#include $RULE_PATH/backdoor.rules
 
 # so rules
-#include $PLUGIN_RULE_PATH/bad-traffic.rules
-#include $PLUGIN_RULE_PATH/chat.rules
 #include $PLUGIN_RULE_PATH/dos.rules
 
-alert tcp any any -> any 80 ( sid:1; msg:"1"; content:"HTTP"; )
-alert tcp any 80 -> any any ( sid:2; msg:"2"; content:"HTTP"; )
+# no metadata:service:
+#alert http ( sid:1; msg:"1"; content:"HTTP"; )
+#alert http any -> 1.2.3.4 ( sid:2; msg:"2"; content:"HTTP"; )
+#alert http any any -> 1.2.3.4 80 ( sid:3; msg:"3"; content:"HTTP"; )
+
+# no ; separated content suboptions
+#alert tcp $HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS (msg:"BLACKLIST URI request for known malicious URI - /inst.php?fff="; flow:to_server,established; http_uri; content:"/inst.php?fff=", nocase; content:  "coid=", nocase; metadata:impact_flag red, policy balanced-ips drop, policy security-ips drop, reference:url,labs.snort.org/docs/16924.html; classtype:trojan-activity; sid:16924; rev:5;)
+
+# fast_pattern:<offset>,<length>; ->
+# fast_pattern:<offset> <length>;
+
+# test pattern = "ABABACD"
+#alert tcp any any -> any any ( sid:100; content:"ABA"; )
+#alert tcp any any -> any any ( sid:200; raw_data; content:"ABA"; )
+#alert tcp any any -> any any ( sid:300; pkt_data; content:"ABA"; )
+#alert tcp any any -> any any ( sid:400; content:"ABA"; content:"C", depth 6; )
+#alert tcp any any -> any any ( sid:401; content:"ABA"; content:"C", depth 5; )
+#alert tcp any any -> any any ( sid:402; content:"ABA"; content:"C", offset 5; )
+#alert tcp any any -> any any ( sid:403; content:"ABA"; content:"C", offset 6; )
+#alert tcp any any -> any any ( sid:404; content:"ABA"; content:"C", offset 5, depth 6; )
+#alert tcp any any -> any any ( sid:510; content:"ABA"; content:"C", within 1; )
+#alert tcp any any -> any any ( sid:110; pcre:"/ABA/"; )
+#alert tcp any any -> any any ( sid:210; raw_data; pcre:"/ABA/"; )
+#alert tcp any any -> any any ( sid:310; pkt_data; pcre:"/ABA/"; )
+#alert tcp any any -> any any ( sid:410; pcre:"/ABA/"; pcre:"/C/"; )
+#alert tcp any any -> any any ( sid:411; pcre:"/ABA/"; pcre:"/AC/R"; )
+#alert tcp any any -> any any ( sid:412; pcre:"/ABA/"; pcre:"/AC/"; )
+#alert tcp any any -> any any ( sid:414; pcre:"/ABA/"; pcre:"/C/R"; )
+
+#alert ( gid:134; sid:1; )
+#alert ( gid:134; sid:2; )
+#alert ( gid:134; sid:3; )
+
+#alert tcp any any -> any 80 ( sid:2; rev:3; http_uri; content:"evil", fast_pattern; )
+#alert tcp any any -> any 80 ( sid:2; rev:3; http_uri; content:"evil", nocase, fast_pattern; )
+#alert tcp any any -> any 80 ( sid:2; rev:3; http_uri; content:"evil"; )
+#alert tcp any any -> any 80 ( sid:2; rev:3; http_uri; content:"evil"; content:"sauce"; )
+#alert tcp any any -> any 80 ( sid:2; rev:3; http_uri; content:"evil"; content:"sauce", distance:0; )
+#alert tcp any any -> any 80 ( sid:2; rev:3; http_uri; content:"evil"; http_header; content:"Generic"; )
 ]]
 
 network =
@@ -645,57 +580,226 @@ ips =
 {
     --include = '../active.rules',
     --rules = default_rules,
-    enable_builtin_rules = true
+    enable_builtin_rules = false
 }
 
--- prototype bindings:
--- nets and ports move out of inspector configurations
--- only need to specify non-default bindings
--- match = id | ((vlans | networks) [protocol [ports]])
--- config = type [name [direction]]
--- type = module | 'file'
--- name = type (default) | instance | filename
--- action = block | allow | inspect (default)
--- direction = from client | from server | any (default) | none
-
-bindings =
+--[[
+event_filter =
+{
+    { gid = 1, sid = 2, type = 'both', count = 1, seconds = 5 },
+    { gid = 1, sid = 1, type = 'both', count = 1, seconds = 5 }
+}
+--]]
+
+suppress =
+{
+    { gid = 116, sid = 408 },
+    { gid = 116, sid = 412 },
+    { gid = 116, sid = 414 },
+}
+
+---------------------------------------------------------------------------
+-- net map attributes (replaces attribte table)
+---------------------------------------------------------------------------
+
+hosts = 
 {
     {
-        match = { id = 5 },
-        config = { type = 'bo', name = 'bo2' }
+        ip = '1.2.3.4',
+        frag_policy = 'linux',
+        tcp_policy = 'linux',
+        services =
+        {
+            { name = 'ftp', proto = 'tcp', port = 21 },
+            { name = 'smtp', proto = 'tcp', port = 25 },
+            { name = 'http', proto = 'tcp', port = 80 }
+        }
     },
+    {
+        ip = '2.4.6.8',
+        frag_policy = 'windows',
+        tcp_policy = 'windows',
+        services =
+        {
+            { name = 'netbios', proto = 'tcp', port = 137 },
+            { name = 'imap', proto = 'tcp', port = 143 },
+        }
+    }
+}
+
+---------------------------------------------------------------------------
+-- prototype wizard
+---------------------------------------------------------------------------
+
+http_methods = { 'GET', 'POST', 'HEAD' } -- build from default_http_methods
+ftp_commands = { 'USER' } -- add others
+sip_methods = { 'INVITE', 'NOTIFY' } -- add others
+isakmp_hex = { '?????????????????|01|', '?????????????????|10|' }
+
+telnet_commands =
+{
+    '|FF F0|', '|FF F1|', '|FF F2|', '|FF F3|',
+    '|FF F4|', '|FF F5|', '|FF F6|', '|FF F7|',
+    '|FF F8|', '|FF F9|', '|FF FA|', '|FF FB|',
+    '|FF FC|', '|FF FD|', '|FF FE|', '|FF FF|'
+}
 
+wizard =
+{
+    spells =
     {
-        match = { id = 4 },
-        config = { type = 'file', name = '4.lua' }
+        { service = 'ftp', proto = 'tcp', client_first = false,
+          to_server = ftp_commands, to_client = { '220*FTP' } },
+
+        { service = 'http', proto = 'tcp', client_first = true,
+          to_server = http_methods, to_client = { 'HTTP/' } },
+
+        { service = 'imap', proto = 'tcp', client_first = false,
+          to_server = { 'LOGIN', 'AUTHENTICATE', 'STARTTLS' },
+          to_client = { '**OK', '**BYE' } },
+
+        { service = 'pop3', proto = 'tcp', client_first = false,
+          to_server = { 'USER', 'APOP' },
+          to_client = { '+OK', '-ERR' } },
+
+        { service = 'sip', proto = 'tcp', client_first = true,
+          to_server = sip_methods, to_client = { 'SIP/' } },
+
+        { service = 'smtp', proto = 'tcp', client_first = false,
+          to_server = { 'HELO', 'EHLO' },
+          to_client = { '220*SMTP', '220*MAIL' } },
+
+        { service = 'ssh', proto = 'tcp', client_first = true,
+          to_server = { '*SSH' }, to_client = { '*SSH' } }
     },
+    hexes =
+    {
+        { service = 'dcerpc', proto = 'tcp', client_first = true, 
+          to_server = { '|05 00|' }, to_client = { '|05 00|' } },
+
+        { service = 'dnp3', proto = 'tcp', client_first = true, 
+          to_server = { '|05 64|' }, to_client = { '|05 64|' } },
+
+        { service = 'isakmp',  proto = 'udp', client_first = true,
+          to_server = isakmp_hex, to_client = isakmp_hex },
+--[[
+        { service = 'modbus', proto = 'tcp', client_first = true,
+          to_server = { '??|0 0|' } },
+
+        { service = 'rpc', proto = 'tcp', client_first = true,
+          to_server = { '????|0 0 0 0 0 0 0 1|' },
+          to_client = { '????|0 0 0 0 0 0 0 1|' } },
+--]]
+        { service = 'smb', proto = 'tcp', client_first = true,
+          to_server = { '|FF|SMB' }, to_client = { '|FF|SMB' } },
+
+        { service = 'smb', proto = 'udp', client_first = true,
+          to_server = { '|FF|SMB' }, to_client = { '|FF|SMB' } },
+
+        { service = 'ssl', proto = 'tcp', client_first = true,
+          to_server = { '|16 03|' }, to_client = { '|16 03|' } },
+
+        { service = 'telnet', proto = 'tcp', client_first = true,
+          to_server = telnet_commands, to_client = telnet_commands },
+    }
+}
 
+---------------------------------------------------------------------------
+-- prototype bindings:
+--
+-- nets and ports move out of inspector configurations
+-- only need to specify non-default bindings
+-- when: policy_id, vlans, nets, proto, ports, roles, service
+-- use: action | file | type,name | policy_id [,service]
+-- when: days, times are tbd
+---------------------------------------------------------------------------
+
+-- define a target selector
+target_x = { nets = HTTP_SERVERS, proto = 'tcp', ports = HTTP_PORTS } 
+
+binder =
+{
+    -- policy selected by firewall
     {
-        match = { vlans = '123' },
-        config = { type = 'detect', name = '123.detect' }
+        when = { policy_id = 'uuid' },
+        use = { file = 'uuid.lua' }
     },
-
+    -- policy based on vlan
     {
-        match = { networks = '1.2.3.0/24', protocol = 'tcp' },
-        config = { type = 'stream_tcp', name = 'last', direction = 'any' }
+        when = { vlans = '123' },
+        use = { file = 'vlan.lua' }
     },
-
+    -- policy based on cidr
     {
-        match = { networks = '1.2.3.4', protocol = 'tcp', ports = '80 8080' },
-        config = { type = 'http_inspect' },
-        action = 'inspect'
+        when = { nets = HOME_NET },
+        use = { file = 'net.lua' }
     },
+    -- targeted config
+    --{ when = target_x, use = { type = 'stream_tcp', name = 'tcp_x' } },
+    --{ when = target_x, use = { type = 'http_server', name = 'hi_x' } },
+
+    -- classic ports only config
+    --{ when = { proto = 'tcp', ports = HTTP_PORTS }, use = { type = 'http_server' } },
+    --{ when = { proto = 'tcp', ports = HTTP_PORTS }, use = { type = 'nhttp_inspect' } },
+    { when = { proto = 'tcp', ports = FTP_PORTS }, use = { type = 'ftp_server' } },
+    { when = { proto = 'tcp', ports = RPC_PORTS }, use = { type = 'rpc_decode' } },
 
+    -- auto service id override
     {
-        match = { networks = '1.2.3.4', protocol = 'tcp', ports = '88 8088' },
-        config = { type = 'http', name = 'iis' },
+        when = { nets = '3.4.5.0/24', proto = 'tcp', ports = '80', role = 'any' },
+        use = { service = 'http' }
     },
-
+    -- allow rule - replaces config ignore_ports
     {
-        match = { networks = '192.168.1.0/24', protocol = 'udp', ports = '53' },
-        action = 'block'
-    }
+        when = { nets = '4.5.6.7', proto = 'udp', ports = '53' },
+        use = { action = 'allow' }
+    },
+    { when = { proto = 'tcp', ports = SSH_PORTS }, use = { action = 'allow' } },
+    -- block rule
+    {
+        when = { nets = '5.6.7.8', proto = 'tcp', ports = '8' },
+        use = { action = 'block' }
+    },
+    { when = { proto = 'tcp', ports = 'any' }, use = { type = 'wizard' } },
+    { when = { proto = 'udp', ports = 'any' }, use = { type = 'wizard' } },
 }
  
--- lowmem_q = { var = "test" }
+---------------------------------------------------------------------------
+-- error handling
+---------------------------------------------------------------------------
+
+--[[
+-- parse error handled by lua:
+foo bar
+
+ERROR: can't load ../lua/snort.lua: ../lua/snort.lua:629: '=' expected near 'bar'
+Fatal Error, Quitting..
+
+-- another:
+stream_xyz.foo = 'bar'
+
+ERROR: can't init ../lua/snort.lua: ../lua/snort.lua:635: attempt to index global 'stream_xyz' (a nil value)
+Fatal Error, Quitting..
+
+-- semantic errors handled by Snort++ don't have file / line:
+stream_tcp.foo = 'bar'
+
+ERROR: can't find stream_tcp.foo
+Fatal Error, Quitting..
+
+-- multiple range errors:
+stream_tcp.policy = 'bar'
+stream_tcp.paf_max = 123456
+
+ERROR invalid stream_tcp.policy = bar
+ERROR invalid stream_tcp.paf_max = 123456
+ERROR: see prior configuration errors
+Fatal Error, Quitting..
+
+-- undetected error:
+suppress = { { gid = 116, sid = 408 } }
+-- other foo
+suppress = { { gid = 116, sid = 412 } }
+}
+--]]
 
index 099af099f374353b24fac13d45a02b846cfcd0e8..6e7ccfe65744492b7b842063f4599160f5cc6efc 100644 (file)
@@ -324,6 +324,7 @@ static void printFileContext (FileContext* context)
         cur += used;
     }
 
+#if 0
     if (unused > 0)
     {
         used = snprintf(cur, unused, "\nProcessed size: %u\n",
@@ -331,6 +332,7 @@ static void printFileContext (FileContext* context)
         //unused -= used;
         //cur += used;
     }
+#endif
 
     buf[sizeof(buf) - 1] = '\0';
     printf("%s", buf);
index 63a3c5d774e479a3f814d828f49291082bacd69b..599cf964a461380e19d69291779bb3554bf024d4 100644 (file)
@@ -112,6 +112,8 @@ void Flow::reset()
 
 void Flow::clear(bool freeAppData)
 {
+    assert(flow_state < 3);
+
     if ( freeAppData )
         free_application_data();
 
index bfa81e0e94259e4d6cef0cf70c1659c030c22505..d379f122766cddd89d488279e9aff43670867aa2 100644 (file)
@@ -121,7 +121,6 @@ struct FlowState
 
     char       direction;
     char       ignore_direction; /* flag to ignore traffic on this session */
-
 };
 
 typedef enum {
@@ -180,6 +179,11 @@ public:
         clouseau = ins;
         clouseau->add_ref();
     };
+    void set_gadget(Inspector* ins)
+    {
+        gadget = ins;
+        gadget->add_ref();
+    };
 
 public:  // FIXIT privatize if possible
     // these fields are const after initialization
@@ -192,12 +196,15 @@ public:  // FIXIT privatize if possible
     Flow* prev, * next;
     Inspector* ssn_client;
     Inspector* ssn_server;
-    Inspector* clouseau;
     long last_data_seen;
 
     // everything from here down is zeroed
     FlowData* appDataList;
+    Inspector* clouseau;
+    Inspector* gadget;
+    const char* service;
 
+    int flow_state;
     FlowState s5_state;  // FIXIT rename this (s5 not appropriate)
 
     snort_ip client_ip; // FIXTHIS family and bits should be changed to uint16_t
index 16fae283a3d5088bd0c473ee8d980ceec9eaad2e..f31556f2f57683467e962279d58e6c893f49dfc6 100644 (file)
@@ -267,22 +267,32 @@ unsigned FlowControl::process(FlowCache* cache, Packet* p)
 
     p->flow = flow;
 
-    if ( !flow->ssn_client )
-    {
+    if ( !flow->flow_state )
         binder->eval(p);
 
-        if ( !flow->session->setup(p) )
-            return 0;
-
-        news = 1;
-    }
-
-    // no session client/server for allowed/blocked flows
-    if ( flow->ssn_client )
+    switch ( flow->flow_state )
+    {
+    case 1: // block
+        stream.drop_packet(p);
+        break;
+
+    case 2: // allow
+        stream.stop_inspection(flow, p, SSN_DIR_BOTH, -1, 0);
+        break;
+
+    case 3: // setup
+        if ( !flow->ssn_client || !flow->session->setup(p) )
+        {
+            flow->flow_state = 2;
+            break;
+        }
+        flow->flow_state = 4;
+        // now process
+
+    case 4: // inspect
         flow->session->process(p);
-
-    if ( news )
-        binder->eval(p);
+        break;
+    }
 
     if ( flow->next && is_bidirectional(flow) )
         cache->unlink_uni(flow);
index eaa734a928c301f8b4d8a4da79e7e38c3ea00eca..c8ce82d82bb4f4aa1f9ae131b380c0823d451de2 100644 (file)
@@ -73,6 +73,7 @@ public:
 
     virtual void eval(Packet*) = 0;
     virtual void meta(int, const uint8_t*) { };
+    virtual int exec(int, void*) { return 0; };
 
     // framework support
     unsigned get_ref(unsigned i) { return ref_count[i]; };
index 1daea9038f9f60e935012a6b2cf30236e6386fb7..b15cf09e33f5ee6264ae97eb4bcacd5e291ea073 100644 (file)
@@ -252,15 +252,21 @@ static bool valid_addr(Value& v, const char*)
 static bool valid_bit_list(Value& v, const char* r)
 {
     string pl = v.get_string();
-    stringstream ss(pl);
-    ss >> setbase(0);
+    string bs;
 
     int max = r ? strtol(r, nullptr, 0) : 0;
     assert(max > 0);
 
-    string bs;
-    bs.assign(max+1, '0');
+    if ( pl == "any" )
+    {
+        bs.assign(max+1, '1');
+        v.set(bs.c_str());
+        return true;
+    }
+    stringstream ss(pl);
+    ss >> setbase(0);
 
+    bs.assign(max+1, '0');
     int bit;
 
     while ( ss >> bit )
index 2a07ac96a800b3af8dc03ae2191c9abc295dc039..40bc5905535157079b2adff06240236de3683d35 100644 (file)
@@ -576,7 +576,10 @@ static void parse_offset(
         ParseError("offset can't be used with itself, distance, or within");
 
     if (data == NULL)
+    {
         ParseError("Missing argument to 'offset' option");
+        return;
+    }
 
     if (isdigit(data[0]) || data[0] == '-')
     {
@@ -602,7 +605,10 @@ static void parse_depth(
         ParseError("depth can't be used with itself, distance, or within");
 
     if (data == NULL)
+    {
         ParseError("Missing argument to 'depth' option");
+        return;
+    }
 
     if (isdigit(data[0]) || data[0] == '-')
     {
@@ -635,7 +641,10 @@ static void parse_distance(
         ParseError("distance can't be used with itself, offset, or depth");
 
     if (data == NULL)
+    {
         ParseError("Missing argument to 'distance' option");
+        return;
+    }
 
     if (isdigit(data[0]) || data[0] == '-')
     {
@@ -660,7 +669,10 @@ static void parse_within(
         ParseError("within can't be used with itself, offset, or depth");
 
     if (data == NULL)
+    {
         ParseError("Missing argument to 'within' option");
+        return;
+    }
 
     if (isdigit(data[0]) || data[0] == '-')
     {
index 3a847d9289b14190b4d9e0d202253838aa59be39..a26ab4a46afc080a08ecfeb9804e925c41111bbf 100644 (file)
@@ -168,6 +168,7 @@ static void ipopts_parse(char *data, IpOptionData *ds_ptr)
     if(data == NULL)
     {
         ParseError("IP Option keyword missing argument");
+        return;
     }
 
     while(isspace((u_char)*data))
index b921171d9b2dd7e87e1596cec32821907e88f004..6eec723a5d55476e45c993939b530d90391720f8 100644 (file)
@@ -219,7 +219,10 @@ static void react_getpage (SnortConfig* sc)
     size_t n;
 
     if ( !sc )
+    {
         ParseError("Snort config for parsing is NULL.");
+        return;
+    }
 
     if ( s_page || !sc->react_page ) return;
 
index fa2859318c8229a67502119ff957d6aea4b689cd..8613952ec44a509cca99ba8b079a696ecb365622 100644 (file)
@@ -64,6 +64,7 @@ static void replace_parse(char* args, string& s)
     if ( !args )
     {
         ParseError("missing argument to 'replace' option");
+        return;
     }
     /* clear out the temp buffer */
     memset(tmp_buf, 0, MAX_PATTERN_SIZE);
@@ -90,6 +91,7 @@ static void replace_parse(char* args, string& s)
     {
         ParseError("Replace data needs to be enclosed "
                    "in quotation marks (\")");
+        return;
     }
 
     /* set the end to be NULL */
index 407e2c358bc049ceda0e6667424fb0d1ea4e2146..ad4d96fb509335c0021e6bd4acbe7d2e73128d36 100644 (file)
@@ -271,6 +271,7 @@ void rpc_parse(char *data, RpcCheckData *ds_ptr)
     else
     {
         ParseError("Invalid applicaion number in rpc rule option");
+        return;
     }
 
     if(*tmp == '\0') return;
index faaa1329d308a5717c1ea5067d776fb79bd8e000..a164a76ab894b17af85f772b509976f28e33d307 100644 (file)
@@ -213,6 +213,7 @@ static void AlertSyslog(
         else
             SnortSnprintfAppend(event_string, sizeof(event_string), "ALERT ");
 
+        if ( event )
         {
             if ((event->sig_info->classType != NULL)
                     && (event->sig_info->classType->name != NULL))
index 16e15f046148a3552591529cd6f062554c46a85f..840e391ca6266a6a461f3c1d20fabf9953bcd5c8 100644 (file)
@@ -138,7 +138,7 @@ typedef uint16_t Port;
 #  define NORETURN
 # endif
 #else
-# define NORETURN
+# define NORETURN __attribute__ ((noreturn))
 #endif
 
 #if !defined(__GNUC__) || __GNUC__ < 2 || \
index 117b8d5b797691610cc67f0d5c147c327b1b214b..2b511d6e0195aa170b987dabe323e10e7a17378d 100644 (file)
@@ -532,11 +532,28 @@ void InspectorManager::execute (Packet* p)
 
     if ( p->dsize )
     {
-        if ( p->flow && p->flow->clouseau )
-            p->flow->clouseau->eval(p);
+        Flow* flow = p->flow;
 
+        if ( !flow )
+            return;
+
+        if ( flow->clouseau )
+        {
+            flow->clouseau->eval(p);
+
+            if ( flow->service )
+            {
+                Inspector* ins = InspectorManager::get_inspector("binder");
+                if ( ins )
+                    ins->exec(0, flow);
+
+                flow->clouseau = nullptr;
+            }
+        }
         // FIXIT BIND need more than one service inspector?
         //::execute(p, fp->service.vec, fp->service.num);
+        if ( flow->gadget )
+            flow->gadget->eval(p);
     }
     else
         DisableDetect(p);
index 51a39a8c922a7908c356b4c673cd3b46b2e114d8..7f606689427e0b6f255e9795b5d03018352bbc79 100644 (file)
@@ -99,16 +99,14 @@ public:
     { LogMessage("Binder\n"); };
 
     void eval(Packet*);
+    int exec(int, void*);
 
     void add(Binding* b)
     { bindings.push_back(b); };
 
 private:
-    Inspector* get_clouseau(Flow*, Packet*);
-
+    int check_rules(Flow*, Packet*);
     void init_flow(Flow*);
-    void init_flow(Flow*, Packet*);
-    bool check_rules(Flow*, Packet*);
 
 private:
     vector<Binding*> bindings;
@@ -128,48 +126,40 @@ Binder::~Binder()
 void Binder::eval(Packet* p)
 {
     Flow* flow = p->flow;
-
-    if ( !flow->ssn_client && !check_rules(flow, p) )
-        init_flow(flow);
-
-    else if ( !flow->clouseau )
-        init_flow(flow, p);
-
+    flow->flow_state = check_rules(flow, p);
     ++tstats.total_packets;
 }
 
-// FIXIT bind services - this is a temporary hack that just looks at ports,
-// need to examine all key fields for matching.  ultimately need a routing
-// table, scapegoat tree, magic wand, etc.
-Inspector* Binder::get_clouseau(Flow* flow, Packet* p)
+// FIXIT implement inspector lookup from policy / bindings
+static Inspector* find_inspector(const char*)
 {
-    Binding* pb;
-    unsigned i, sz = bindings.size();
+    return nullptr;
+}
 
-    Port port = (p->packet_flags & PKT_FROM_CLIENT) ? p->dp : p->sp;
+int Binder::exec(int, void* pv)
+{
+    Flow* flow = (Flow*)pv;
+    Inspector* ins = find_inspector(flow->service);
 
-    for ( i = 0; i < sz; i++ )
+    if ( ins )
     {
-        pb = bindings[i];
-
-        if ( !check_proto(flow, pb->proto) )
-            continue;
-
-        if ( pb->ports.test(port) )
-            break;
+        flow->gadget = ins;
+        stream.set_splitter(flow, true, ins->get_splitter(true));
+        stream.set_splitter(flow, false, ins->get_splitter(false));
     }
-    Inspector* ins;
-
-    if ( i == sz || !pb->type.size() )
-        ins = InspectorManager::get_inspector("wizard");
-        
     else
-        ins = InspectorManager::get_inspector(pb->type.c_str());
+    {
+        stream.set_splitter(flow, true, new AtomSplitter(true));
+        stream.set_splitter(flow, false, new AtomSplitter(false));
+    }
 
-    return ins;
+    return 0;
 }
 
-bool Binder::check_rules(Flow* flow, Packet* p)
+// FIXIT bind services - this is a temporary hack that just looks at ports,
+// need to examine all key fields for matching.  ultimately need a routing
+// table, scapegoat tree, etc.
+int Binder::check_rules(Flow* flow, Packet* p)
 {
     Binding* pb;
     unsigned i, sz = bindings.size();
@@ -186,19 +176,27 @@ bool Binder::check_rules(Flow* flow, Packet* p)
         if ( pb->ports.test(port) )
             break;
     }
-    if ( i < sz && pb->action )
-    {
-        // FIXIT this is repeatedly entered on same flow; need to 
-        // shortcircuit so we don't walk the rules each time
-        if ( pb->action == BA_ALLOW )
-            stream.stop_inspection(flow, p, SSN_DIR_BOTH, -1, 0);
+        
+    if ( i == sz )
+        return BA_ALLOW;  // default action FIXIT make configurable
 
-        else //if ( pb->action == BA_BLOCK )
-            stream.drop_packet(p);
+    if ( pb->action != BA_INSPECT )
+        return pb->action;
 
-        return true;
+    init_flow(flow);
+    Inspector* ins;
+
+    if ( !pb->type.size() || pb->type == "wizard" )
+    {
+        ins = InspectorManager::get_inspector("wizard");
+        flow->set_clouseau(ins);
     }
-    return false;
+    else
+    {
+        ins = InspectorManager::get_inspector(pb->type.c_str()); 
+        flow->set_gadget(ins);
+    }
+    return BA_INSPECT;
 }
 
 void Binder::init_flow(Flow* flow)
@@ -207,8 +205,6 @@ void Binder::init_flow(Flow* flow)
     {
     case IPPROTO_IP:
         set_session(flow, "stream_ip");
-        stream.set_splitter(flow, true, nullptr);
-        stream.set_splitter(flow, false, nullptr);
         break;
 
     case IPPROTO_ICMP:
@@ -228,25 +224,6 @@ void Binder::init_flow(Flow* flow)
     }
 }
 
-void Binder::init_flow(Flow* flow, Packet* p)
-{
-    Inspector* ins = get_clouseau(flow, p);
-
-    if ( !ins )
-        return;
-
-    if ( flow->protocol == IPPROTO_TCP )
-    {
-        StreamSplitter* ss = ins->get_splitter(true);
-        StreamSplitter* cs = ins->get_splitter(false);
-
-        stream.set_splitter(flow, true, ss);
-        stream.set_splitter(flow, false, cs);
-    }
-
-    flow->set_clouseau(ins);
-}
-
 //-------------------------------------------------------------------------
 // api stuff
 //-------------------------------------------------------------------------
index 020f060f7d9ccebddb63254e8a92af8306af9f01..5db8d4318400fc88d20cd4b57ac7a2d7d9f9b304 100644 (file)
@@ -34,9 +34,9 @@ enum BindRole
 
 enum BindAction
 {
-    BA_INSPECT,
+    BA_BLOCK = 1,
     BA_ALLOW,
-    BA_BLOCK
+    BA_INSPECT
 };
 
 enum BindProto
index 82638e41ebb5e20e306dcfdf41267b8d4f10f151..fd118ea7e2df047dd3e244b744be0bd9d450a620 100644 (file)
@@ -322,7 +322,7 @@ static int MakeOpenPortInfo(
 {
     int dsize;
 
-    if(!total_size || !buffer)
+    if ( !total_size || !buffer || !user )
         return -1;
 
     dsize = (g_tmp_pkt->max_dsize - *total_size);
index 701175d3310e2e337dfe4399439c440bff733444..3884d15b714e3fb1cdba92e8b6731bee065cce3e 100644 (file)
@@ -424,7 +424,7 @@ static void queue_add (QUEUE * s, int state)
 
     if (!s->head) {
         q = s->tail = s->head =
-                          (QNODE *)AC_MALLOC(sizeof(QNODE), ACSM2_MEMORY_TYPE__NONE);
+            (QNODE *)AC_MALLOC(sizeof(QNODE), ACSM2_MEMORY_TYPE__NONE);
         MEMASSERT (q, "queue_add");
         q->state = state;
         q->next = 0;
index 3270812c6b435a67fa125dbb24d427e5b2f7962c..bfd949148e5daef95a6579a007c9c4de278adabd 100644 (file)
@@ -74,7 +74,7 @@ bool HexBook::translate(const char* in, HexVector& out)
 //-------------------------------------------------------------------------
 
 void HexBook::add_spell(
-    const char* key, HexVector& hv, unsigned i, MagicPage* p)
+    const char* key, const char* val, HexVector& hv, unsigned i, MagicPage* p)
 {
     while ( i < hv.size() )
     {
@@ -90,9 +90,10 @@ void HexBook::add_spell(
         ++i;
     }
     p->key = key;
+    p->value = val;
 }
 
-bool HexBook::add_spell(const char* key)
+bool HexBook::add_spell(const char* key, const char* val)
 {
     HexVector hv;
 
@@ -120,7 +121,7 @@ bool HexBook::add_spell(const char* key)
     if ( p->key == key )
         return false;
 
-    add_spell(key, hv, i, p);
+    add_spell(key, val, hv, i, p);
     return true;
 }
 
@@ -162,7 +163,7 @@ MagicPage* HexBook::find_spell(
 const char* HexBook::find_spell(const uint8_t* data, unsigned len) const
 {
     if ( MagicPage* p = find_spell(data, len, root) )
-        return p->key.c_str();
+        return p->value.c_str();
     else
         return nullptr;
 }
index f18a4a08c7e44cc6d35097be921a826f233ddc14..02ac9f1ec85cc2c3a9aedfab5482e91a89c0ee51 100644 (file)
@@ -29,8 +29,11 @@ class MagicBook;
 struct MagicPage
 {
     std::string key;
+    std::string value;
+
     MagicPage* next[256];
     MagicPage* any;
+
     const MagicBook& book;
 
     MagicPage(const MagicBook&);
@@ -44,7 +47,7 @@ class MagicBook
 public:
     virtual ~MagicBook();
 
-    virtual bool add_spell(const char* key) = 0;
+    virtual bool add_spell(const char* key, const char* val) = 0;
     virtual const char* find_spell(const uint8_t*, unsigned len) const = 0;
 
     const MagicPage* page1()
@@ -66,12 +69,12 @@ public:
     SpellBook();
     ~SpellBook() { };
 
-    bool add_spell(const char*);
+    bool add_spell(const char*, const char*);
     const char* find_spell(const uint8_t*, unsigned len) const;
 
 private:
     bool translate(const char*, HexVector&);
-    void add_spell(const char*, HexVector&, unsigned, MagicPage*);
+    void add_spell(const char*, const char*, HexVector&, unsigned, MagicPage*);
     MagicPage* find_spell(const uint8_t*, unsigned, MagicPage*, unsigned = 0) const;
 };
 
@@ -86,12 +89,12 @@ public:
     HexBook() { };
     ~HexBook() { };
 
-    bool add_spell(const char*);
+    bool add_spell(const char*, const char*);
     const char* find_spell(const uint8_t*, unsigned len) const;
 
 private:
     bool translate(const char*, HexVector&);
-    void add_spell(const char*, HexVector&, unsigned, MagicPage*);
+    void add_spell(const char*, const char*, HexVector&, unsigned, MagicPage*);
     MagicPage* find_spell(const uint8_t*, unsigned, MagicPage*, unsigned = 0) const;
 };
 
index a73581415cc733e177462a5478ce756e5187de5a..fecbb469fc20ef49f03da4fe4158a340558bbf7d 100644 (file)
@@ -64,7 +64,7 @@ bool SpellBook::translate(const char* in, HexVector& out)
 }
 
 void SpellBook::add_spell(
-    const char* key, HexVector& hv, unsigned i, MagicPage* p)
+    const char* key, const char* val, HexVector& hv, unsigned i, MagicPage* p)
 {
     while ( i < hv.size() )
     {
@@ -79,9 +79,10 @@ void SpellBook::add_spell(
         ++i;
     }
     p->key = key;
+    p->value = val;
 }
 
-bool SpellBook::add_spell(const char* key)
+bool SpellBook::add_spell(const char* key, const char* val)
 {
     HexVector hv;
 
@@ -109,7 +110,7 @@ bool SpellBook::add_spell(const char* key)
     if ( p->key == key )
         return false;
 
-    add_spell(key, hv, i, p);
+    add_spell(key, val, hv, i, p);
     return true;
 }
 
@@ -161,7 +162,7 @@ const char* SpellBook::find_spell(const uint8_t* data, unsigned len) const
         len = max;
     
     if ( MagicPage* p = find_spell(data, len, root) )
-        return p->key.c_str();
+        return p->value.c_str();
     else
         return nullptr;
 }
index b291f292580c0071353c8fd48c79783b68a4f948..81b8241930079de95358bd4f535b266f39684dac 100644 (file)
@@ -36,10 +36,10 @@ static const char* s_name = "wizard";
 // wizard module
 //-------------------------------------------------------------------------
 
-static const Parameter wizard_hex_params[] =
+static const Parameter wizard_hex_param[] =
 {
-    { "service", Parameter::PT_STRING, nullptr, nullptr,
-      "name of service" },
+    { "hex", Parameter::PT_STRING, nullptr, nullptr,
+      "sequence of data with wild chars (?)" },
 
     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
 };
@@ -50,24 +50,24 @@ static const Parameter wizard_hexes_params[] =
       "name of service" },
 
     { "proto", Parameter::PT_SELECT, "tcp | udp", "tcp",
-      "name of service" },
+      "protocol to scan" },
 
     { "client_first", Parameter::PT_BOOL, nullptr, "true",
       "which end initiates data transfer" },
 
-    { "to_server", Parameter::PT_LIST, wizard_hex_params, nullptr,
-      "sequence of offsets and data" },
+    { "to_server", Parameter::PT_LIST, wizard_hex_param, nullptr,
+      "sequence of data with wild chars (?)" },
 
-    { "to_client", Parameter::PT_LIST, wizard_hex_params, nullptr,
-      "sequence of offsets and data" },
+    { "to_client", Parameter::PT_LIST, wizard_hex_param, nullptr,
+      "sequence of data with wild chars (?)" },
 
     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
 };
 
-static const Parameter wizard_spell_params[] =
+static const Parameter wizard_spell_param[] =
 {
-    { "service", Parameter::PT_STRING, nullptr, nullptr,
-      "name of service" },
+    { "spell", Parameter::PT_STRING, nullptr, nullptr,
+      "sequence of data with wild cards (*)" },
 
     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
 };
@@ -78,16 +78,16 @@ static const Parameter wizard_spells_params[] =
       "name of service" },
 
     { "proto", Parameter::PT_SELECT, "tcp | udp", "tcp",
-      "name of service" },
+      "protocol to scan" },
 
     { "client_first", Parameter::PT_BOOL, nullptr, "true",
       "which end initiates data transfer" },
 
-    { "to_server", Parameter::PT_LIST, wizard_spell_params, nullptr,
-      "sequence of offsets and data" },
+    { "to_server", Parameter::PT_LIST, wizard_spell_param, nullptr,
+      "list of initial tokens with wild cards (*)" },
 
-    { "to_client", Parameter::PT_LIST, wizard_spell_params, nullptr,
-      "sequence of offsets and data" },
+    { "to_client", Parameter::PT_LIST, wizard_spell_param, nullptr,
+      "list of initial tokens with wild cards (*)" },
 
     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
 };
@@ -123,7 +123,7 @@ WizardModule::~WizardModule()
 bool WizardModule::set(const char*, Value& v, SnortConfig*)
 {
     if ( v.is("service") )
-        return true;
+        service = v.get_string();
 
     else if ( v.is("proto") )
         return true;
@@ -131,20 +131,12 @@ bool WizardModule::set(const char*, Value& v, SnortConfig*)
     else if ( v.is("client_first") )
         return true;
 
-    else if ( v.is("to_server") )
-    {
-        if ( hex )
-            c2s_hexes->add_spell(v.get_string());
-        else
-            c2s_spells->add_spell(v.get_string());
-    }
-    else if ( v.is("to_client") )
-    {
-        if ( hex )
-            s2c_hexes->add_spell(v.get_string());
-        else
-            s2c_spells->add_spell(v.get_string());
-    }
+    else if ( v.is("hex") )
+        spells.push_back(v.get_string());
+
+    else if ( v.is("spell") )
+        spells.push_back(v.get_string());
+
     else
         return false;
 
@@ -158,20 +150,58 @@ bool WizardModule::begin(const char* fqn, int, SnortConfig*)
         c2s_hexes = new HexBook;
         s2c_hexes = new HexBook;
 
-        c2s_spells = new HexBook;
-        s2c_spells = new HexBook;
+        c2s_spells = new SpellBook;
+        s2c_spells = new SpellBook;
     }
-    else if ( !strcmp(fqn, "hexes") )
+    else if ( !strcmp(fqn, "wizard.hexes") )
         hex = true;
 
-    else if ( !strcmp(fqn, "spells") )
+    else if ( !strcmp(fqn, "wizard.spells") )
         hex = false;
 
+    else if ( !strcmp(fqn, "wizard.hexes.to_client") )
+        c2s = false;
+
+    else if ( !strcmp(fqn, "wizard.spells.to_client") )
+        c2s = false;
+
+    else if ( !strcmp(fqn, "wizard.hexes.to_server") )
+        c2s = true;
+
+    else if ( !strcmp(fqn, "wizard.spells.to_server") )
+        c2s = true;
+
     return true;
 }
 
-bool WizardModule::end(const char*, int, SnortConfig*)
+void WizardModule::add_spells(MagicBook* b, string& service)
+{
+    for ( auto p : spells )
+        b->add_spell(p.c_str(), service.c_str());
+}
+
+bool WizardModule::end(const char*, int idx, SnortConfig*)
 {
+    if ( !idx )
+        return true;
+
+    if ( hex )
+    {
+        if ( c2s )
+            add_spells(c2s_hexes, service);
+        else
+            add_spells(s2c_hexes, service);
+    }
+    else
+    {
+        if ( c2s )
+            add_spells(c2s_spells, service);
+        else
+            add_spells(s2c_spells, service);
+    }
+    spells.clear();
+    service.clear();
+
     return true;
 }
 
index ee0bf296a982454525a2b75a3097799d4e728a96..c559401ab7c62c2528e3675c18b4ee4ca4ca0df9 100644 (file)
@@ -22,6 +22,7 @@
 #ifndef WIZ_MODULE_H
 #define WIZ_MODULE_H
 
+#include <string>
 #include "framework/module.h"
 
 class MagicBook;
@@ -38,8 +39,15 @@ public:
 
     MagicBook* get_book(bool c2s, bool hex);
 
+private:
+    void add_spells(MagicBook*, std::string&);
+
 private:
     bool hex;
+    bool c2s;
+
+    std::string service;
+    std::vector<std::string> spells;
 
     MagicBook* c2s_hexes;
     MagicBook* s2c_hexes;
index c932496716b59b7264d89f10f94d898965666336..f8e5897369919397a65dcf59f0523d4eaa2df099 100644 (file)
@@ -54,7 +54,7 @@ struct WizStats
 {
     PegCount tcp_scans;
     PegCount tcp_hits;
-    PegCount udp_pkts;
+    PegCount udp_scans;
     PegCount udp_hits;
 };
 
@@ -62,7 +62,7 @@ static const char* wiz_pegs[] =
 {
     "tcp scans",
     "tcp hits",
-    "udp packets",
+    "udp scans",
     "udp hits"
 };
 
@@ -77,9 +77,6 @@ struct Wand
 {
     const MagicPage* hex;
     const MagicPage* spell;
-
-    void clear()
-    { hex = spell = nullptr; };
 };
 
 class Wizard;
@@ -113,7 +110,8 @@ public:
     StreamSplitter* get_splitter(bool);
 
     void reset(Wand&, bool tcp, bool c2s);
-    bool cast_spell(Wand&, const uint8_t*, unsigned);
+    bool cast_spell(Wand&, Flow*, const uint8_t*, unsigned);
+    bool spellbind(const MagicPage*, Flow*, const uint8_t*, unsigned);
 
 public:
     MagicBook* c2s_hexes;
@@ -143,12 +141,12 @@ MagicSplitter::~MagicSplitter()
 }
 
 PAF_Status MagicSplitter::scan (
-    Flow*, const uint8_t* data, uint32_t len,
+    Flow* f, const uint8_t* data, uint32_t len,
     uint32_t, uint32_t* fp)
 {
     ++tstats.tcp_scans;
 
-    if ( wizard->cast_spell(wand, data, len) )
+    if ( wizard->cast_spell(wand, f, data, len) )
     { 
         // FIXIT len + 1 means go back to the last flush point
         // (0 means start of this buffer)
@@ -201,14 +199,10 @@ void Wizard::eval(Packet* p)
     Wand wand;
     reset(wand, false, p->packet_flags & PKT_FROM_CLIENT);
 
-    if ( cast_spell(wand, p->data, p->dsize) )
-    {
-        // FIXIT spellbind inspector gadget here
-        // and make the wizard disappear from flow
+    if ( cast_spell(wand, p->flow, p->data, p->dsize) )
         ++tstats.udp_hits;
-    }
 
-    ++tstats.udp_pkts;
+    ++tstats.udp_scans;
 }
 
 StreamSplitter* Wizard::get_splitter(bool c2s)
@@ -216,24 +210,22 @@ StreamSplitter* Wizard::get_splitter(bool c2s)
     return new MagicSplitter(c2s, this);
 }
 
-bool Wizard::cast_spell(
-    Wand& w, const uint8_t* data, unsigned len)
+bool Wizard::spellbind(
+    const MagicPage* m, Flow* f, const uint8_t* data, unsigned len)
 {
     // FIXIT convert to stateful find
-    if ( w.hex && w.hex->book.find_spell(data, len) )
-    {
-        // FIXIT spellbind inspector gadget here
-        // and make the wizard disappear from flow
-        w.clear();
+    f->service = m->book.find_spell(data, len);
+    return f->service != nullptr;
+}
+
+bool Wizard::cast_spell(
+    Wand& w, Flow* f, const uint8_t* data, unsigned len)
+{
+    if ( w.hex && spellbind(w.hex, f, data, len) )
         return true;
-    }
 
-    if ( w.spell && w.spell->book.find_spell(data, len) )
-    {
-        // FIXIT spellbind inspector gadget here
-        w.clear();
+    if ( w.spell && spellbind(w.spell, f, data, len) )
         return true;
-    }
 
     return false;
 }
index 8076ba70d9f7bd649c10277f62a851709809f583..e5186d53ef0c275483830a1631a69cc7dbefed19 100644 (file)
@@ -54,8 +54,11 @@ static PreprocStats* ip_get_profile(const char* key)
 
 void IpSessionCleanup (Flow* lws, FragTracker* tracker)
 {
-    Defrag* d = get_defrag(lws->ssn_server);
-    d->cleanup(tracker);
+    if ( lws->ssn_server )
+    {
+        Defrag* d = get_defrag(lws->ssn_server);
+        d->cleanup(tracker);
+    }
 
     if (lws->s5_state.session_flags & SSNFLAG_PRUNED)
     {
index 060aee815bcac5abb5f2f98a2b144f634d97bad3..e76b1dcf1bcf0b78c01591dd84e3cee39ab0d2fe 100644 (file)
@@ -234,6 +234,7 @@ void Stream::stop_inspection(
     /* TODO: Handle bytes/response parameters */
 
     DisableInspection(p);
+    flow->flow_state = 2;
 }
 
 void Stream::resume_inspection(Flow* flow, char dir)
@@ -302,6 +303,7 @@ void Stream::drop_packet(Packet *p)
     if (!flow)
         return;
 
+    flow->flow_state = 1;
     flow->session->clear();
 
     if (!(p->packet_flags & PKT_STATELESS))
index 4d70745ac750deb7bafc4f320c04e920dbdecc88..5516d9f01e4070aa248e1f50e4d77711a733c84e 100644 (file)
@@ -537,9 +537,8 @@ void Stream5SetSplitterTcp (Flow* lwssn, bool c2s, StreamSplitter* ss)
         trk = &tcpssn->client;
     }
 
-    // FIXIT we have a sequencing issue with binder
-    //if ( trk->splitter && tcpssn->tcp_init )
-    //    delete trk->splitter;
+    if ( trk->splitter && tcpssn->tcp_init )
+        delete trk->splitter;
 
     trk->splitter = ss;
 
@@ -2683,6 +2682,7 @@ static void TcpSessionClear (Flow* lwssn, TcpSession* tcpssn, int freeApplicatio
     s5_paf_clear(&tcpssn->server.paf_state);
 
     // update light-weight state
+    lwssn->flow_state = 0;
     lwssn->clear(freeApplicationData);
 
     // generate event for rate filtering
@@ -7270,21 +7270,15 @@ bool TcpSession::setup (Packet* p)
         flow->session_state = STREAM5_STATE_SYN;  // FIXIT same as line 4555
 
     assert(flow->session == this);
-
-    // FIXIT binder sets splitters before we get here
-    StreamSplitter* sc = client.splitter;
-    StreamSplitter* ss = server.splitter;
-
-    PAF_Status pc = client.paf_state.paf;
-    PAF_Status ps = server.paf_state.paf;
-
     reset();
 
-    client.paf_state.paf = pc;
-    server.paf_state.paf = ps;
+    Inspector* ins = flow->clouseau;
+    if ( !ins )
+        ins = flow->gadget;
+    assert(ins);
 
-    client.splitter = sc;
-    server.splitter = ss;
+    stream.set_splitter(flow, true, ins->get_splitter(true));
+    stream.set_splitter(flow, false, ins->get_splitter(false));
 
     ssnStats.sessions++;
     return true;
index aa3cd0b694d932960f635a007ced94601f85d6c2..bded4968111198dfbc1efe68cd0634ae8ad28695 100644 (file)
@@ -83,6 +83,7 @@ static void UdpSessionCleanup(Flow *lwssn)
         CloseStreamSession(&sfBase, SESSION_CLOSED_NORMALLY);
     }
 
+    lwssn->flow_state = 0;
     lwssn->clear();
 
     udpStats.released++;
index c1c78e046baf53ff8def22cba7fc5f859c1eeec2..4e270488c07060441d5eefb9f31ca310b8f61861 100644 (file)
@@ -1,4 +1,4 @@
 
 add_subdirectory(u2boat)
 add_subdirectory(u2spewfoo)
-add_subdirectory(snort2lua)
+#add_subdirectory(snort2lua)