From: Russ Combs Date: Tue, 8 Jul 2014 19:25:39 +0000 (-0400) Subject: updated wizard X-Git-Tag: 3.0.0-233~1444^2~25 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4f14885c2e1febc4b0bc5af80dd7625c7eef7341;p=thirdparty%2Fsnort3.git updated wizard --- diff --git a/ChangeLog b/ChangeLog index a008987d2..bf4bed8cd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +99 +-- updated wizard + 98 -- initial wizard implementation diff --git a/lua/snort.lua b/lua/snort.lua index 6d3a18613..f578fc05b 100644 --- a/lua/snort.lua +++ b/lua/snort.lua @@ -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:,; -> +# fast_pattern: ; + +# 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 } } +} +--]] diff --git a/src/file_api/file_service.cc b/src/file_api/file_service.cc index 099af099f..6e7ccfe65 100644 --- a/src/file_api/file_service.cc +++ b/src/file_api/file_service.cc @@ -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); diff --git a/src/flow/flow.cc b/src/flow/flow.cc index 63a3c5d77..599cf964a 100644 --- a/src/flow/flow.cc +++ b/src/flow/flow.cc @@ -112,6 +112,8 @@ void Flow::reset() void Flow::clear(bool freeAppData) { + assert(flow_state < 3); + if ( freeAppData ) free_application_data(); diff --git a/src/flow/flow.h b/src/flow/flow.h index bfa81e0e9..d379f1227 100644 --- a/src/flow/flow.h +++ b/src/flow/flow.h @@ -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 diff --git a/src/flow/flow_control.cc b/src/flow/flow_control.cc index 16fae283a..f31556f2f 100644 --- a/src/flow/flow_control.cc +++ b/src/flow/flow_control.cc @@ -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); diff --git a/src/framework/inspector.h b/src/framework/inspector.h index eaa734a92..c8ce82d82 100644 --- a/src/framework/inspector.h +++ b/src/framework/inspector.h @@ -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]; }; diff --git a/src/framework/parameter.cc b/src/framework/parameter.cc index 1daea9038..b15cf09e3 100644 --- a/src/framework/parameter.cc +++ b/src/framework/parameter.cc @@ -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 ) diff --git a/src/ips_options/ips_content.cc b/src/ips_options/ips_content.cc index 2a07ac96a..40bc59055 100644 --- a/src/ips_options/ips_content.cc +++ b/src/ips_options/ips_content.cc @@ -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] == '-') { diff --git a/src/ips_options/ips_ipopts.cc b/src/ips_options/ips_ipopts.cc index 3a847d928..a26ab4a46 100644 --- a/src/ips_options/ips_ipopts.cc +++ b/src/ips_options/ips_ipopts.cc @@ -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)) diff --git a/src/ips_options/ips_react.cc b/src/ips_options/ips_react.cc index b921171d9..6eec723a5 100644 --- a/src/ips_options/ips_react.cc +++ b/src/ips_options/ips_react.cc @@ -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; diff --git a/src/ips_options/ips_replace.cc b/src/ips_options/ips_replace.cc index fa2859318..8613952ec 100644 --- a/src/ips_options/ips_replace.cc +++ b/src/ips_options/ips_replace.cc @@ -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 */ diff --git a/src/ips_options/ips_rpc.cc b/src/ips_options/ips_rpc.cc index 407e2c358..ad4d96fb5 100644 --- a/src/ips_options/ips_rpc.cc +++ b/src/ips_options/ips_rpc.cc @@ -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; diff --git a/src/loggers/alert_syslog.cc b/src/loggers/alert_syslog.cc index faaa1329d..a164a76ab 100644 --- a/src/loggers/alert_syslog.cc +++ b/src/loggers/alert_syslog.cc @@ -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)) diff --git a/src/main/snort_types.h b/src/main/snort_types.h index 16e15f046..840e391ca 100644 --- a/src/main/snort_types.h +++ b/src/main/snort_types.h @@ -138,7 +138,7 @@ typedef uint16_t Port; # define NORETURN # endif #else -# define NORETURN +# define NORETURN __attribute__ ((noreturn)) #endif #if !defined(__GNUC__) || __GNUC__ < 2 || \ diff --git a/src/managers/inspector_manager.cc b/src/managers/inspector_manager.cc index 117b8d5b7..2b511d6e0 100644 --- a/src/managers/inspector_manager.cc +++ b/src/managers/inspector_manager.cc @@ -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); diff --git a/src/network_inspectors/binder/binder.cc b/src/network_inspectors/binder/binder.cc index 51a39a8c9..7f6066894 100644 --- a/src/network_inspectors/binder/binder.cc +++ b/src/network_inspectors/binder/binder.cc @@ -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 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 //------------------------------------------------------------------------- diff --git a/src/network_inspectors/binder/binder.h b/src/network_inspectors/binder/binder.h index 020f060f7..5db8d4318 100644 --- a/src/network_inspectors/binder/binder.h +++ b/src/network_inspectors/binder/binder.h @@ -34,9 +34,9 @@ enum BindRole enum BindAction { - BA_INSPECT, + BA_BLOCK = 1, BA_ALLOW, - BA_BLOCK + BA_INSPECT }; enum BindProto diff --git a/src/network_inspectors/port_scan/port_scan.cc b/src/network_inspectors/port_scan/port_scan.cc index 82638e41e..fd118ea7e 100644 --- a/src/network_inspectors/port_scan/port_scan.cc +++ b/src/network_inspectors/port_scan/port_scan.cc @@ -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); diff --git a/src/search_engines/acsmx2.cc b/src/search_engines/acsmx2.cc index 701175d33..3884d15b7 100644 --- a/src/search_engines/acsmx2.cc +++ b/src/search_engines/acsmx2.cc @@ -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; diff --git a/src/service_inspectors/wizard/hexes.cc b/src/service_inspectors/wizard/hexes.cc index 3270812c6..bfd949148 100644 --- a/src/service_inspectors/wizard/hexes.cc +++ b/src/service_inspectors/wizard/hexes.cc @@ -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; } diff --git a/src/service_inspectors/wizard/magic.h b/src/service_inspectors/wizard/magic.h index f18a4a08c..02ac9f1ec 100644 --- a/src/service_inspectors/wizard/magic.h +++ b/src/service_inspectors/wizard/magic.h @@ -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; }; diff --git a/src/service_inspectors/wizard/spells.cc b/src/service_inspectors/wizard/spells.cc index a73581415..fecbb469f 100644 --- a/src/service_inspectors/wizard/spells.cc +++ b/src/service_inspectors/wizard/spells.cc @@ -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; } diff --git a/src/service_inspectors/wizard/wiz_module.cc b/src/service_inspectors/wizard/wiz_module.cc index b291f2925..81b824193 100644 --- a/src/service_inspectors/wizard/wiz_module.cc +++ b/src/service_inspectors/wizard/wiz_module.cc @@ -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; } diff --git a/src/service_inspectors/wizard/wiz_module.h b/src/service_inspectors/wizard/wiz_module.h index ee0bf296a..c559401ab 100644 --- a/src/service_inspectors/wizard/wiz_module.h +++ b/src/service_inspectors/wizard/wiz_module.h @@ -22,6 +22,7 @@ #ifndef WIZ_MODULE_H #define WIZ_MODULE_H +#include #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 spells; MagicBook* c2s_hexes; MagicBook* s2c_hexes; diff --git a/src/service_inspectors/wizard/wizard.cc b/src/service_inspectors/wizard/wizard.cc index c93249671..f8e589736 100644 --- a/src/service_inspectors/wizard/wizard.cc +++ b/src/service_inspectors/wizard/wizard.cc @@ -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; } diff --git a/src/stream/ip/ip_session.cc b/src/stream/ip/ip_session.cc index 8076ba70d..e5186d53e 100644 --- a/src/stream/ip/ip_session.cc +++ b/src/stream/ip/ip_session.cc @@ -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) { diff --git a/src/stream/stream_api.cc b/src/stream/stream_api.cc index 060aee815..e76b1dcf1 100644 --- a/src/stream/stream_api.cc +++ b/src/stream/stream_api.cc @@ -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)) diff --git a/src/stream/tcp/tcp_session.cc b/src/stream/tcp/tcp_session.cc index 4d70745ac..5516d9f01 100644 --- a/src/stream/tcp/tcp_session.cc +++ b/src/stream/tcp/tcp_session.cc @@ -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; diff --git a/src/stream/udp/udp_session.cc b/src/stream/udp/udp_session.cc index aa3cd0b69..bded49681 100644 --- a/src/stream/udp/udp_session.cc +++ b/src/stream/udp/udp_session.cc @@ -83,6 +83,7 @@ static void UdpSessionCleanup(Flow *lwssn) CloseStreamSession(&sfBase, SESSION_CLOSED_NORMALLY); } + lwssn->flow_state = 0; lwssn->clear(); udpStats.released++; diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index c1c78e046..4e270488c 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,4 +1,4 @@ add_subdirectory(u2boat) add_subdirectory(u2spewfoo) -add_subdirectory(snort2lua) +#add_subdirectory(snort2lua)