Index: snort/ChangeLog.snort-wireless diff -u /dev/null snort/ChangeLog.snort-wireless:1.6 --- /dev/null Sat Nov 5 19:10:38 2005 +++ snort/ChangeLog.snort-wireless Fri Oct 21 02:50:22 2005 @@ -0,0 +1,127 @@ +2005-10-20 Andrew Lockhart + + * Updated code to Snort 2.4.3 + +2005-10-07 Andrew Lockhart + + * Updated code to Snort 2.4.2 + +2005-06-25 Andrew Lockhart + + * src/snort.c (SnortMain): + - Added function call to setup wifi_statetable + +2005-06-24 Andrew Lockhart + + * src/preprocessors/Makefile.am: + - Added entries for preprocessors merged from + WIRELESS_SGRACIA branch + + * src/preprocessors/spp_deauth_flood.c: + * src/preprocessors/spp_deauth_flood.h: + - Merged deauth_flood preprocessor from WIRELESS_SGRACIA + + * src/preprocessors/spp_auth_flood.c: + * src/preprocessors/spp_auth_flood.h: + - Merged auth_flood preprocessor from WIRELESS_SGRACIA + + * src/preprocessors/spp_macspoof.c: + * src/preprocessors/spp_macspoof.h: + - Merged macspoof preprocessor from WIRELESS_SGRACIA + + * src/Makefile.am: + - Added entries for wifi_statetable.c & wifi_statetable.h + + * src/wifi_statetable.c: + * src/wifi_statetable.h: + - Merged wifi_statetable code from WIRELESS_SGRACIA + + * src/debug.h: + - Added defines for deauth_flood, auth_flood, and macspoof + preprocessors + + * src/decode.h: + - Added WSTIdx structure for wifi_statetable + + * src/generators.h: + - Added in generator IDs for deauth_flood, auth_flood, and macspoof + preprocessors + - Added in message strings for preprocessors mentioned above + + * src/plugbase.c: + - Added in includes for deauth_flood, auth_flood, and macspoof + preprocessors + + * src/plugbase.c (InitPreprocessors): + - Added function calls to setup deauth_flood, auth_flood, and macspoof + preprocessors + + * src/preprocessors/spp_antistumbler.c (AntiStumblerDetect): + - Removed hack to get alerts to display in ACID -- it created a blank IP header + + * src/preprocessors/spp_rogue_ap.c (RogueApDetect): + - Removed hack to get alerts to display in ACID -- it created a blank IP header + +2005-04-24 Andrew Lockhart + + * src/decode.c (DecodeWifiHdr): + - Changed references to p->pkt to pkt so that the contents of + 802.11 frames with Prism headers are decoded correctly. + +2003-08-25 Andrew Lockhart + + * rules/wifi.rules: + - Changed example addr4 plugin rule to work with fixed plugin. + + * src/detection-plugins/sp_wifi_addr4.c (WifiAddr4ParseMAC): + - Fixed MAC address parsing to cope with snort's option parsing + (was XX:XX:XX:XX:XX:XX, now 0xXXXXXXXXXXXX) + +2003-08-24 Andrew Lockhart + + * rules/wifi.rules: + - Changed example bssid plugin rule to work with fixed plugin. + + * src/detection-plugins/sp_wifi_bssid.c (WifiBssidParseBSSID): + - Fixed MAC address parsing to cope with snort's option parsing + (was XX:XX:XX:XX:XX:XX, now 0xXXXXXXXXXXXX) + +2003-08-23 Andrew Lockhart + + * src/log.c (Print2ndHeader): + - Added case for DLT_PRISM_HEADER. + +2003-08-21 Andrew Lockhart + + * src/decode.c: + - Added DecodePrismHdr() + - Moved bulk of DecodeIEEE80211Pkt() to + DecodeWifiHdr() to prevent duplicate code + + * src/decode.h: + - Added PrismHdr structure + - Added prism_val structure + + * src/snort.c (SetPktProcessor): + - Added case for DLT_PRISM_HEADER + +2003-08-14 Andrew Lockhart + + * rules/wifi.rules: + - Fixed typo in STYPE_ACK sample rule. + + * src/detection-plugins/sp_wifi_stype.c: + - Fixed typo in disassociation subtype string. + - Fixed typo in power-save poll subtype string. + - Removed redundant error check in WifiStypeRuleParseFunction() + that caused an off-by-one error. + + +2003-07-27 Andrew Lockhart + * Added ssid plugin + +2003-07-25 Andrew Lockhart + + * Added seqnum plugin + * Added fragnum plugin + * Added addr4 plugin Index: snort/Makefile.am diff -u snort/Makefile.am:1.1.1.9 snort/Makefile.am:1.1.1.9.4.1 --- snort/Makefile.am:1.1.1.9 Sat Oct 1 16:16:12 2005 +++ snort/Makefile.am Sat Nov 5 14:56:28 2005 @@ -1,6 +1,6 @@ ## $Id: Makefile.am,v 1.70.4.1.2.2 2005/07/21 04:24:43 roesch Exp $ AUTOMAKE_OPTIONS=foreign no-dependencies -SUBDIRS = src doc etc templates contrib schemas rpm m4 +SUBDIRS = src doc etc rules templates contrib schemas rpm m4 INCLUDES = @INCLUDES@ Index: snort/configure.in diff -u snort/configure.in:1.1.1.20 snort/configure.in:1.22.2.2 --- snort/configure.in:1.1.1.20 Thu Oct 20 10:13:53 2005 +++ snort/configure.in Sat Nov 5 14:56:28 2005 @@ -4,7 +4,7 @@ AM_CONFIG_HEADER(config.h) # When changing the snort version, please also update the VERSION # definition in "src/win32/WIN32-Includes/config.h" -AM_INIT_AUTOMAKE(snort,2.4.3) +AM_INIT_AUTOMAKE(snort-wireless,2.4.3-alpha04) # Since we get -O2 from configure defaults, which doesn't work in 64bit # mode, let's make some changes here before calling _CC macros. @@ -898,6 +898,7 @@ rpm/Makefile \ m4/Makefile \ etc/Makefile \ +rules/Makefile \ templates/Makefile \ src/win32/Makefile) Index: snort/doc/Makefile.am diff -u snort/doc/Makefile.am:1.1.1.11 snort/doc/Makefile.am:1.11 --- snort/doc/Makefile.am:1.1.1.11 Sat Oct 1 16:16:13 2005 +++ snort/doc/Makefile.am Sat Oct 1 20:06:35 2005 @@ -22,7 +22,8 @@ README.sfportscan \ README.frag3 \ snort_schema_v106.pdf \ -README.wireless PROBLEMS RULES.todo WISHLIST faq.pdf faq.tex +README.wireless PROBLEMS RULES.todo WISHLIST faq.pdf faq.tex \ +README.snort-wireless DISTCLEANFILES= snort_manual.log snort_manual.toc snort_manual.aux faq.log faq.toc faq.aux snort_manual.pdf faq.pdf snort_manual.out Index: snort/doc/README.snort-wireless diff -u /dev/null snort/doc/README.snort-wireless:1.1 --- /dev/null Sat Nov 5 19:10:39 2005 +++ snort/doc/README.snort-wireless Thu Mar 10 17:34:35 2005 @@ -0,0 +1,74 @@ +Snort-Wireless +============== + +Copyright (c) 2003 Andrew Lockhart + +Any feedback, bug reports, feature requests, etc. are welcome at +andrew@snort-wireless.org. If you'd like to help in any way, feel free to +contact me. I'll try to respond ASAP. + +"wifi" Protocol Rules +===================== +Snort at present does not contain direct support for rule based detection of +anything below the IP layer. It is possible in Snort 2.0.x to match byte +patterns in a packet, but it is not very straightforward and is very +time-consuming to write detection rules this way. + +Rules for detecting particular 802.11 frames are specified +using the following syntax: + + wifi -> () + +The 802.11 plugins are in src/detection-plugins and their filenames begin +with sp_wifi_. Each plugin should have documentation for it in the comments +at the top of its source file. Additionally, rules/wifi.rules contains example +rules for every plugin contained in the distribution. + +-Bugs- +* Only the alert and log actions have been tested +* Only the first matching rule triggers an alert +* Alerts logged to a database do not show up in ACID - this is because they + lack in IP header + +RogueAP Preprocessor +The RogueAP preprocessor detects both rogue APs and AdHoc networks. To +configure it, you'll need to first specify your APs BSSIDs and channels that +they operate on in your snort.conf file using the ACCESS_POINTS and CHANNELS +variables. + +# Single AP +var ACCESS_POINTS XX:XX:XX:XX:XX:XX +# Multiple APs +var ACCESS_POINTS [XX:XX:XX:XX:XX:XX, YY:YY:YY:YY:YY:YY, ....] +# Single channel +var CHANNELS X +# Multiple channels +var CHANNELS [X, Y, ...] + +The preprocessor is activated by specifying the following in your snort.conf: + +preprocessor rogue_ap: $ACCESS_POINTS, $CHANNELS, scan_flag [0 | 1], \ + scan_timeout [num], expire_timeout [num] + + +* scan_flag - toggles scanning of multiple channels *NOT IMPLEMENTED* +* scan_timeout - time in seconds between channel scans *NOT IMPLEMENTED* +* expire_timeout - time in seconds before a BSSID is removed from the rogue + list + +AntiStumbler Preprocessor + +The AntiStumbler preprocessor attempts to detect Netstumbler like traffic. It +does this by keeping track of probe request frames sent with NULL SSID fields. +The preprocessor is activated by specifying the following in your snort.conf: + +preprocessor antistumbler: probe_reqs [num], probe_period [num], \ + expire_timeout [num] + + +* probe_reqs - number of probe requests that triggers an alert +* probe_period - time period in seconds that NULL SSID probe request count is + maintained +* expire_timeout - time in seconds before a STA is removed from the stumbler + list + Index: snort/doc/README.wifi_statetable diff -u /dev/null snort/doc/README.wifi_statetable:1.2 --- /dev/null Sat Nov 5 19:10:39 2005 +++ snort/doc/README.wifi_statetable Thu Oct 20 09:09:28 2005 @@ -0,0 +1,93 @@ +Enabled with --enable-wireless configure option. + +Snort-Wifi_StateTable +===================== + +Copyright (c) 2004 Sebastien Gracia + +Any feedback, bug reports, feature requests, etc. are welcome at +sgracia@wanadoo.fr. If you'd like to help in any way, feel free to +contact me. I'll try to respond ASAP. + +I would like to thank Michel Weinachter and Olivier Grumelard. + +This patch is a snort-2.1.1 patch and includes Andrew Lockhart works +(). + +"wifi_statetable" +================= +Basically, Wifi_StateTable (WST) should be considered as a stateful table used +by dedicated wireless preprocessors which purpose is to detect some wireless +specific attack. +The index of this table will be "MAC address hash" based. +Anytime a packet would filled some WST preprocessors alert criterions (depending +on preprocessor arguments inside snort.conf), some data will be inserted or +updated inside WST. +Whenever alert_threshold are reached, corresponding alert will be sended. +At the moment, two preprocessors use WST: + - deauthflood, + - authflood. + +DeauthFlood +--------------------------------------------- +DeauthFlood detects wireless station flooded with deauth frames. + +Arguments: + +deauth_threshold [num] => number of deauth frames during time delta it takes + to trigger an alert +expire_timeout [num] => time period used to keep count of deauth frames +target_limit [num] => maximum number of station inserted inside deauthstation + mempool +prune_period [num] => number of seconds to wait for removing some decayed + deauthstations from mempool + +AuthFlood +--------------------------------------------- +AuthFlood detects wireless access point flooded with auth frames. + +Arguments: + +auth_threshold [num] => number of auth frames during time delta it takes + to trigger an alert +expire_timeout [num] => time period used to keep count of auth frames +target_limit [num] => maximum number of access point inserted inside authAP mempool +prune_period [num] => number of seconds to wait for removing some decayed + flooded AP from mempool + +MacSpoof +--------------------------------------------- +MacSpoof detects wireless MAC addresses involved in some MAC spoofed traffic. + +Arguments: + +MACSPOOF_MASKED_ADDR => list of MAC addresses excluded from wireless MAC spoofing + [var] detection process +tolerate_gap [num] => tolerate missing frames between two consecutives frames issued + from same MAC address +threshold [num] => number of abnormal sequence number gaps during time delta to + trigger an alert +expire_timeout [num} => time period used to keep count of abnormal seq number gap +spoofed_target_limit => maximum number of MAC addresses inserted inside MAC spoofed + [num] addresses mempool +prune_period [num] => number of seconds to wait for looking after some decayed + MAC addresses inside mempool + +*Because of some particuliar firmware or some electro_magnetic conditions, this + preprocessors won't fit to all wireless features inside network. + Those would generate too much false positive alert. + Therefore, I suggest macspoof preprocessos users to run snort a first time + in order to identify those particuliar features and thereafter to insert + them inside MaskedMACaddrlist. + +*Whenever an alert si raised, it doesn't mean anytime that concerned MAC address + is spoofed. Furthermore, It means that this MAC adress is involved in some MAC + spoofed traffic (either MAC spoofed or MAC spoofing address). + +*whenever "end abnormal sequence number gap" is logged, it doesn't exactly mean that + MAC spoofing ended. For example, it would occured if a spoofer succeed to divert + a user from network while keeping using his MAC address. In such a case, neither + abnormal sequence number gap would be detected nor alert would be sended + while MAC spoofing still occur. + + Index: snort/etc/snort.conf diff -u snort/etc/snort.conf:1.1.1.12 snort/etc/snort.conf:1.14 --- snort/etc/snort.conf:1.1.1.12 Thu Oct 20 10:13:58 2005 +++ snort/etc/snort.conf Thu Oct 20 10:20:37 2005 @@ -47,6 +47,36 @@ # Set up the external network addresses as well. A good start may be "any" var EXTERNAL_NET any +# Configure your wireless AP lists. This allows snort to look for attacks +# against your wireless network, such as rogue access points or adhoc wireless +# networks. Also specify what channels your access points are setup on. +# +# Ex: +# +# var ACCESS_POINTS XX:XX:XX:XX:XX:XX +# var CHANNELS X +# OR +# +# var ACCESS_POINTS [XX:XX:XX:XX:XX:XX, YY:YY:YY:YY:YY:YY, ....] +# var CHANNELS [X, Y, ....] + +var ACCESS_POINTS FF:FF:FF:FF:FF:FF +var CHANNELS 11 + +# Configure masked MAC addresses. This disabled any MAC spoofing wireless +# detection for concerned MAC addresses in order to avoid too much false positive +# alert. +# +# Ex: +# +# var MACSPOOF_MASKED_ADDR none +# OR +# var MACSPOOF_MASKED_ADDR XX:XX:XX:XX:XX:XX +# OR +# var MACSPOOF_MASKED_ADDR [XX:XX:XX:XX:XX:XX,YY:YY:YY:YY:YY:YY,....] + +var MACSPOOF_MASKED_ADDR none + # Configure your server lists. This allows snort to only look for attacks to # systems that have a service up. Why look for HTTP attacks if you are not # running a web server? This allows quick filtering based on IP addresses @@ -546,6 +576,85 @@ preprocessor xlink2state: ports { 25 691 } +# RogueAP +#--------------------------------------------- +# RogueAP detects rogue APs and AdHoc networks +# +# Arguments: +# +# scan_flag [0 | 1] => toggles scanning of multiple channels *NOT IMPLEMENTED* +# scan_timeout [num] => time in seconds between channel scans *NOT IMPLEMENTED* +# expire_timeout [num] => time in seconds before a BSSID is removed from the rogue list +# + +#preprocessor rogue_ap: $ACCESS_POINTS, $CHANNELS, scan_flag 1, scan_timeout 1800, expire_timeout 3600 + +# AntiStumbler +#--------------------------------------------- +# AntiStumbler detects possible Netstumbler activity +# +# Arguments: +# +# probe_reqs [num] => number of probe requests that triggers an alert +# probe_period [num] => time period in seconds that NULL SSID probe requests are counted +# expire_timeout [num] => time in seconds before a STA is removed from the stumbler list +# + +#preprocessor antistumbler: probe_reqs 90, probe_period 30, expire_timeout 3600 + +# DeauthFlood +#--------------------------------------------- +# DeauthFlood detects wireless station flooded with deauth frames. +# +# Arguments: +# +# deauth_threshold [num] => number of deauth frames during time delta it takes +# to trigger an alert +# expire_timeout [num] => time period used to keep count of deauth frames +# target_limit [num] => maximum number of station inserted inside deauthstation +# mempool +# prune_period [num] => number of seconds to wait for removing some decayed +# deauthstations from mempool +# + +#preprocessor deauth_flood: deauth_threshold 20, expire_timeout 60, target_limit 100, prune_period 30 + +# AuthFlood +#--------------------------------------------- +# AuthFlood detects wireless access point flooded with auth frames. +# +# Arguments: +# +# auth_threshold [num] => number of auth frames during time delta it takes +# to trigger an alert +# expire_timeout [num] => time period used to keep count of auth frames +# target_limit [num] => maximum number of access point inserted inside authAP mempool +# prune_period [num] => number of seconds to wait for removing some decayed +# flooded AP from mempool +# + +#preprocessor auth_flood: auth_threshold 100, expire_timeout 60, target_limit 10, prune_period 30 + +# MacSpoof +#--------------------------------------------- +# MacSpoof detects wireless MAC addresses involved in some MAC spoofed traffic. +# +# Arguments: +# +# MACSPOOF_MASKED_ADDR => list of MAC addresses excluded from wireless MAC spoofing +# [var detection process +# tolerate_gap [num] => tolerate missing frames between two consecutives frames issued +# from same MAC address +# threshold [num] => number of abnormal sequence number gaps during time delta to +# trigger an alert +# expire_timeout [num} => time period used to keep count of abnormal seq number gap +# spoofed_target_limit => maximum number of MAC addresses inserted inside MAC spoofed +# [num] addresses mempool +# prune_period [num] => number of seconds to wait for looking after some decayed +# MAC addresses inside mempool + +#preprocessor macspoof: $MACSPOOF_MASKED_ADDR, tolerate_gap 5, threshold 10, expire_timeout 120, spoofed_addr_limit 100, prune_period 30 + #################################################################### # Step #3: Configure output plugins # @@ -752,6 +861,7 @@ # include $RULE_PATH/multimedia.rules # include $RULE_PATH/p2p.rules include $RULE_PATH/experimental.rules +#include $RULE_PATH/wifi.rules # Include any thresholding or suppression commands. See threshold.conf in the # /etc directory for details. Commands don't necessarily need to be Index: snort/rules/Makefile.am diff -u /dev/null snort/rules/Makefile.am:1.5.2.1 --- /dev/null Sat Nov 5 19:10:42 2005 +++ snort/rules/Makefile.am Sat Nov 5 14:56:28 2005 @@ -0,0 +1,4 @@ +## $Id: Makefile.am,v 1.6 2003/10/20 15:03:04 chrisgreen Exp $ +AUTOMAKE_OPTIONS=foreign no-dependencies + +EXTRA_DIST = wifi.rules Index: snort/rules/wifi.rules diff -u /dev/null snort/rules/wifi.rules:1.7 --- /dev/null Sat Nov 5 19:10:42 2005 +++ snort/rules/wifi.rules Fri Mar 11 10:54:28 2005 @@ -0,0 +1,74 @@ +# these are just for testing right now + +# *NOTE* MAC addresses can be substituted for "any" + + +# Frame types +# ! may proceed any type argument to perform a logical NOT operation + +alert wifi any -> any (msg:"Mangement Frame"; type:TYPE_MANAGEMENT;) +alert wifi any -> any (msg:"Control Frame"; type:TYPE_CONTROL;) +alert wifi any -> any (msg:"Data Frame"; type:TYPE_DATA;) + + +# Frame subtypes (These implicitly check the frame's type) +# ! may proceed any stype argument to perform a logical NOT operation + +#alert wifi any -> any (msg:"Association Request"; stype:STYPE_ASSOCREQ;) +#alert wifi any -> any (msg:"Association Response"; stype:STYPE_ASSOCRESP;) +#alert wifi any -> any (msg:"Reassociation Request"; stype:STYPE_REASSOC_REQ;) +#alert wifi any -> any (msg:"Reassociation Response"; stype:STYPE_REASSOC_RESP;) +#alert wifi any -> any (msg:"Probe Request"; stype:STYPE_PROBEREQ;) +#alert wifi any -> any (msg:"Probe Response"; stype:STYPE_PROBERESP;) +#alert wifi any -> any (msg:"Beacon"; stype:STYPE_BEACON;) +#alert wifi any -> any (msg:"ATIM"; stype:STYPE_ATIM;) +#alert wifi any -> any (msg:"Disassociation"; stype:STYPE_DISASSOC;) +#alert wifi any -> any (msg:"Authentication"; stype:STYPE_AUTH;) +#alert wifi any -> any (msg:"Deauthentication"; stype:STYPE_DEAUTH;) + +#alert wifi any -> any (msg:"Power-Save Poll"; stype:STYPE_PSPOLL;) +#alert wifi any -> any (msg:"RTS"; stype:STYPE_RTS;) +#alert wifi any -> any (msg:"CTS"; stype:STYPE_CTS;) +#alert wifi any -> any (msg:"Ack"; stype:STYPE_ACK;) +#alert wifi any -> any (msg:"CF-End"; stype:STYPE_CFEND;) +#alert wifi any -> any (msg:"CF-End+CF-Ack"; stype:STYPE_CFEND_CFACK;) + +#alert wifi any -> any (msg:"Data"; stype:STYPE_DATA;) +#alert wifi any -> any (msg:"CF-Ack"; stype:STYPE_CFACK;) +#alert wifi any -> any (msg:"CF-Poll"; stype:STYPE_CFPOLL;) +#alert wifi any -> any (msg:"CF-Ack+CF-Poll"; stype:STYPE_CFACK_CFPOLL;) +#alert wifi any -> any (msg:"NULL Function"; stype:STYPE_NULLFUNC;) +#alert wifi any -> any (msg:"CF-Ack+NULL Function"; stype:STYPE_CFACK_NULLFUNC;) +#alert wifi any -> any (msg:"CF-Poll+NULL Function"; stype:STYPE_CFPOLL_NULLFUNC;) +#alert wifi any -> any (msg:"CF-Ack+CF-Poll-NULL Function"; stype:STYPE_CFACK_CFPOLL_NULLFUNC;) + +# Check for a match of the entire frame control field against a hex or decimal value +# ! may proceed the argument to perform a logical NOT operation +#alert wifi any -> any (msg:"WEP encrypted Data frame with from_ds set"; frame_control:0x4208;) +#alert wifi any -> any (msg:"WEP encrypted Data frame with from_ds set"; frame_control:16904;) + + +# Frame control flags +# ON, OFF, TRUE, or FALSE may be used. '!' may proceed any of these. + +#alert wifi any -> any (msg:"from_ds flag set"; from_ds:TRUE;) +#alert wifi any -> any (msg:"to_ds flag set"; to_ds:ON;) +#alert wifi any -> any (msg:"more_frags flag set"; more_frags:!FALSE;) +#alert wifi any -> any (msg:"retry flag set"; retry:!OFF;) +#alert wifi any -> any (msg:"pwr_mgmt flag not set"; pwr_mgmt:FALSE;) +#alert wifi any -> any (msg:"more_data flag not set"; more_data:OFF;) +#alert wifi any -> any (msg:"wep flag set"; wep:TRUE;) +#alert wifi any -> any (msg:"order flag set"; order:TRUE;) + + +# These plugins will detect on frames that contain the respective field +# '!' may proceed any of these plugin arguments to perform a logical NOT operation + +#alert wifi any -> any (msg:"Duration/ID is 0xFF"; duration_id:0xFF;) +#alert wifi any -> any (msg:"BSSID is not 00\:DE\:AD\:C0\:DE\:00"; bssid:!0x00DEADC0DE00;) +#alert wifi any -> any (msg:"Sequence Number is 2345"; seq_num:2345;) +#alert wifi any -> any (msg:"Sequence Number is 0xFF"; seq_num:0x00FF;) +#alert wifi any -> any (msg:"Fragment Number is 12"; frag_num:12;) +#alert wifi any -> any (msg:"Fragment Number is 15"; frag_num:0xF;) +#alert wifi any -> any (msg:"Address 4 Field is D1\:ED\:1E\:D1\:ED\:1E"; addr4:0xD1ED1ED1ED1E;) +#alert wifi any -> any (msg:"SSID is linksys"; ssid:linksys;) Index: snort/src/Makefile.am diff -u snort/src/Makefile.am:1.1.1.9 snort/src/Makefile.am:1.2 --- snort/src/Makefile.am:1.1.1.9 Sun Apr 24 22:11:05 2005 +++ snort/src/Makefile.am Fri Jun 24 18:31:28 2005 @@ -45,7 +45,8 @@ smalloc.h \ snort_packet_header.h \ event_queue.c event_queue.h \ -inline.c inline.h +inline.c inline.h \ +wifi_statetable.c wifi_statetable.h snort_LDADD = output-plugins/libspo.a \ detection-plugins/libspd.a \ Index: snort/src/debug.h diff -u snort/src/debug.h:1.1.1.4 snort/src/debug.h:1.3 --- snort/src/debug.h:1.1.1.4 Sat Oct 1 16:16:14 2005 +++ snort/src/debug.h Sat Oct 1 20:07:05 2005 @@ -49,6 +49,10 @@ #define DEBUG_HTTPINSPECT 0x00400000 /* 4194304 */ #define DEBUG_STREAM_STATE 0x00800000 /* 8388608 */ #define DEBUG_ASN1 0x01000000 /* 16777216 */ +#define DEBUG_WIFI_STATETABLE 0x00800000 /* 8388608 */ +#define DEBUG_DEAUTHFLOOD 0x01000000 /* 16777216 */ +#define DEBUG_AUTHFLOOD 0x02000000 /* 23554432 */ +#define DEBUG_MACSPOOF 0x04000000 /* 67108864 */ #ifdef DEBUG Index: snort/src/decode.c diff -u snort/src/decode.c:1.1.1.10 snort/src/decode.c:1.14 --- snort/src/decode.c:1.1.1.10 Sat Oct 1 20:23:20 2005 +++ snort/src/decode.c Sat Oct 1 20:46:48 2005 @@ -154,10 +154,9 @@ /* - * Function: DecodeIEEE80211Pkt(Packet *, char *, struct pcap_pkthdr*, - * u_int8_t*) + * Function: DecodeWifiHdr(Packet *, char *, struct pcap_pkthdr *, u_int8_t *) * - * Purpose: Decode those fun loving wireless LAN packets, one at a time! + * Purpose: Decodes unencapsulated portion of 802.11 frame headers * * Arguments: p => pointer to the decoded packet struct * user => Utility pointer (unused) @@ -166,40 +165,34 @@ * * Returns: void function */ -void DecodeIEEE80211Pkt(Packet * p, struct pcap_pkthdr * pkthdr, - u_int8_t * pkt) -{ +void DecodeWifiHdr(Packet *p, struct pcap_pkthdr * pkthdr, u_int8_t *pkt){ + u_int32_t pkt_len; /* suprisingly, the length of the packet */ u_int32_t cap_len; /* caplen value */ - - bzero((char *) p, sizeof(Packet)); - - p->pkth = pkthdr; - p->pkt = pkt; - + /* set the lengths we need */ pkt_len = pkthdr->len; /* total packet length */ cap_len = pkthdr->caplen; /* captured packet length */ + + if(snaplen < pkthdr->len) + pkt_len = cap_len; - if(snaplen < pkt_len) - pkt_len = cap_len; - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Packet!\n");); - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "caplen: %lu pktlen: %lu\n", - (unsigned long)cap_len, (unsigned long)pkt_len);); - - /* do a little validation */ - if(p->pkth->caplen < MINIMAL_IEEE80211_HEADER_LEN) - { - if(pv.verbose_flag) - { - ErrorMessage("Captured data length < IEEE 802.11 header length! (%d bytes)\n", p->pkth->caplen); - } - return; - } /* lay the wireless structure over the packet data */ p->wifih = (WifiHdr *) pkt; + +#if BYTE_ORDER == BIG_ENDIAN + /* Swap bytes of duration_id on big endian archs */ + p->wifih->duration_id = (p->wifih->duration_id << 8) | + (p->wifih->duration_id >> 8); + + /* I'm not sure if this is peculiar to OS X or is required on all + big endian archs, since this involves a rotate rather than a byte swap */ + + p->wifih->seq_control = (p->wifih->seq_control << 4) | + (p->wifih->seq_control >> 12); +#endif + DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "%X %X\n", *p->wifih->addr1, *p->wifih->addr2);); @@ -317,7 +310,7 @@ switch(ntohs(p->ehllcother->proto_id)) { case ETHERNET_TYPE_IP: - DecodeIP(p->pkt + IEEE802_11_DATA_HDR_LEN + sizeof(EthLlc) + + DecodeIP(pkt + IEEE802_11_DATA_HDR_LEN + sizeof(EthLlc) + sizeof(EthLlcOther), pkt_len - IEEE802_11_DATA_HDR_LEN - sizeof(EthLlc) - sizeof(EthLlcOther), p); @@ -325,19 +318,19 @@ case ETHERNET_TYPE_ARP: case ETHERNET_TYPE_REVARP: - DecodeARP(p->pkt + IEEE802_11_DATA_HDR_LEN + sizeof(EthLlc) + + DecodeARP(pkt + IEEE802_11_DATA_HDR_LEN + sizeof(EthLlc) + sizeof(EthLlcOther), pkt_len - IEEE802_11_DATA_HDR_LEN - sizeof(EthLlc) - sizeof(EthLlcOther), p); return; case ETHERNET_TYPE_EAPOL: - DecodeEapol(p->pkt + IEEE802_11_DATA_HDR_LEN + sizeof(EthLlc) + + DecodeEapol(pkt + IEEE802_11_DATA_HDR_LEN + sizeof(EthLlc) + sizeof(EthLlcOther), pkt_len - IEEE802_11_DATA_HDR_LEN - sizeof(EthLlc) - sizeof(EthLlcOther), p); return; case ETHERNET_TYPE_8021Q: - DecodeVlan(p->pkt + IEEE802_11_DATA_HDR_LEN , + DecodeVlan(pkt + IEEE802_11_DATA_HDR_LEN , cap_len - IEEE802_11_DATA_HDR_LEN , p); return; @@ -356,6 +349,116 @@ } + + +/* + * Function: DecodeIEEE80211Pkt(Packet *, char *, struct pcap_pkthdr*, + * u_int8_t*) + * + * Purpose: Decode those fun loving (unencapsulated) wireless LAN packets, one at a time! + * + * Arguments: p => pointer to the decoded packet struct + * user => Utility pointer (unused) + * pkthdr => ptr to the packet header + * pkt => pointer to the real live packet data + * + * Returns: void function + */ + +void DecodeIEEE80211Pkt(Packet * p, struct pcap_pkthdr * pkthdr, + u_int8_t * pkt) +{ + u_int32_t pkt_len; /* suprisingly, the length of the packet */ + u_int32_t cap_len; /* caplen value */ + + bzero((char *) p, sizeof(Packet)); + + p->pkth = pkthdr; + p->pkt = pkt; + + /* set the lengths we need */ + pkt_len = pkthdr->len; /* total packet length */ + cap_len = pkthdr->caplen; /* captured packet length */ + + if(snaplen < pkt_len) + pkt_len = cap_len; + + DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Packet!\n");); + DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "caplen: %lu pktlen: %lu\n", + (unsigned long)cap_len, (unsigned long)pkt_len);); + + /* do a little validation */ + if(p->pkth->caplen < MINIMAL_IEEE80211_HEADER_LEN) + { + if(pv.verbose_flag) + { + ErrorMessage("Captured data length < IEEE 802.11 header length! (%d bytes)\n", p->pkth->caplen); + } + return; + } + + /* decode the actual 802.11 frame */ + DecodeWifiHdr(p, pkthdr, pkt); +} + + + + + +/* + * Function: DecodePrismHdr(Packet *, char *, struct pcap_pkthdr *, u_int8_t *) + * + * Purpose: Decode PRISM header encapsulated 802.11 frames. + * + * Arguments: p => pointer to the decoded packet struct + * user => Utility pointer (unused) + * pkthdr => ptr to the packet header + * pkt => pointer to the real live packet data + * + * Returns: void function + */ + +void DecodePrismHdr(Packet *p, struct pcap_pkthdr *pkthdr, u_int8_t *pkt){ + + u_int32_t pkt_len; /* suprisingly, the length of the packet */ + u_int32_t cap_len; /* caplen value */ + + bzero((char *) p, sizeof(Packet)); + + p->pkth = pkthdr; + p->pkt = pkt; + + /* set the lengths we need */ + pkt_len = pkthdr->len; /* total packet length */ + cap_len = pkthdr->caplen; /* captured packet length */ + + + if(snaplen < pkt_len) + pkt_len = cap_len; + + DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Packet!\n");); + DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "caplen: %lu pktlen: %lu\n", + (unsigned long)cap_len, (unsigned long)pkt_len);); + + /* do a little validation */ + if(p->pkth->caplen < (sizeof(PrismHdr) + MINIMAL_IEEE80211_HEADER_LEN)) + { + if(pv.verbose_flag) + { + ErrorMessage("Captured data length < IEEE 802.11 header length! (%d bytes)\n", p->pkth->caplen); + } + return; + } + + /* lay the prism structure over the packet data */ + p->prismh = (PrismHdr *)pkt; + + /* decode the encapsulated 802.11 frame */ + DecodeWifiHdr(p, pkthdr, pkt + sizeof(PrismHdr)); +} + + + void DecodeVlan(u_int8_t * pkt, const u_int32_t len, Packet * p) { if(len < sizeof(VlanTagHdr)) Index: snort/src/decode.h diff -u snort/src/decode.h:1.1.1.10 snort/src/decode.h:1.14 --- snort/src/decode.h:1.1.1.10 Sat Oct 1 20:23:20 2005 +++ snort/src/decode.h Sat Oct 1 20:46:48 2005 @@ -808,15 +808,91 @@ */ typedef struct _WifiHdr { + union{ u_int16_t frame_control; + struct { + + /* Compensate for endianess/libpcap and maybe OSX/libpcap weirdness - + you'd think a straight byte swap would work */ + +#if BYTE_ORDER == LITTLE_ENDIAN + u_int16_t version:2; + u_int16_t type:2; + u_int16_t stype:4; +#else + u_int16_t stype:4; + u_int16_t type:2; + u_int16_t version:2; +#endif + u_int16_t to_ds:1; + u_int16_t from_ds:1; + u_int16_t more_frags:1; + u_int16_t retry:1; + u_int16_t pwr_mgmt:1; + u_int16_t more_data:1; + u_int16_t wep:1; + u_int16_t order:1; + }; + }; u_int16_t duration_id; u_int8_t addr1[6]; u_int8_t addr2[6]; u_int8_t addr3[6]; - u_int16_t seq_control; + + union { + u_int16_t seq_control; + struct { + u_int16_t fragnum:4; + u_int16_t seqnum:12; + }; + }; u_int8_t addr4[6]; } WifiHdr; +/* + * PRISM Header (Sometimes encapsulates IEEE 802.11 Headers) + * + * (Somewhat borrowed from Tim Newsham's PRISM decoder for ethereal) + */ + +typedef struct _prism_val { + u_int32_t did; + u_int16_t status; + u_int16_t len; + u_int32_t data; +} prism_val; + +typedef struct _PrismHdr { + + u_int32_t msg_code; + u_int32_t msg_len; + char dev_name[16]; + prism_val host_time; + prism_val mac_time; + prism_val channel; + prism_val rssi; + prism_val sq; + prism_val signal; + prism_val noise; + prism_val rate; + prism_val is_tx; + prism_val frame_len; + +} PrismHdr; + + +/* + * WifiStateTable Index + * + */ + +typedef struct _WSTIdx { + + // u_int8_t *cache_addr[2]; + int32_t cache_addr[2]; + +} WSTIdx; + /* Can't add any fields not in the real header here because of how the decoder uses structure overlaying */ @@ -1097,6 +1173,8 @@ EthLlcOther *ehllcother; WifiHdr *wifih; /* wireless LAN header */ + PrismHdr *prismh; /* PRISM header */ + WSTIdx wstidx; EtherARP *ah; @@ -1196,6 +1274,7 @@ void DecodeLinuxSLLPkt(Packet *, struct pcap_pkthdr *, u_int8_t *); void DecodeEthPkt(Packet *, struct pcap_pkthdr *, u_int8_t *); void DecodeIEEE80211Pkt(Packet *, struct pcap_pkthdr *, u_int8_t *); +void DecodePrismHdr(Packet *, struct pcap_pkthdr *, u_int8_t *); void DecodeVlan(u_int8_t *, const u_int32_t, Packet *); void DecodePppPkt(Packet *, struct pcap_pkthdr *, u_int8_t *); void DecodePppSerialPkt(Packet *, struct pcap_pkthdr *, u_int8_t *); Index: snort/src/detect.c diff -u snort/src/detect.c:1.1.1.9 snort/src/detect.c:1.10 --- snort/src/detect.c:1.1.1.9 Sat Oct 1 16:16:14 2005 +++ snort/src/detect.c Sat Oct 1 20:07:05 2005 @@ -449,7 +449,7 @@ rule = RuleLists; - if(p && p->iph == NULL) + if(p && p->iph == NULL && p->wifih == NULL) return 0; /* @@ -645,6 +645,7 @@ { RuleTreeNode *rtn_idx; IpAddrSet *idx; /* indexing pointer */ + MacAddrSet *idx2; int i; #ifdef DEBUG OptTreeNode *otn_idx; @@ -662,6 +663,60 @@ /* walk thru the RTN list */ while(rtn_idx != NULL) { + if(rtn_idx->is_wifi){ + DEBUG_WRAP( + DebugMessage(DEBUG_RULES, "Rule type: %d\n", rtn_idx->type); + DebugMessage(DEBUG_RULES, "SRC MAC List:\n"); + ); + + idx2 = rtn_idx->smac; + i = 0; + while(idx2 != NULL) + { + DEBUG_WRAP(DebugMessage(DEBUG_RULES, + "[%d] %.2X:%.2X:%.2X:%.2X:%.2X:%.2X ", i++, + idx2->mac_addr[0], idx2->mac_addr[1], idx2->mac_addr[2], + idx2->mac_addr[3], idx2->mac_addr[4], idx2->mac_addr[5])); + + if(idx2->addr_flags & EXCEPT_MAC) + { + DEBUG_WRAP(DebugMessage(DEBUG_RULES, + " (EXCEPTION_FLAG Active)\n");); + } + else + { + DEBUG_WRAP(DebugMessage(DEBUG_RULES, "\n");); + } + idx2 = idx2->next; + } + + DEBUG_WRAP(DebugMessage(DEBUG_RULES, "DST MAC List:\n");); + + idx2 = rtn_idx->dmac; + i = 0; + while(idx2 != NULL) + { + DEBUG_WRAP(DebugMessage(DEBUG_RULES, + "[%d] %.2X:%.2X:%.2X:%.2X:%.2X:%.2X ", i++, + idx2->mac_addr[0], idx2->mac_addr[1], idx2->mac_addr[2], + idx2->mac_addr[3], idx2->mac_addr[4], idx2->mac_addr[5])); + + if(idx2->addr_flags & EXCEPT_MAC) + { + DEBUG_WRAP(DebugMessage(DEBUG_RULES, + " (EXCEPTION_FLAG Active)\n");); + } + else + { + DEBUG_WRAP(DebugMessage(DEBUG_RULES, "\n");); + } + idx2 = idx2->next; + } + + + + } + else{ DEBUG_WRAP( DebugMessage(DEBUG_RULES, "Rule type: %d\n", rtn_idx->type); DebugMessage(DEBUG_RULES, "SRC IP List:\n"); @@ -671,7 +726,7 @@ while(idx != NULL) { DEBUG_WRAP(DebugMessage(DEBUG_RULES, - "[%d] 0x%.8lX / 0x%.8lX", + "[%d] 0x%.8lX / 0x%.8lX ", i++, (u_long) idx->ip_addr, (u_long) idx->netmask);); @@ -694,7 +749,7 @@ while(idx != NULL) { DEBUG_WRAP(DebugMessage(DEBUG_RULES, - "[%d] 0x%.8lX / 0x%.8lX", + "[%d] 0x%.8lX / 0x%.8lX ", i++,(u_long) idx->ip_addr, (u_long) idx->netmask);); if(idx->addr_flags & EXCEPT_IP) @@ -709,7 +764,25 @@ idx = idx->next; } + } #ifdef DEBUG + if(rtn_idx->is_wifi){ + DebugMessage(DEBUG_RULES, "FLags: "); + if(rtn_idx->flags & EXCEPT_SRC_MAC) + DebugMessage(DEBUG_RULES, "EXCEPT_SRC_MAC "); + if(rtn_idx->flags & EXCEPT_DST_MAC) + DebugMessage(DEBUG_RULES, "EXCEPT_DST_MAC "); + if(rtn_idx->flags & EXCEPT_BSSID_MAC) + DebugMessage(DEBUG_RULES, "EXCEPT_BSSID_MAC "); + if(rtn_idx->flags & ANY_SRC_MAC) + DebugMessage(DEBUG_RULES, "ANY_SRC_MAC "); + if(rtn_idx->flags & ANY_DST_MAC) + DebugMessage(DEBUG_RULES, "ANY_DST_MAC "); + if(rtn_idx->flags & ANY_BSSID_MAC) + DebugMessage(DEBUG_RULES, "ANY_BSSID_MAC "); + DebugMessage(DEBUG_RULES, "\n"); + } + else{ DebugMessage(DEBUG_RULES, "SRC PORT: %d - %d \n", rtn_idx->lsp, rtn_idx->hsp); DebugMessage(DEBUG_RULES, "DST PORT: %d - %d \n", rtn_idx->ldp, @@ -730,6 +803,7 @@ DebugMessage(DEBUG_RULES, "EXCEPT_DST_PORT "); DebugMessage(DEBUG_RULES, "\n"); + } otn_idx = rtn_idx->down; DEBUG_WRAP( @@ -901,6 +975,134 @@ +int CheckSrcMAC(Packet *p, struct _RuleTreeNode *rtn_idx, RuleFpList *fp_list){ + + MacAddrSet *idx; + + DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"CheckSrcMACEqual: ");); + +#warning "Make sure frames src and dest addresses correspond correctly" + + if(!(rtn_idx->flags & EXCEPT_SRC_MAC)){ + /* do the check */ + for(idx = rtn_idx->smac; idx != NULL; idx=idx->next) + { + +/* if( ((idx->ip_addr == (p->iph->ip_src.s_addr & idx->netmask)) */ +/* ^ (idx->addr_flags & EXCEPT_IP)) ) */ + if(!memcmp(idx->mac_addr, p->wifih->addr2, 6) ^ (idx->addr_flags & EXCEPT_MAC)) + { +#ifdef DEBUG + if(idx->addr_flags & EXCEPT_MAC) { + DebugMessage(DEBUG_DETECT, " SMAC exception match\n"); + } + else + { + DebugMessage(DEBUG_DETECT, " SMAC match\n"); + } + +/* DebugMessage(DEBUG_DETECT, "Rule: 0x%X Packet: 0x%X\n", */ +/* idx->ip_addr, (p->iph->ip_src.s_addr & idx->netmask)); */ +#endif /* DEBUG */ + + /* the packet matches this test, proceed to the next test */ + return fp_list->next->RuleHeadFunc(p, rtn_idx, fp_list->next); + } + } + } + else + { + /* global exception flag is up, we can't match on *any* + * of the source addresses + */ + DEBUG_WRAP(DebugMessage(DEBUG_DETECT," global exception flag, \n");); + + /* do the check */ + for(idx=rtn_idx->smac; idx != NULL; idx=idx->next) + { + if(!memcmp(idx->mac_addr, p->wifih->addr2, 6) ^ (idx->addr_flags & EXCEPT_MAC)) + { + DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"address matched, failing on SMAC\n");); + /* got address match on globally negated rule, fail */ + return 0; + } + } + DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"no matches on SMAC, passed\n");); + + return fp_list->next->RuleHeadFunc(p, rtn_idx, fp_list->next); + } + + DEBUG_WRAP(DebugMessage(DEBUG_DETECT," Mismatch on SMAC\n");); + + /* return 0 on a failed test */ + return 0; +} + +int CheckDstMAC(Packet *p, struct _RuleTreeNode *rtn_idx, RuleFpList *fp_list){ + MacAddrSet *idx; /* ip address indexer */ + + DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "CheckDstMACEqual: ");) + + /* check for global exception flag */ + if(!(rtn_idx->flags & EXCEPT_DST_MAC)) + { + /* do the check */ + for(idx=rtn_idx->dmac; idx != NULL; idx=idx->next) + { + /* if( ((idx->ip_addr == (p->iph->ip_dst.s_addr & idx->netmask)) */ +/* ^ (idx->addr_flags & EXCEPT_IP)) ) */ + if(!memcmp(idx->mac_addr, p->wifih->addr1, 6) ^ (idx->addr_flags & EXCEPT_MAC)) + { +#ifdef DEBUG + if(idx->addr_flags & EXCEPT_MAC) + { + DebugMessage(DEBUG_DETECT, " DMAC exception match\n"); + } + else + { + DebugMessage(DEBUG_DETECT, " DMAC match\n"); + } + +/* DebugMessage(DEBUG_DETECT, "Rule: 0x%X Packet: 0x%X\n", */ +/* idx->ip_addr, (p->iph->ip_src.s_addr & idx->netmask)); */ +#endif /* DEBUG */ + /* the packet matches this test, proceed to the next test */ + return fp_list->next->RuleHeadFunc(p, rtn_idx, fp_list->next); + } + } + } + else + { + /* global exception flag is up, we can't match on *any* + * of the source addresses + */ + DEBUG_WRAP(DebugMessage(DEBUG_DETECT, " global exception flag, \n");); + + /* do the check */ + for(idx=rtn_idx->dip; idx != NULL; idx=idx->next) + { +/* if( ((idx->ip_addr == (p->iph->ip_dst.s_addr & idx->netmask)) */ +/* ^ (idx->addr_flags & EXCEPT_IP)) ) */ + if(!memcmp(idx->mac_addr, p->wifih->addr1, 6) ^ (idx->addr_flags & EXCEPT_MAC)) + { + DEBUG_WRAP(DebugMessage(DEBUG_DETECT, + "address matched, failing on DMAC\n");); + /* got address match on globally negated rule, fail */ + return 0; + } + } + DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "no matches on DMAC, passed\n");); + + return fp_list->next->RuleHeadFunc(p, rtn_idx, fp_list->next); + } + + DEBUG_WRAP(DebugMessage(DEBUG_DETECT, " Mismatch on DMAC\n");); + /* return 0 on a failed test */ + return 0; +} + + + /**************************************************************************** * * Function: CheckSrcIpEqual(Packet *, struct _RuleTreeNode *, RuleFpList *) Index: snort/src/detect.h diff -u snort/src/detect.h:1.1.1.6 snort/src/detect.h:1.7 --- snort/src/detect.h:1.1.1.6 Sat Oct 1 16:16:14 2005 +++ snort/src/detect.h Sat Oct 1 20:07:05 2005 @@ -64,6 +64,10 @@ /* detection modules */ int CheckBidirectional(Packet *, struct _RuleTreeNode *, RuleFpList *); + +int CheckSrcMAC(Packet *, struct _RuleTreeNode *, RuleFpList *); +int CheckDstMAC(Packet *, struct _RuleTreeNode *, RuleFpList *); + int CheckSrcIP(Packet *, struct _RuleTreeNode *, RuleFpList *); int CheckDstIP(Packet *, struct _RuleTreeNode *, RuleFpList *); int CheckSrcIPNotEq(Packet *, struct _RuleTreeNode *, RuleFpList *); Index: snort/src/fpcreate.c diff -u snort/src/fpcreate.c:1.1.1.7 snort/src/fpcreate.c:1.8 --- snort/src/fpcreate.c:1.1.1.7 Sat Oct 1 16:16:14 2005 +++ snort/src/fpcreate.c Sat Oct 1 20:07:05 2005 @@ -71,6 +71,8 @@ static PORT_RULE_MAP *prmIpRTNX = NULL; static PORT_RULE_MAP *prmIcmpRTNX= NULL; +static PORT_RULE_MAP *prmWifiRTNX = NULL; + static FPDETECT fpDetect; /* @@ -105,6 +107,12 @@ } +int prmFindRuleGroupWifi(PORT_GROUP **wifi_group, PORT_GROUP **gen){ + PORT_GROUP *src; + return prmFindRuleGroup(prmWifiRTNX, -1, -1, &src, wifi_group, gen); +} + + /* ** These Otnhas* functions check the otns for different contents. This ** helps us decide later what group (uri, content) the otn will go to. @@ -692,6 +700,8 @@ RuleTreeNode *rtn; int sport; int dport; + u_int8_t *smac; + u_int8_t *dmac; OptTreeNode * otn; int iBiDirectional = 0; @@ -715,6 +725,10 @@ if(prmIcmpRTNX == NULL) return 1; + prmWifiRTNX = prmNewMap(); + if(prmWifiRTNX == NULL) + return 1; + for (rule=RuleLists; rule; rule=rule->next) { if(!rule->RuleList) @@ -1077,17 +1091,75 @@ } } } + if(rule->RuleList->WifiList){ /* treat a Wifi rule like an IP one without ports */ + + for(rtn = rule->RuleList->WifiList; rtn != NULL; rtn = rtn->right) + { + /* Walk OTN list -Add as Content, or NoContent */ + for( otn=rtn->down; otn; otn=otn->next ) + { + + otnx = malloc( sizeof(OTNX) ); + MEMASSERT(otnx,"otnx-WIFI"); + + otnx->otn = otn; + otnx->rtn = rtn; + +/* IpProto = */ +/* (IpProtoData *)otn->ds_list[PLUGIN_IP_PROTO_CHECK] ; */ + +/* if( IpProto ) */ +/* { */ +/* protocol = IpProto->protocol; */ +/* if( IpProto->comparison_flag == GREATER_THAN ) */ +/* protocol=-1; */ + +/* if( IpProto->comparison_flag == LESS_THAN ) */ +/* protocol=-1; */ + +/* if( IpProto->not_flag ) */ +/* protocol=-1; */ +/* } */ +/* else */ +/* { */ +/* protocol = -1; */ +/* } */ + + if( OtnHasContent( otn ) ) + { + if(fpDetect.debug) + { + printf("WIFI Content-Rule %s\n", otn->sigInfo.message); + } + prmAddRule(prmWifiRTNX, -1, -1, otnx); + + } + else + { + if(fpDetect.debug) + { + printf("WIFI NoContent-Rule %s\n", otn->sigInfo.message); + } + prmAddRuleNC(prmWifiRTNX, -1, -1, otnx); + + } + } + } + + } } prmCompileGroups(prmTcpRTNX); prmCompileGroups(prmUdpRTNX); prmCompileGroups(prmIcmpRTNX); prmCompileGroups(prmIpRTNX); + prmCompileGroups(prmWifiRTNX); BuildMultiPatternGroups(prmTcpRTNX); BuildMultiPatternGroups(prmUdpRTNX); BuildMultiPatternGroups(prmIcmpRTNX); BuildMultiPatternGroups(prmIpRTNX); + BuildMultiPatternGroups(prmWifiRTNX); if(fpDetect.debug) { @@ -1102,6 +1174,9 @@ printf("\n** IP Rule Group Stats -- "); prmShowStats(prmIpRTNX); + + printf("\n** WIFI Rule Group Stats -- "); + prmShowStats(prmWifiRTNX); } return 0; @@ -1124,6 +1199,7 @@ printf("\n** UDP Event Stats -- "); prmShowEventStats(prmUdpRTNX); printf("\n** ICMP Event Stats -- "); prmShowEventStats(prmIcmpRTNX); printf("\n** IP Event Stats -- "); prmShowEventStats(prmIpRTNX); + printf("\n** WIFI Event Stats -- "); prmShowEventStats(prmWifiRTNX); return 0; } Index: snort/src/fpdetect.c diff -u snort/src/fpdetect.c:1.1.1.11 snort/src/fpdetect.c:1.13 --- snort/src/fpdetect.c:1.1.1.11 Sat Oct 1 16:16:14 2005 +++ snort/src/fpdetect.c Sat Oct 1 20:07:05 2005 @@ -143,6 +143,10 @@ static INLINE int fpEvalHeaderIcmp(Packet *p); static INLINE int fpEvalHeaderTcp(Packet *p); static INLINE int fpEvalHeaderUdp(Packet *p); + + +static INLINE int fpEvalHeaderWifi(Packet *p); + static INLINE int fpEvalHeaderSW(PORT_GROUP *port_group, Packet *p, int check_ports); static int otnx_match (void* id, int index, void * data ); @@ -1487,6 +1491,31 @@ return fpFinalSelectEvent(&omd, p); } + +static INLINE int fpEvalHeaderWifi(Packet *p){ + + PORT_GROUP *gen, *wifi_group; + int retval; + + retval = prmFindRuleGroupWifi(&wifi_group, &gen); + + switch(retval) + { + case 4: + if(fpEvalHeader(gen, p, 0)) + { + return 1; + } + break; + default: + break; + } + + return 0; +} + + + /* ** ** NAME @@ -1514,7 +1543,19 @@ */ int fpEvalPacket(Packet *p) { - int ip_proto = p->iph->ip_proto; + int ip_proto; + + + /* check both the ip and wifi headers if they exist */ + + if(p->wifih){ + DEBUG_WRAP(DebugMessage(DEBUG_DETECT, + "Detecting on WifiList\n");); + fpEvalHeaderWifi(p); + } + + if(p->iph){ + ip_proto = p->iph->ip_proto; switch(ip_proto) { @@ -1562,5 +1603,9 @@ ** No Match on TCP/UDP, Do IP */ return fpEvalHeaderIp(p, ip_proto); + } + + return 0; } + Index: snort/src/generators.h diff -u snort/src/generators.h:1.1.1.8 snort/src/generators.h:1.10 --- snort/src/generators.h:1.1.1.8 Thu Oct 20 10:13:53 2005 +++ snort/src/generators.h Thu Oct 20 10:20:37 2005 @@ -253,6 +253,25 @@ #define GENERATOR_SMTP 124 +#define GENERATOR_SPP_ROGUE_AP 200 +#define ROGUE_AP_DETECTED 1 + +#define GENERATOR_SPP_ANTISTUMBLER 201 +#define STUMBLER_DETECTED 1 + +#define GENERATOR_WIFI_STATETABLE 210 +#define RANDOM_MAC_ADDR_TRAFFIC 1 + +#define GENERATOR_SPP_DEAUTHFLOOD 211 +#define DEAUTHFLOOD_DETECTED 1 + +#define GENERATOR_SPP_AUTHFLOOD 212 +#define AUTHFLOOD_DETECTED 1 + +#define GENERATOR_SPP_MACSPOOF 213 +#define MACSPOOF_DETECTED 1 + + /* This is where all the alert messages will be archived for each internal alerts */ @@ -439,4 +458,11 @@ #define PSNG_OPEN_PORT_STR "(portscan) Open Port" +#define RANDOM_SRC_MAC "(wifi_state_table) detected 802.11 traffic with random SRC MAC addr." +#define RANDOM_DST_MAC "(wifi_state_table) detected 802.11 traffic with random DST MAC addr." + +#define DEAUTHFLOOD_PREFIX_STR "(spp_deauthflood) Deauthflood detected!" +#define AUTHFLOOD_PREFIX_STR "(spp_authflood) Authflood detected!" +#define MACSPOOF_PREFIX_STR "(spp_macspoof) Abnormal sequence number gap detected!" + #endif /* __GENERATORS_H__ */ Index: snort/src/log.c diff -u snort/src/log.c:1.1.1.7 snort/src/log.c:1.8 --- snort/src/log.c:1.1.1.7 Sat Oct 1 20:23:21 2005 +++ snort/src/log.c Sat Oct 1 20:46:48 2005 @@ -548,6 +548,13 @@ PrintWifiHeader(fp, p); break; #endif + +#ifdef DLT_PRISM_HEADER + case DLT_PRISM_HEADER: + if(p && p->wifih) + PrintWifiHeader(fp, p); + break; +#endif case DLT_IEEE802: /* Token Ring */ if(p && p->trh) PrintTrHeader(fp, p); Index: snort/src/parser.c diff -u snort/src/parser.c:1.1.1.15 snort/src/parser.c:1.16 --- snort/src/parser.c:1.1.1.15 Sat Oct 1 16:16:13 2005 +++ snort/src/parser.c Sat Oct 1 20:07:05 2005 @@ -120,6 +120,7 @@ RuleTreeNode *GetDynamicRTN(int, RuleTreeNode *); OptTreeNode *GetDynamicOTN(int, RuleTreeNode *); void AddrToFunc(RuleTreeNode *, int); +void MacAddrToFunc(RuleTreeNode *, int); void PortToFunc(RuleTreeNode *, int, int, int); void SetupRTNFuncList(RuleTreeNode *); static void ParsePortList(char *args); @@ -425,6 +426,7 @@ while(rule != NULL) { + DumpChain(rule->RuleList->WifiList, rule->name, "WIFI Chains"); DumpChain(rule->RuleList->IpList, rule->name, "IP Chains"); DumpChain(rule->RuleList->TcpList, rule->name, "TCP Chains"); DumpChain(rule->RuleList->UdpList, rule->name, "UDP Chains"); @@ -449,6 +451,7 @@ while(rule != NULL) { + IntegrityCheck(rule->RuleList->WifiList, rule->name, "WIFI Chains"); IntegrityCheck(rule->RuleList->IpList, rule->name, "IP Chains"); IntegrityCheck(rule->RuleList->TcpList, rule->name, "TCP Chains"); IntegrityCheck(rule->RuleList->UdpList, rule->name, "UDP Chains"); @@ -694,7 +697,38 @@ } else {*/ + + if(protocol == DLT_IEEE802_11){ + proto_node.is_wifi = 1; + proto_node.sip = NULL; + proto_node.dip = NULL; + ProcessMAC(toks[2], &proto_node, SRC); /* get src mac */ + /* New in version 1.3: support for bidirectional rules */ + /* + * this checks the rule "direction" token and sets the bidirectional flag + * if the token = '<>' + */ + if(!strncmp("<>", toks[3], 2)) + { + DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Bidirectional rule!\n");); + proto_node.flags |= BIDIRECTIONAL; + } + + /* changed version 1.8.4 + * Die when someone has tried to define a rule character other than + -> or <> + */ + if(!strcmp("->", toks[3]) && !strcmp("<>", toks[3])) + { + FatalError("%s(%d): Illegal direction specifier: %s", toks[3]); + } + ProcessMAC(toks[4], &proto_node, DST); /* get dst mac */ + + } + else{ + proto_node.is_wifi = 0; ProcessIP(toks[2], &proto_node, SRC); + /*}*/ /* check to make sure that the user entered port numbers */ @@ -770,6 +804,8 @@ if(proto_node.not_dp_flag) proto_node.flags |= EXCEPT_DST_PORT; + } + DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"proto_node.flags = 0x%X\n", proto_node.flags);); DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Processing Head Node....\n");); @@ -885,6 +921,10 @@ rtn_idx = list->IpList; break; + case DLT_IEEE802_11: + rtn_idx = list->WifiList; + break; + default: rtn_idx = NULL; break; @@ -930,6 +970,12 @@ rtn_tmp = list->IpList; break; + case DLT_IEEE802_11: + list->WifiList = (RuleTreeNode *) calloc(sizeof(RuleTreeNode), sizeof(char)); + rtn_tmp = list->WifiList; + break; + + } /* copy the prototype header data into the new node */ @@ -1204,6 +1250,12 @@ } else { + if(rtn->is_wifi){ + MacAddrToFunc(rtn, SRC); + MacAddrToFunc(rtn, DST); + + } + else{ /* Attach the proper port checking function to the function list */ /* * the in-line "if's" check to see if the "any" or "not" flags have @@ -1223,7 +1275,7 @@ /* last verse, same as the first (but for dest IP) ;) */ AddrToFunc(rtn, DST); } - + } DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"RuleListEnd\n");); /* tack the end (success) function to the list */ @@ -1280,6 +1332,36 @@ +void MacAddrToFunc(RuleTreeNode *rtn, int mode){ + /* + * if IP and mask are both 0, this is a "any" IP and we don't need to + * check it + */ + switch(mode) + { + case SRC: + if((rtn->flags & ANY_SRC_MAC) == 0) + { + DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"CheckSrcMAC -> ");); + AddRuleFuncToList(CheckSrcMAC, rtn); + } + + break; + + case DST: + if((rtn->flags & ANY_DST_MAC) == 0) + { + DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"CheckDstMAC -> ");); + AddRuleFuncToList(CheckDstMAC, rtn); + } + + break; + } +} + + + + /**************************************************************************** * * Function: PortToFunc(RuleTreeNode *, int, int, int) @@ -2031,6 +2113,13 @@ if(!strcasecmp(proto_str, "arp")) return ETHERNET_TYPE_ARP; + if(!strcasecmp(proto_str, "wifi")){ +#ifdef DEBUG + fprintf(stderr, "WhichProto() returning: DLT_IEEE802_11\n"); +#endif + return DLT_IEEE802_11; +#warning "need to make a REAL protocol #define for wifi" + } /* * if we've gotten here, we have a protocol string we din't recognize and * should exit @@ -2163,6 +2252,7 @@ + IpAddrSet *AllocAddrNode(RuleTreeNode *rtn, int mode) { IpAddrSet *idx; /* indexing pointer */ @@ -2228,6 +2318,217 @@ return NULL; } + +MacAddrSet *AllocMacAddrNode(RuleTreeNode *rtn, int mode){ + MacAddrSet *idx; + + switch(mode) + { + case SRC: + if(rtn->smac == NULL){ + rtn->smac = (MacAddrSet *)calloc(sizeof(MacAddrSet), sizeof(char)); + if(rtn->smac == NULL){ + FatalError(" Unable to allocate node for MAC list\n"); + } + return rtn->smac; + } + else{ + idx = rtn->smac; + + while(idx->next != NULL){ + idx = idx->next; + } + + idx->next = (MacAddrSet *)calloc(sizeof(MacAddrSet), sizeof(char)); + if(idx->next == NULL){ + FatalError(" Unable to allocate node for MAC list\n"); + } + return idx->next; + } + break; + + case DST: + if(rtn->dmac == NULL){ + + rtn->dmac = (MacAddrSet *)calloc(sizeof(MacAddrSet), sizeof(char)); + if(rtn->dmac == NULL){ + FatalError(" Unable to allocate node for MAC list\n"); + } + return rtn->dmac; + } + else{ + idx = rtn->dmac; + + while(idx->next != NULL){ + idx = idx->next; + } + + idx->next = (MacAddrSet *)calloc(sizeof(MacAddrSet), sizeof(char)); + if(idx->next == NULL){ + FatalError(" Unable to allocate node for MAC list\n"); + } + return idx->next; + } + break; + } + return NULL; +} + + + + +int ProcessMAC(char *addr, RuleTreeNode *rtn, int mode){ + + char **toks = NULL; + int num_toks; + int i; + MacAddrSet *tmp_addr; + char *tmp; + char *enbracket; + + DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Got MAC address string: %s\n", + addr);); + + if(*addr == '!') + { + switch(mode) + { + case SRC: + rtn->flags |= EXCEPT_SRC_MAC; + break; + + case DST: + rtn->flags |= EXCEPT_DST_MAC; + break; + } + + addr++; + } + + if(*addr == '$') + { + if((tmp = VarGet(addr + 1)) == NULL) + { + FatalError("%s(%d) => Undefined variable %s\n", file_name, + file_line, addr); + } + } + else + { + tmp = addr; + } + + /* check to see if the first char is a + * bracket, which signifies a list + */ + if(*tmp == '[') + { + DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Found MAC list!\n");); + + /* *(tmp+strlen(tmp)) = ' ';*/ + enbracket = strrchr(tmp, (int)']'); /* null out the en-bracket */ + if(enbracket) *enbracket = '\x0'; + + toks = mSplit(tmp+1, ",", 128, &num_toks, 0); + + DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"mSplit got %d tokens...\n", + num_toks);); + + for(i=0; i< num_toks; i++) + { + DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"adding %s to MAC " + "address list\n", toks[i]);); + tmp = toks[i]; + while (isspace((int)*tmp)||*tmp=='[') tmp++; + enbracket = strrchr(tmp, (int)']'); /* null out the en-bracket */ + if(enbracket) *enbracket = '\x0'; + + if (strlen(tmp) == 0) + continue; + + tmp_addr = AllocMacAddrNode(rtn, mode); + if(ParseMAC(tmp, tmp_addr)) + { + switch(mode) + { + case SRC: + rtn->flags |= ANY_SRC_MAC; + break; + + case DST: + rtn->flags |= ANY_DST_MAC; + break; + } + } + } + + DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES, "Freeing %d tokens...\n", + num_toks);); + + for(i=0;iflags |= ANY_SRC_MAC; + break; + + case DST: + rtn->flags |= ANY_DST_MAC; + break; + } + } + } + + return 0; +} + + +int ParseMAC(char *paddr, MacAddrSet *address_data){ + int i = 0; + char *str, *next, *addr; + + addr = paddr; + if(*addr == '!'){ + address_data->addr_flags |= EXCEPT_MAC; + addr++; + } + + if(!strcasecmp(addr, "any")){ + memset(address_data, 0x00, sizeof(MacAddrSet)); + return 1; + } + + str = paddr; + next = str; + + while(*next){ + if((address_data->mac_addr[i] = strtol(str, &next, 16)) > 255){ + FatalError("%s(%d) => Unrecognized MAC address %s\n", file_name, file_line, addr); + } + if(str != next && i < 6){ + str = next + 1; + i++; + } + else + FatalError("%s(%d) => Unrecognized MAC address %s\n", file_name, file_line, addr); + } + return 0; +} + + + + /**************************************************************************** * * Function: ParsePort(char *, u_short *) @@ -2648,6 +2949,9 @@ rtn->type = rule->type; rtn->sip = rule->sip; rtn->dip = rule->dip; + rtn->is_wifi = rule->is_wifi; + rtn->smac = rule->smac; + rtn->dmac = rule->dmac; rtn->hsp = rule->hsp; rtn->lsp = rule->lsp; rtn->hdp = rule->hdp; Index: snort/src/plugbase.c diff -u snort/src/plugbase.c:1.1.1.10 snort/src/plugbase.c:1.17 --- snort/src/plugbase.c:1.1.1.10 Sat Oct 1 20:23:20 2005 +++ snort/src/plugbase.c Sat Oct 1 20:46:49 2005 @@ -38,6 +38,7 @@ #include #include +#include #include "plugbase.h" #include "spo_plugbase.h" @@ -63,6 +64,11 @@ #include "preprocessors/spp_sfportscan.h" #include "preprocessors/spp_frag3.h" #include "preprocessors/spp_xlink2state.h" +#include "preprocessors/spp_rogue_ap.h" +#include "preprocessors/spp_antistumbler.h" +#include "preprocessors/spp_deauth_flood.h" +#include "preprocessors/spp_auth_flood.h" +#include "preprocessors/spp_macspoof.h" /* built-in detection plugins */ #include "detection-plugins/sp_pattern_match.h" @@ -99,6 +105,29 @@ #include "detection-plugins/sp_ftpbounce.h" +#include "detection-plugins/sp_wifi_type.h" +#include "detection-plugins/sp_wifi_stype.h" +#include "detection-plugins/sp_wifi_to_ds.h" +#include "detection-plugins/sp_wifi_from_ds.h" +#include "detection-plugins/sp_wifi_more_frags.h" +#include "detection-plugins/sp_wifi_retry.h" +#include "detection-plugins/sp_wifi_pwr_mgmt.h" +#include "detection-plugins/sp_wifi_more_data.h" +#include "detection-plugins/sp_wifi_wep.h" +#include "detection-plugins/sp_wifi_order.h" +#include "detection-plugins/sp_wifi_frame_control.h" +#include "detection-plugins/sp_wifi_duration_id.h" +#include "detection-plugins/sp_wifi_bssid.h" +#include "detection-plugins/sp_wifi_seqnum.h" +#include "detection-plugins/sp_wifi_fragnum.h" +#include "detection-plugins/sp_wifi_addr4.h" +#include "detection-plugins/sp_wifi_ssid.h" + + + + + + /* built-in output plugins */ #include "output-plugins/spo_alert_syslog.h" #include "output-plugins/spo_log_tcpdump.h" @@ -170,6 +199,23 @@ SetupRespond(); #endif SetupFTPBounce(); + SetupWifiType(); + SetupWifiStype(); + SetupWifiToDs(); + SetupWifiFromDs(); + SetupWifiMoreFrags(); + SetupWifiRetry(); + SetupWifiPwrMgmt(); + SetupWifiMoreData(); + SetupWifiWep(); + SetupWifiOrder(); + SetupWifiFrameControl(); + SetupWifiDurationId(); + SetupWifiBssid(); + SetupWifiSeqNum(); + SetupWifiFragNum(); + SetupWifiAddr4(); + SetupWifiSsid(); } /**************************************************************************** @@ -421,6 +467,11 @@ SetupPsng(); SetupFrag3(); SetupXLINK2STATE(); + SetupRogueAp(); + SetupAntiStumbler(); + SetupDeauthFlood(); + SetupAuthFlood(); + SetupMACSpoof(); } /**************************************************************************** @@ -859,6 +910,16 @@ /************************** Miscellaneous Functions **************************/ +int PacketIsWIFI(Packet *p) +{ + if(p->wifih != NULL) + return 1; + + return 0; +} + + + int PacketIsIP(Packet * p) { if(p->iph != NULL) Index: snort/src/plugbase.h diff -u snort/src/plugbase.h:1.1.1.8 snort/src/plugbase.h:1.9 --- snort/src/plugbase.h:1.1.1.8 Sat Oct 1 20:23:20 2005 +++ snort/src/plugbase.h Sat Oct 1 20:46:49 2005 @@ -166,6 +166,7 @@ } PluginSignalFuncNode; +int PacketIsWIFI(Packet *); int PacketIsIP(Packet *); int PacketIsTCP(Packet *); int PacketIsUDP(Packet *); Index: snort/src/plugin_enum.h diff -u snort/src/plugin_enum.h:1.1.1.2 snort/src/plugin_enum.h:1.8 --- snort/src/plugin_enum.h:1.1.1.2 Thu Mar 10 13:13:47 2005 +++ snort/src/plugin_enum.h Fri Mar 11 10:54:29 2005 @@ -34,4 +34,21 @@ PLUGIN_TTL_CHECK, PLUGIN_BYTE_TEST, PLUGIN_PCRE, + PLUGIN_WIFI_TYPE_CHECK, + PLUGIN_WIFI_STYPE_CHECK, + PLUGIN_WIFI_TO_DS_CHECK, + PLUGIN_WIFI_FROM_DS_CHECK, + PLUGIN_WIFI_MORE_FRAGS_CHECK, + PLUGIN_WIFI_RETRY_CHECK, + PLUGIN_WIFI_PWR_MGMT_CHECK, + PLUGIN_WIFI_MORE_DATA_CHECK, + PLUGIN_WIFI_WEP_CHECK, + PLUGIN_WIFI_ORDER_CHECK, + PLUGIN_WIFI_FRAME_CONTROL_CHECK, + PLUGIN_WIFI_DURATION_ID_CHECK, + PLUGIN_WIFI_BSSID_CHECK, + PLUGIN_WIFI_SEQNUM_CHECK, + PLUGIN_WIFI_FRAGNUM_CHECK, + PLUGIN_WIFI_ADDR4_CHECK, + PLUGIN_WIFI_SSID_CHECK }; Index: snort/src/rules.h diff -u snort/src/rules.h:1.1.1.6 snort/src/rules.h:1.7 --- snort/src/rules.h:1.1.1.6 Sun Apr 24 22:11:14 2005 +++ snort/src/rules.h Sun Apr 24 22:56:31 2005 @@ -70,6 +70,15 @@ #define EXCEPT_IP 0x01 +#define EXCEPT_SRC_MAC 0x01 +#define EXCEPT_DST_MAC 0x02 +#define EXCEPT_BSSID_MAC 0x04 +#define ANY_SRC_MAC 0x08 +#define ANY_DST_MAC 0x10 +#define ANY_BSSID_MAC 0x20 + +#define EXCEPT_MAC 0x01 + #define R_FIN 0x01 #define R_SYN 0x02 #define R_RST 0x04 @@ -233,6 +242,15 @@ } IpAddrSet; #endif /* RELOCATED to parser/IpAddrSet.h */ + +/* #warning "Move _MacAddrSet to parser/MacAddrSet.h at some point" */ +typedef struct _MacAddrSet{ + u_int8_t mac_addr[6]; + u_int8_t addr_flags; + + struct _MacAddrSet *next; +} MacAddrSet; + typedef struct _RuleTreeNode { RuleFpList *rule_func; /* match functions.. (Bidirectional etc.. ) */ @@ -240,10 +258,14 @@ int head_node_number; int type; + int is_wifi; IpAddrSet *sip; IpAddrSet *dip; + MacAddrSet *smac; + MacAddrSet *dmac; + int not_sp_flag; /* not source port flag */ u_short hsp; /* hi src port */ @@ -278,6 +300,7 @@ RuleTreeNode *TcpList; RuleTreeNode *UdpList; RuleTreeNode *IcmpList; + RuleTreeNode *WifiList; struct _OutputFuncNode *LogList; struct _OutputFuncNode *AlertList; struct _RuleListNode *ruleListNode; Index: snort/src/snort.c diff -u snort/src/snort.c:1.1.1.11 snort/src/snort.c:1.12 --- snort/src/snort.c:1.1.1.11 Sat Oct 1 20:23:20 2005 +++ snort/src/snort.c Sat Oct 1 20:46:49 2005 @@ -97,6 +97,8 @@ #define DLT_OLDPFLOG 17 #endif +#include "wifi_statetable.h" + /* G L O B A L S ************************************************************/ extern OutputFuncNode *AlertList; extern OutputFuncNode *LogList; @@ -616,7 +618,15 @@ printRuleOrder(); LogMessage("Log directory = %s\n", pv.log_dir); } - } + + /* Create WifiStateTable */ + if(!pv.quiet_flag) + { + LogMessage("\n+++++++++++++++++++++++++++++++++++++++++++++++++++\n"); + LogMessage("Allocating memory for WifistateTable...\n"); + } + WSTDoTable(); + } #ifndef WIN32 @@ -1701,6 +1711,19 @@ grinder = DecodeIEEE80211Pkt; break; #endif + +#ifdef DLT_PRISM_HEADER + case DLT_PRISM_HEADER: + if(!pv.readmode_flag){ + if(!pv.quiet_flag) + LogMessage("Decoding IEEE 802.11 with PRISM headers on interface %s\n", + PRINT_INTERFACE(pv.interface)); + } + + grinder = DecodePrismHdr; + break; +#endif + #ifdef DLT_ENC case DLT_ENC: /* Encapsulated data */ if (!pv.readmode_flag) Index: snort/src/wifi_statetable.c diff -u /dev/null snort/src/wifi_statetable.c:1.2 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/wifi_statetable.c Sat Jun 25 00:31:22 2005 @@ -0,0 +1,602 @@ +/* +** Copyright (C) 2004 Sebastien Gracia +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Copyright disclaimers: +** The Directeur Central de la sécurité des systèmes d'information hereby +** disclaims all copyright interest in the changes and enhancements +** made by sebastien Gracia. +** 5th Fev 2004. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#ifdef HAVE_MAP_ANONYMOUS +#include +#endif + +#include "decode.h" +#include "util.h" +#include "debug.h" +#include "generators.h" +#include "log.h" +#include "plugbase.h" +#include "detect.h" +#include "snort.h" + +#ifndef __WIFI_STATETABLE_C__ +#define __WIFI_STATETABLE_C__ +#include "wifi_statetable.h" +#endif + +static u_int16_t current_size = WST_DATA_INITIAL_LENGTH; +/* Total size of data associated with a MAC address inside the WST + * (Wifi StateTable). Incremented during preprocessors initialization + * whenever a preprocessor request new data recording */ + +static u_int8_t *WST_ptr; /* pointer to the WST */ + +static u_int32_t rdm = 0; /* random value */ +/* MAC address and corresponding data will be inserted inside WST through + * a Hashing process (see WSTSearchAndInsert comments). rdm is used to avoid + * predictable Hash value */ + +static u_int32_t alert_time = 0; +/* time in second when the last "RANDOM_MAC_ADDR_TRAFFIC" alert was sended */ + +static u_int32_t timeout = 0; +/* Time validity of a MAC address and associated data recorded inside the + * WST. WSTSearchAndInsert function considers as decayed a MAC address and data + * with a timeval older than timeout. + * Update throught WSTUpdateTimeout. */ + +/* + * Function: u_int16_t WSTInit(u_int8_t size) + * + * Purpose: Called by WST's preprocessors. + * Updates current_size and returns data offset corresponding to + * calling preprocessor's needs. + * + * Arguments: size => data's size + * + * Returns: data's offset + */ +u_int16_t WSTInit(u_int8_t size) +{ + u_int16_t buffer_size; + + buffer_size = current_size; + current_size += size; + + DEBUG_WRAP(DebugMessage(DEBUG_WIFI_STATETABLE, "WSTInit function." + "current_size = %u, was just %u bytes increased\n", + current_size, size);); + + return(buffer_size); +} + + +/* + * Function: void WSTDoTable(void) + * + * Purpose: Creates WST called by SnortMain. + * + * Arguments: None + * + * Returns: void + */ +void WSTDoTable(void) +{ + static u_int32_t wst_total_size; /* total size in bytes of WST */ + + DEBUG_WRAP(DebugMessage(DEBUG_WIFI_STATETABLE, "Creating WST\n");); + + if(current_size == WST_DATA_INITIAL_LENGTH){ + if(!pv.quiet_flag){ + LogMessage("No memory allocated since no preprocessor requires it"); + LogMessage("\n+++++++++++++++++++++++++++++++++++++++++++++++++++\n"); + } + return; + } + + srand(time(0)); + rdm = rand(); /* allocating a radom value to rdm */ + + wst_total_size = current_size*WST_LENGTH; + +#ifdef HAVE_MAP_ANONYMOUS + WST_ptr = mmap(NULL, wst_total_size, PROT_READ | PROT_WRITE , + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (WST_ptr == MAP_FAILED){ + FatalError("WSTDoTable failed to map requested length into memory: %s\n", + strerror(errno)); + } +#else + WST_ptr = malloc(wst_total_size); + if (WST_ptr == NULL){ + FatalError("WSTDoTable failed to allocate requested memory: %s\n", + strerror(errno)); + } +#endif + if(!pv.quiet_flag){ + LogMessage("%u Kbyte allocated\n", (wst_total_size >> 10)); + LogMessage(" %s: %u\n", OPT_WST_LENGTH, WST_LENGTH); + LogMessage(" %s: %u\n", OPT_WST_TIMEOUT , timeout); + LogMessage(" %s: %u\n", OPT_MAX_HASH_RETRY, MAX_HASH_RETRY); + LogMessage(" %s: %u", OPT_WST_ALERT_PERIOD, WST_ALERT_PERIOD); + LogMessage("\n+++++++++++++++++++++++++++++++++++++++++++++++++++\n"); + } + memset(WST_ptr , 0, wst_total_size); + + srand(time(0)); + rdm = rand(); /* allocating a radom value to rdm */ + + AddFuncToCleanExitList(WSTCleanExitFunction, &wst_total_size); + AddFuncToRestartList(WSTRestartFunction, &wst_total_size); + + return; +} + +/* + * Function: void WSTUpdateTimeout(u_int32_t time) + * + * Purpose: Called by WST preprocessors. + * Whenever called, WSTmain checks whether or not needed timeout is superior or not + * to actual WST timeout. + * If not, updates it. + * + * Arguments: time => WST timeout length requested by calling preprocessor. + * + * Returns: void + */ +void WSTUpdateTimeout(u_int32_t time) +{ + if(time * 2 >= timeout){ + timeout = time * 2; + } + DEBUG_WRAP(DebugMessage(DEBUG_WIFI_STATETABLE, " WST timeout =%u\n", timeout);); + return; +} + + +/* + * Function: void WSTMain(Packet *p, wst_flag_type flag_addr) + * + * Purpose: Called by WST preprocessors. + * Whenever called, WSTmain checks whether or not a previous preprocessor + * already made a request for corresponding MAC address packet (src or dest). + * If not, fills up desired p->wstidx.cache_addr by calling WSTSearchAndUInsert + * function. + * + * Arguments: p => pointer to the current packet data struct + * + * flag_addr => either src or dst wst_flag_type depending on + * calling preprocessors needs. + * + * Returns: void + */ +void WSTMain(Packet *p, wst_flag_type flag_addr) +{ + u_int8_t *MACaddr_ptr; /* pointer to p->wifih corresponding to desired + MAC address */ + int8_t offset; + + /* checks whether or not p->wstidx.cache_addr[flag_addr] is already filled up. + * if not determine MACaddr_ptr and finally fills p->wstidx.cache_addr[flag_addr] up */ + + if(!p->wstidx.cache_addr[flag_addr]){ + offset = WSTDetermineMACAddrOffset(p, flag_addr); + if(offset == -1){ + p->wstidx.cache_addr[flag_addr] = WST_FAILED; + return; + } + else{ + MACaddr_ptr = ((u_int8_t*) p->wifih + offset); + + /* finally calls WSTSearchAndInsert function to determine + * p->wstidx.cache_addr[flag_addr] */ + + p->wstidx.cache_addr[flag_addr] = WSTSearchAndInsert(p, MACaddr_ptr, flag_addr); + } + } + return; +} + + +/* + * Function: int8_t WSTDetermineMACAddrOffset(Packet *p, wst_flag_type flag_addr) + * + * Purpose: Depending on both kind of frame type and needs + * (src or dst MAC address), determines needed offset inside p->wifih + * + * Arguments: p => pointer to the current packet data struct + * + * flag_addr => either src or dst wst_flag_type depending on + * calling preprocessors needs. + * + * Returns: needed offset inside p->wifih or -1 if failed + */ +int8_t WSTDetermineMACAddrOffset(Packet *p, wst_flag_type flag_addr) +{ + + switch(p->wifih->type){ + + case TYPE_MANAGEMENT: + if(flag_addr == WST_FLAG_SRCADDR){ + return(OFFSET_MANAGEMENT_SRCADDR); + } + else{ + return(OFFSET_MANAGEMENT_DESTADDR); + } + + case TYPE_CONTROL: + if(p->wifih->stype == STYPE_CTS || p->wifih->stype == STYPE_ACK){ + if(flag_addr == WST_FLAG_DESTADDR){ + return(OFFSET_CONTROL_DESTADDR); + } + else{ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, + "received frame do not contain any source MAC address/invalid request\n");); + return -1; + } + } + else{ + if(flag_addr == WST_FLAG_SRCADDR){ + return(OFFSET_CONTROL_SRCADDR); + } + else{ + return(OFFSET_CONTROL_DESTADDR); + } + } + + case TYPE_DATA: + if(p->wifih->from_ds){ + if(p->wifih->to_ds){ /* from_ds == 1 && to_ds == 1 */ + if(flag_addr == WST_FLAG_SRCADDR){ + return(OFFSET_DATA_SRCADDR_FROM_TO); + } + else{ + return(OFFSET_DATA_DESTADDR_FROM_TO); + } + } + else{ + if(flag_addr == WST_FLAG_SRCADDR){ /* from_ds == 1 && to_ds == 0 */ + return(OFFSET_DATA_SRCADDR_FROM); + } + else{ + return(OFFSET_DATA_DESTADDR_FROM); + } + } + } + else{ + if(p->wifih->to_ds){ /* from_ds == 0 && to_ds == 1 */ + if(flag_addr == WST_FLAG_SRCADDR){ + return(OFFSET_DATA_SRCADDR_TO); + } + else{ + return(OFFSET_DATA_DESTADDR_TO); + } + } + else{ + if(flag_addr == WST_FLAG_SRCADDR){ /* from_ds == 0 && to_ds == 0 */ + return(OFFSET_DATA_SRCADDR_); + } + else{ + return(OFFSET_DATA_DESTADDR_); + } + } + } + + default: + DEBUG_WRAP(DebugMessage(DEBUG_WIFI_STATETABLE, "received frame with unknown/invalid type\n");); + return -1; + } +} + + +/* + * Function: int32_t WSTSearchAndInsert(Packet *p, u_int8_t *MACaddr_ptr, + * wst_flag_type flag_addr) + * + * Purpose: Searches for the MAC address pointed by MACaddr_prt inside WST. + * In default, inserts it. + * If neither able to find nor insert it, sends an alert (traffic with random + * address detected). + * + * Arguments: p => pointer to the current packet data struct + * + * MACaddr_ptr => pointer to p->wifih corresponding to desired + * MAC address + * + * flag_addr => either src or dst wst_flag_type depending upon + * calling preprocessors needs. + * + * Returns: memory address corresponding to the place where MAC address and + * related data are recorded inside WST. + */ +int32_t WSTSearchAndInsert(Packet *p, u_int8_t *MACaddr_ptr, + wst_flag_type flag_addr) +{ + u_int32_t hash, x[2]; + u_int32_t wst_offset_line; /* offset line inside WST table */ + u_int8_t cpt=0; /* number of retry while trying to determine where MAC adrress and + * related data are recorded inside WST */ + struct timeval wst_tv, tv_diff; + Event event; + char outstring[255], tmp[255]; + + DEBUG_WRAP(DebugMessage(DEBUG_WIFI_STATETABLE, "WSTSearchAndInsert function processing " + "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x MAC address\n", + *((u_int8_t *)(MACaddr_ptr)), *((u_int8_t *)(MACaddr_ptr + 1)), + *((u_int8_t *)(MACaddr_ptr + 2)), *((u_int8_t *)(MACaddr_ptr + 3)), + *((u_int8_t *)(MACaddr_ptr + 4)), *((u_int8_t *)(MACaddr_ptr + 5)));); + + /* fill up x[0] and x[1]. x[0] contains the 4 first bytes of MAC address, x[1] + * the last 2. To avoid later predictable hash value x[0] is gonna be xored with a random + * value: rdm. */ + + x[1]=0; + memcpy(&x[0], MACaddr_ptr, SIZE_MAC_ADDR); + x[0] ^= rdm; + + /* It's time to determine where MAC adrress and related data are recorded + * inside WST */ + + do{ + + /* Determines Hash value */ + + hash = WSTMix32(x[0], x[1]); + hash %= WST_LENGTH; + + /* evaluates wst_offset_line */ + + wst_offset_line = hash * current_size; + + /* Checks if wst_offset_line is the offset line associated with needed MAC + * address (the one we are looking for) */ + + if(!memcmp(MACaddr_ptr, WST_ptr + wst_offset_line, SIZE_MAC_ADDR)){ + DEBUG_WRAP(DebugMessage(DEBUG_WIFI_STATETABLE, "Find corresponding line offset" + " inside WST\n");); + + /* Updates timeval related with MAC address inside WST */ + + memcpy(WST_ptr + wst_offset_line + SIZE_MAC_ADDR, &p->pkth->ts, + sizeof(struct timeval)); + + /* returns memory address corresponding to MAC address and related data + we were looking for */ + + return((int32_t) (WST_ptr + wst_offset_line)); + } + + /* calculated wst_offset_line isn't the offset line associated with needed + * MAC address. Maybe MAC address associated with wst_offset_line should be + * considered as decayed because of an expired associated timeval? */ + + memcpy(&wst_tv , WST_ptr + wst_offset_line + SIZE_MAC_ADDR, + sizeof(struct timeval)); + tv_diff = WSTTimevalSubtract(p->pkth->ts, wst_tv); + if(tv_diff.tv_sec > timeout){ + DEBUG_WRAP(DebugMessage(DEBUG_WIFI_STATETABLE, "Find a decayed MAC address" + " inside WST\n");); + + /* Overwrites decayed MAC address with the new one and updates timeval + * related with */ + + memcpy(WST_ptr + wst_offset_line, MACaddr_ptr, SIZE_MAC_ADDR); + memcpy(WST_ptr + wst_offset_line + SIZE_MAC_ADDR, &p->pkth->ts, + sizeof(struct timeval)); + + /* refreshes WST data */ + + bzero(WST_ptr + wst_offset_line + SIZE_MAC_ADDR + sizeof(struct timeval), + current_size - SIZE_MAC_ADDR - sizeof(struct timeval)); + + /* returns memory address corresponding to the place where MAC address + * and related data are now recorded inside WST */ + + return((int32_t) (WST_ptr + wst_offset_line)); + } + + /* Though MAC address pointed by wst_offset_line isn't the one + * we were looking for, associated timeval will be updated. + * Such refresh is made too avoid any subsequent loss of data due to both + * collision and unlucky timeval expiry situation. + * On the other hand, such refresh might involv some "dead wst_offset_line + * " offset. According to wireless network characteristics, it shouldn't + * have any real consequences. */ + + memcpy(WST_ptr + wst_offset_line + SIZE_MAC_ADDR, &p->pkth->ts, + sizeof(struct timeval)); + + /* Raising x[1] to calculate a new hash value and furthermore + a new wst_offset_line. */ + + x[1] += 1; + cpt++; + } while(cpt <= MAX_HASH_RETRY); + + + DEBUG_WRAP(DebugMessage(DEBUG_WIFI_STATETABLE, "WSTSearchAndInsert function failed" + " to insert MAC address inside WST\n");); + + /* Checks whether or not an alert has already been sended before WST_ALERT_PERIOD + * ended. */ + + if(alert_time + WST_ALERT_PERIOD > p->pkth->ts.tv_sec){ + return( WST_FAILED); + } + + /* an alert gonna be raised */ + + alert_time = p->pkth->ts.tv_sec; + + if(flag_addr == WST_FLAG_SRCADDR){ + snprintf(outstring, 255, RANDOM_SRC_MAC); + } + else{ + snprintf(outstring, 255, RANDOM_DST_MAC); + } + snprintf(tmp, 255, + "\nAddr src: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x" + " -> Addr dst: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x" + ",\nBssid: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x, TYPE: 0x%x, STYPE: 0x%x.", + p->wifih->addr2[0], p->wifih->addr2[1], p->wifih->addr2[2], + p->wifih->addr2[3], p->wifih->addr2[4], p->wifih->addr2[5], + p->wifih->addr1[0], p->wifih->addr1[1], p->wifih->addr1[2], + p->wifih->addr1[3], p->wifih->addr1[4], p->wifih->addr1[5], + p->wifih->addr3[0], p->wifih->addr3[1], p->wifih->addr3[2], + p->wifih->addr3[3], p->wifih->addr3[4], p->wifih->addr3[5], + p->wifih->type, p->wifih->stype); + strncat(outstring, tmp, 255); + + DEBUG_WRAP(DebugMessage(DEBUG_WIFI_STATETABLE, "%s\n", outstring);); + + SetEvent(&event, GENERATOR_WIFI_STATETABLE, RANDOM_MAC_ADDR_TRAFFIC, + 1, 0, 0, 0); + CallAlertFuncs(p, outstring, NULL, &event); /* send alert */ + + return(WST_FAILED); +} + + +/* + * Function: u_int32_t WSTMix32(u_int32_t x, u_int32_t y) + * + * Purpose: Calculate an hash value based on two u_int32_t. + * + * Arguments: x => first u_int32_t + * y => second u_int32_t + * + * Returns: hash value + */ +u_int32_t WSTMix32(u_int32_t x, u_int32_t y) +{ + u_int32_t db5=0xfb5cc520, w31_27; + + w31_27 = (y>>27); y<<=5; y+=((db5>>w31_27)^(db5<<(32-w31_27))); + w31_27 = (y>>27); y<<=5; y+=((db5>>w31_27)^(db5<<(32-w31_27))); + + w31_27 = (x>>27); x<<=5; x+=((db5>>w31_27)^(db5<<(32-w31_27))); + + x^=y; + + w31_27 = (x>>27); x<<=5; x+=((db5>>w31_27)^(db5<<(32-w31_27))); + w31_27 = (x>>27); x<<=5; x+=((db5>>w31_27)^(db5<<(32-w31_27))); + w31_27 = (x>>27); x<<=5; x+=((db5>>w31_27)^(db5<<(32-w31_27))); + w31_27 = (x>>27); x<<=5; x+=((db5>>w31_27)^(db5<<(32-w31_27))); + w31_27 = (x>>27); x<<=5; x+=((db5>>w31_27)^(db5<<(32-w31_27))); + + return(x); +} + + +/* + * Function: struct timeval WSTTimevalSubtract(struct timeval x, struct timeval y) + * + * Purpose: Subtract two `struct timeval. + * + * Arguments: x => first struct timeval value + * y => second struct timeval value + * + * Returns: result of subtract + */ +struct timeval WSTTimevalSubtract (struct timeval x, struct timeval y) +{ + struct timeval result; + + /* Perform the carry for the later subtraction by updating Y. */ + if (x.tv_usec < y.tv_usec){ + int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1; + y.tv_usec -= 1000000 * nsec; + y.tv_sec += nsec; + } + if (x.tv_usec - y.tv_usec > 1000000){ + int nsec = (x.tv_usec - y.tv_usec) / 1000000; + y.tv_usec += 1000000 * nsec; + y.tv_sec -= nsec; + } + + /* Compute the time remaining to wait. + `tv_usec' is certainly positive. */ + result.tv_sec = x.tv_sec - y.tv_sec; + result.tv_usec = x.tv_usec - y.tv_usec; + + return(result); +} + + +/* + * Function: void WSTCleanExitFunction(int, void *) + * + * Purpose: free wifi statetable while exiting snort + * + * Arguments: + * + * Returns: void + */ +void WSTCleanExitFunction(int signal, void *arg) +{ + u_int32_t *size = (u_int32_t *) arg; + + DEBUG_WRAP(DebugMessage(DEBUG_WIFI_STATETABLE, "WSTCleanExitFunction\n");); + +#ifdef HAVE_MAP_ANONYMOUS + if(munmap(NULL, *size) == -1) + LogMessage("Munmap failure: %s\n", + strerror(errno)); +#else + free(WST_ptr); +#endif + return; +} + + +/* + * Function: void WSTRestartFunction(int, void *) + * + * Purpose: free wifi statetable while restarting snort + * + * Arguments: + * + * Returns: void + */ +void WSTRestartFunction(int signal, void *arg) +{ + u_int32_t *size = (u_int32_t *) arg; + + DEBUG_WRAP(DebugMessage(DEBUG_WIFI_STATETABLE, "WSTRestartFunction\n");); + +#ifdef HAVE_MAP_ANONYMOUS + if(munmap(NULL, *size) == -1) + LogMessage("Munmap failure: %s\n", + strerror(errno)); +#else + free(WST_ptr); +#endif + return; +} + Index: snort/src/wifi_statetable.h diff -u /dev/null snort/src/wifi_statetable.h:1.2 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/wifi_statetable.h Sat Jun 25 00:31:22 2005 @@ -0,0 +1,159 @@ +/* +** Copyright (C) 2004 Sebastien Gracia +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Copyright disclaimers: +** The Directeur Central de la sécurité des systèmes d'information hereby +** disclaims all copyright interest in the changes and enhancements +** made by sebastien Gracia. +** 5th Fev 2004. +*/ + + +#ifndef __WIFI_STATETABLE_H__ +#define __WIFI_STATETABLE_H__ + + +/* I N C L U D E S +*******************************************************************************/ + + +/* D E F I N E S +*******************************************************************************/ + +#define SIZE_MAC_ADDR (u_int32_t) 6 + +#define WST_DATA_INITIAL_LENGTH SIZE_MAC_ADDR + sizeof(struct timeval) +/* intitial size of data recorded inside the WST (Wifi StateTable), + * corresponding to the size of a MAC address and a struct timeval */ + + +#define WST_LENGTH (u_int32_t) 1 << 18 +/* Total lenght of the WST, corresponding to the maximum number of valid MAC + * address recorded inside. A valid MAC address means a MAC address with an + * associated timeval below WST_TIMEOUT */ + +#define MAX_HASH_RETRY (u_int8_t) 5 +/* Maximum number of retry for the WSTSearchAnsInsert function to insert or + * search for a MAC address inside the WST. Above this limit an alert will be + * send because someone around sending wifi frames with numerous random either + * source or destination MAC address */ + +#define WST_ALERT_PERIOD 120 +/* Number of second to wait for sending a new "RANDOM_MAC_ADDR-TRAFFIC" alert + * if such a situation is still occur */ + +#define WST_FAILED -1 +/* value return by WSTSearchAnsInsert function whenever MAX_HASH_RETRY is + * overruned or WSTMain received frame with unknow/invalid type */ + +#define OPT_WST_LENGTH "wst_length" +#define OPT_WST_TIMEOUT "wst_timeout" +#define OPT_MAX_HASH_RETRY "wst_max_hash_retry" +#define OPT_WST_ALERT_PERIOD "wst_alert_period" + +typedef enum { + /* 802.11 management frame address offset */ + OFFSET_MANAGEMENT_SRCADDR = 0x0a, + OFFSET_MANAGEMENT_DESTADDR = 0x04, + + /* 802.11 control frame address offset */ + OFFSET_CONTROL_SRCADDR = 0x0a, + OFFSET_CONTROL_DESTADDR = 0x04, + + /* 802.11 data frame address offset */ + OFFSET_DATA_SRCADDR_FROM_TO = 0x0a, + OFFSET_DATA_DESTADDR_FROM_TO = 0x10, + + OFFSET_DATA_SRCADDR_FROM = 0x10, + OFFSET_DATA_DESTADDR_FROM = 0x04, + + OFFSET_DATA_SRCADDR_TO = 0x0a, + OFFSET_DATA_DESTADDR_TO = 0x10, + + OFFSET_DATA_SRCADDR_ = 0x0a, + OFFSET_DATA_DESTADDR_ = 0x04 +} addr_offset_t; +/* Whenever called WSTSearchAndInsert function will record data associated on + * either source or destination MAC address, depending on calling + * preprocessor's needs. Thanks to addr_offset_t, WSTSearchAndInsert will look + * for the right offset for each packet */ + +typedef enum { + WST_FLAG_SRCADDR = 0x00, + WST_FLAG_DESTADDR = 0x01 +} wst_flag_type; + + +/* borrowed from airsnort */ +typedef enum { /* 802.11 frame types */ + TYPE_INVALID = -1, + TYPE_MANAGEMENT = 0x00, + TYPE_CONTROL = 0x01, + TYPE_DATA = 0x02 +} wifi_type_t; + + +typedef enum { /* 802.11 management frame subtypes */ + STYPE_ASSOCREQ = 0x00, /* Subtypes are already AND'ed with their */ + STYPE_ASSOCRESP = 0x01, /* corresponding Types to prevent false */ + STYPE_REASSOC_REQ = 0x02, /* positives and the need for checking the type */ + STYPE_REASSOC_RESP = 0x03, /* independently */ + STYPE_PROBEREQ = 0x04, + STYPE_PROBERESP = 0x05, + STYPE_BEACON = 0x08, + STYPE_ATIM = 0x09, + STYPE_DISASSOC = 0x0a, + STYPE_AUTH = 0x0b, + STYPE_DEAUTH = 0x0c, + STYPE_INVALID = 0x0d, + +/* 802.11 control frame subtypes */ + STYPE_PS = 0x0a, + STYPE_RTS = 0x0b, + STYPE_CTS = 0x0c, + STYPE_ACK = 0x0d, + STYPE_CFEND = 0x0e, + STYPE_CFEND_CFACK = 0x0f, + +/* 802.11 data frame subtypes */ + STYPE_DATA = 0x00, + STYPE_CFACK = 0x01, + STYPE_CFPOLL = 0x02, + STYPE_CFACK_CFPOLL = 0x03, + STYPE_NULLFUNC = 0x04, + STYPE_CFACK_NULLFUNC = 0x05, + STYPE_CFPOLL_NULLFUNC = 0x06, + STYPE_CFACK_CFPOLL_NULLFUNC = 0x07 +} wifi_stype_t; + + +/* P R O T O T Y P E S +*******************************************************************************/ + +u_int16_t WSTInit(u_int8_t); +void WSTDoTable(); +void WSTUpdateTimeout(u_int32_t); +void WSTMain(Packet *, wst_flag_type); +int8_t WSTDetermineMACAddrOffset(Packet *, wst_flag_type); +int32_t WSTSearchAndInsert(Packet *, u_int8_t *, wst_flag_type); +u_int32_t WSTMix32(u_int32_t, u_int32_t); +struct timeval WSTTimevalSubtract (struct timeval , struct timeval ); +void WSTCleanExitFunction(int, void *); +void WSTRestartFunction(int, void *); + + +#endif /* __WIFI_STATETABLE_H__ */ Index: snort/src/detection-plugins/Makefile.am diff -u snort/src/detection-plugins/Makefile.am:1.1.1.5 snort/src/detection-plugins/Makefile.am:1.13 --- snort/src/detection-plugins/Makefile.am:1.1.1.5 Sat Oct 1 16:16:17 2005 +++ snort/src/detection-plugins/Makefile.am Sat Oct 1 20:07:05 2005 @@ -17,6 +17,24 @@ sp_clientserver.c sp_clientserver.h sp_byte_check.c sp_byte_check.h \ sp_byte_jump.c sp_byte_jump.h sp_pcre.c sp_pcre.h sp_isdataat.c sp_isdataat.h \ sp_flowbits.c sp_flowbits.h sp_asn1.c sp_asn1.h \ -sp_ftpbounce.c sp_ftpbounce.h +sp_ftpbounce.c sp_ftpbounce.h \ +sp_wifi_type.c sp_wifi_type.h \ +sp_wifi_stype.c sp_wifi_stype.h \ +sp_wifi_to_ds.c sp_wifi_to_ds.h \ +sp_wifi_from_ds.c sp_wifi_from_ds.h \ +sp_wifi_more_frags.c sp_wifi_more_frags.h \ +sp_wifi_retry.c sp_wifi_retry.h \ +sp_wifi_pwr_mgmt.c sp_wifi_pwr_mgmt.h \ +sp_wifi_more_data.c sp_wifi_more_data.h \ +sp_wifi_wep.c sp_wifi_wep.h \ +sp_wifi_order.c sp_wifi_order.h \ +sp_wifi_frame_control.c sp_wifi_frame_control.h \ +sp_wifi_duration_id.c sp_wifi_duration_id.h \ +sp_wifi_bssid.c sp_wifi_bssid.h \ +sp_wifi_seqnum.c sp_wifi_seqnum.h \ +sp_wifi_fragnum.c sp_wifi_fragnum.h \ +sp_wifi_addr4.c sp_wifi_addr4.h \ +sp_wifi_ssid.c sp_wifi_ssid.h \ +wifi_datatypes.h INCLUDES = @INCLUDES@ Index: snort/src/detection-plugins/sp_wifi_addr4.c diff -u /dev/null snort/src/detection-plugins/sp_wifi_addr4.c:1.3 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_addr4.c Mon Aug 25 21:37:21 2003 @@ -0,0 +1,248 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_addr4.c,v 1.3 2003/08/26 01:37:21 andrew Exp $ */ + +/* sp_wifi_addr4 + * + * Purpose: + * + * Tests 802.11 frames 4th address field. + * + * Arguments: + * + * {{ '!' | {} } } + * + * Effect: + * + * Success on address field match, failure otherwise. + * + */ + +#include +#include +#include +#include + +#include "rules.h" +#include "decode.h" +#include "plugbase.h" +#include "parser.h" +#include "debug.h" +#include "util.h" +#include "plugin_enum.h" + +#include "wifi_datatypes.h" + +/* don't forget to include the name of this file in plugbase.h! */ + +extern char *file_name; /* this is the file name from rules.c, generally used + for error messages */ + +extern int file_line; /* this is the file line number from rules.c that is + used to indicate file lines for error messages */ + +typedef struct _WifiAddr4Data +{ + u_int8_t addr4[6]; + u_int8_t not_flag; +} WifiAddr4Data; + +void WifiAddr4Init(char *, OptTreeNode *, int); +void WifiAddr4RuleParseFunction(char *, OptTreeNode *); +int WifiAddr4DetectorFunction(Packet *, struct _OptTreeNode *, OptFpList *); + +/**************************************************************************** + * + * Function: SetupWifiAddr4() + * + * Purpose: Generic detection engine plugin template. Registers the + * configuration function and links it to a rule keyword. This is + * the function that gets called from InitPlugins in plugbase.c. + * + * Arguments: None. + * + * Returns: void function + * + ****************************************************************************/ +void SetupWifiAddr4() +{ + /* map the keyword to an initialization/processing function */ + RegisterPlugin("addr4", WifiAddr4Init); + + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Plugin: WifiAddr4 Setup\n");); +} + + +/**************************************************************************** + * + * Function: WifiAddr4Init(char *, OptTreeNode *) + * + * Purpose: Generic rule configuration function. Handles parsing the rule + * information and attaching the associated detection function to + * the OTN. + * + * Arguments: data => rule arguments/data + * otn => pointer to the current rule option list node + * + * Returns: void function + * + ****************************************************************************/ +void WifiAddr4Init(char *data, OptTreeNode *otn, int protocol) +{ + /* allocate the data structure and attach it to the + rule's data struct list */ + otn->ds_list[PLUGIN_WIFI_ADDR4_CHECK] = (WifiAddr4Data *) calloc(sizeof(WifiAddr4Data), sizeof(char)); + + /* be sure to check that the protocol that is passed in matches the + transport layer protocol that you're using for this rule! */ + + /* this is where the keyword arguments are processed and placed into the + rule option's data structure */ + WifiAddr4RuleParseFunction(data, otn); + + /* finally, attach the option's detection function to the rule's + detect function pointer list */ + AddOptFuncToList(WifiAddr4DetectorFunction, otn); +} + + + +/**************************************************************************** + * + * Function: WifiAddr4RuleParseFunction(char *, OptTreeNode *) + * + * Purpose: This is the function that is used to process the option keyword's + * arguments and attach them to the rule's data structures. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: void function + * + ****************************************************************************/ +void WifiAddr4RuleParseFunction(char *data, OptTreeNode *otn) +{ + WifiAddr4Data *ds_ptr; /* data struct pointer */ + + /* set the ds pointer to make it easier to reference the option's + particular data struct */ + ds_ptr = otn->ds_list[PLUGIN_WIFI_ADDR4_CHECK]; + + /* manipulate the option arguments here */ + while(isspace((int) *data)) data++; + + if(*data == '!'){ + ds_ptr->not_flag = 1; + data++; + } + + /* set the final option arguments here */ + + if(WifiAddr4ParseMAC(ds_ptr->addr4, data) < 0) + FatalError("%s (%d) => Error parsing MAC address \"%s\"\n", file_name, file_line, data); +} + + + +/* + * Function: WifiAddr4ParseMAC(u_int8_t *, char *) + * + * Purpose: Parses BSSIDs from a character string and stores them + * in a byte array. + * + * Arguments: bssid => pointer to byte array to store parsed BSSID in + * mac_str => character string containing BSSID + * + * Returns: 0 on success, -1 on error + * + */ + +int WifiAddr4ParseMAC(u_int8_t *bssid, char *mac_str){ + + u_int64_t mac; + + if(strlen(mac_str) != 14) + return -1; + + mac = strtoll(mac_str, NULL, 16); + if(mac < 0 || mac > 0xffffffffffff) + return -1; + + bssid[0] = mac >> 40 & 0x00ff; + bssid[1] = mac >> 32 & 0x00ff; + bssid[2] = mac >> 24 & 0x00ff; + bssid[3] = mac >> 16 & 0x00ff; + bssid[4] = mac >> 8 & 0x00ff; + bssid[5] = mac & 0x00ff; + + return 0; +} + + + +/**************************************************************************** + * + * Function: WifiAddr4DetectorFunction(char *, OptTreeNode *) + * + * Purpose: Use this function to perform the particular detection routine + * that this rule keyword is supposed to encompass. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: If the detection test fails, this function *must* return a zero! + * On success, it calls the next function in the detection list + * + ****************************************************************************/ +int WifiAddr4DetectorFunction(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list) +{ + + WifiAddr4Data *plugin_data; + plugin_data = otn->ds_list[PLUGIN_WIFI_ADDR4_CHECK]; + + if(!p->wifih){ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Not a WIFI frame\n");); + return 0; + } + + if(p->wifih->type != TYPE_DATA || p->wifih->to_ds != 1 || p->wifih->from_ds != 1){ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Frame does not contain addr4 field\n");); + return 0; + } + + /* your detection function tests go here */ + if((plugin_data->not_flag && (memcmp(p->wifih->addr3, plugin_data->addr4, 6) != 0)) || + (!plugin_data->not_flag && (memcmp(p->wifih->addr3, plugin_data->addr4, 6) == 0))) + { + return fp_list->next->OptTestFunc(p, otn, fp_list->next); + } +#ifdef DEBUG + else + { + /* you can put debug comments here or not */ + DebugMessage(DEBUG_PLUGIN,"No match\n"); + } +#endif + + /* if the test isn't successful, this function *must* return 0 */ + return 0; +} + + + Index: snort/src/detection-plugins/sp_wifi_addr4.h diff -u /dev/null snort/src/detection-plugins/sp_wifi_addr4.h:1.1 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_addr4.h Fri Jul 25 18:59:09 2003 @@ -0,0 +1,26 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_addr4.h,v 1.1 2003/07/25 22:59:09 andrew Exp $ */ + +#ifndef __SP_WIFI_ADDR4_H__ +#define __SP_WIFI_ADDR4_H__ + +void SetupWifiAddr4(); + +#endif /* __SP_WIFI_ADDR4_H__ */ Index: snort/src/detection-plugins/sp_wifi_bssid.c diff -u /dev/null snort/src/detection-plugins/sp_wifi_bssid.c:1.6 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_bssid.c Sun Aug 24 02:45:32 2003 @@ -0,0 +1,290 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_bssid.c,v 1.6 2003/08/24 06:45:32 andrew Exp $ */ + +/* sp_wifi_bssid + * + * Purpose: + * + * Tests 802.11 frames BSSID. + * + * Arguments: + * + * {{ '!' | {} } } + * + * Effect: + * + * Success on BSSID match, failure otherwise. + * + */ + +#include +#include +#include +#include + +#include "rules.h" +#include "decode.h" +#include "plugbase.h" +#include "parser.h" +#include "debug.h" +#include "util.h" +#include "plugin_enum.h" + +#include "wifi_datatypes.h" + +/* don't forget to include the name of this file in plugbase.h! */ + +extern char *file_name; /* this is the file name from rules.c, generally used + for error messages */ + +extern int file_line; /* this is the file line number from rules.c that is + used to indicate file lines for error messages */ + +typedef struct _WifiBssidData +{ + u_int8_t bssid[6]; + u_int8_t not_flag; +} WifiBssidData; + +void WifiBssidInit(char *, OptTreeNode *, int); +void WifiBssidRuleParseFunction(char *, OptTreeNode *); +int WifiBssidDetectorFunction(Packet *, struct _OptTreeNode *, OptFpList *); + +/**************************************************************************** + * + * Function: SetupWifiBssid() + * + * Purpose: Generic detection engine plugin template. Registers the + * configuration function and links it to a rule keyword. This is + * the function that gets called from InitPlugins in plugbase.c. + * + * Arguments: None. + * + * Returns: void function + * + ****************************************************************************/ +void SetupWifiBssid() +{ + /* map the keyword to an initialization/processing function */ + RegisterPlugin("bssid", WifiBssidInit); + + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Plugin: WifiBssid Setup\n");); +} + + +/**************************************************************************** + * + * Function: WifiBssidInit(char *, OptTreeNode *) + * + * Purpose: Generic rule configuration function. Handles parsing the rule + * information and attaching the associated detection function to + * the OTN. + * + * Arguments: data => rule arguments/data + * otn => pointer to the current rule option list node + * + * Returns: void function + * + ****************************************************************************/ +void WifiBssidInit(char *data, OptTreeNode *otn, int protocol) +{ + /* allocate the data structure and attach it to the + rule's data struct list */ + otn->ds_list[PLUGIN_WIFI_BSSID_CHECK] = (WifiBssidData *) calloc(sizeof(WifiBssidData), sizeof(char)); + + /* be sure to check that the protocol that is passed in matches the + transport layer protocol that you're using for this rule! */ + + /* this is where the keyword arguments are processed and placed into the + rule option's data structure */ + WifiBssidRuleParseFunction(data, otn); + + /* finally, attach the option's detection function to the rule's + detect function pointer list */ + AddOptFuncToList(WifiBssidDetectorFunction, otn); +} + + + +/**************************************************************************** + * + * Function: WifiBssidRuleParseFunction(char *, OptTreeNode *) + * + * Purpose: This is the function that is used to process the option keyword's + * arguments and attach them to the rule's data structures. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: void function + * + ****************************************************************************/ +void WifiBssidRuleParseFunction(char *data, OptTreeNode *otn) +{ + WifiBssidData *ds_ptr; /* data struct pointer */ + + /* set the ds pointer to make it easier to reference the option's + particular data struct */ + ds_ptr = otn->ds_list[PLUGIN_WIFI_BSSID_CHECK]; + + /* manipulate the option arguments here */ + while(isspace((int) *data)) data++; + + if(*data == '!'){ + ds_ptr->not_flag = 1; + data++; + } + + /* set the final option arguments here */ + + if(WifiBssidParseBSSID(ds_ptr->bssid, data) < 0) + FatalError("%s (%d) => Error parsing BSSID \"%s\"\n", file_name, file_line, data); +} + + + +/* + * Function: WifiBssidParseBSSID(u_int8_t *, char *) + * + * Purpose: Parses BSSIDs from a character string and stores them + * in a byte array. + * + * Arguments: bssid => pointer to byte array to store parsed BSSID in + * mac_str => character string containing BSSID + * + * Returns: 0 on success, -1 on error + * + */ + +int WifiBssidParseBSSID(u_int8_t *bssid, char *mac_str){ + + u_int64_t mac; + + if(strlen(mac_str) != 14) + return -1; + + mac = strtoll(mac_str, NULL, 16); + if(mac < 0 || mac > 0xffffffffffff) + return -1; + + bssid[0] = mac >> 40 & 0x00ff; + bssid[1] = mac >> 32 & 0x00ff; + bssid[2] = mac >> 24 & 0x00ff; + bssid[3] = mac >> 16 & 0x00ff; + bssid[4] = mac >> 8 & 0x00ff; + bssid[5] = mac & 0x00ff; + + return 0; +} + + + +/**************************************************************************** + * + * Function: WifiBssidDetectorFunction(char *, OptTreeNode *) + * + * Purpose: Use this function to perform the particular detection routine + * that this rule keyword is supposed to encompass. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: If the detection test fails, this function *must* return a zero! + * On success, it calls the next function in the detection list + * + ****************************************************************************/ +int WifiBssidDetectorFunction(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list) +{ + + WifiBssidData *plugin_data; + u_int8_t *bssid; + plugin_data = otn->ds_list[PLUGIN_WIFI_BSSID_CHECK]; + + if(!p->wifih){ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Not a WIFI frame\n");); + return 0; + } + + switch(p->wifih->type){ /* point bssid to the correct field in the frame */ + + case TYPE_MANAGEMENT: + bssid = p->wifih->addr3; + break; + + case TYPE_CONTROL: + if(p->wifih->stype == STYPE_RTS || p->wifih->stype == STYPE_CTS || p->wifih->stype == STYPE_ACK){ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Received Control frame subtype that does not contain BSSID\n");); + return 0; + } + else if(p->wifih->stype == STYPE_PS) + bssid = p->wifih->addr1; + else if(p->wifih->stype == STYPE_CFEND) + bssid = p->wifih->addr2; + else if(p->wifih->stype == STYPE_CFEND_CFACK) + bssid = p->wifih->addr2; + else{ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Received Control frame with unknown/invalid subtype\n");); + return 0; + } + break; + + case TYPE_DATA: + if(p->wifih->to_ds){ + if(p->wifih->from_ds){ /* to_ds == 1 && from_ds == 1 */ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Received Data frame subtype that does not contain BSSID\n");); + return 0; + } + else /* to_ds == 1 && from_ds == 0 */ + bssid = p->wifih->addr1; + } + else{ + if(p->wifih->from_ds) /* to_ds == 0 && from_ds == 1 */ + bssid = p->wifih->addr2; + else /* to_ds == 0 && from_ds == 0 */ + bssid = p->wifih->addr3; + } + break; + + default: + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Received frame with unknown/invalid type\n");); + return 0; + } + + + /* your detection function tests go here */ + if((plugin_data->not_flag && (memcmp(bssid, plugin_data->bssid, 6) != 0)) || + (!plugin_data->not_flag && (memcmp(bssid, plugin_data->bssid, 6) == 0))) + { + return fp_list->next->OptTestFunc(p, otn, fp_list->next); + } +#ifdef DEBUG + else + { + /* you can put debug comments here or not */ + DebugMessage(DEBUG_PLUGIN,"No match\n"); + } +#endif + + /* if the test isn't successful, this function *must* return 0 */ + return 0; +} + + + Index: snort/src/detection-plugins/sp_wifi_bssid.h diff -u /dev/null snort/src/detection-plugins/sp_wifi_bssid.h:1.1 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_bssid.h Thu Jul 24 02:20:23 2003 @@ -0,0 +1,26 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_bssid.h,v 1.1 2003/07/24 06:20:23 andrew Exp $ */ + +#ifndef __SP_WIFI_BSSID_H__ +#define __SP_WIFI_BSSID_H__ + +void SetupWifiBssid(); + +#endif /* __SP_WIFI_BSSID_H__ */ Index: snort/src/detection-plugins/sp_wifi_duration_id.c diff -u /dev/null snort/src/detection-plugins/sp_wifi_duration_id.c:1.3 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_duration_id.c Sat Jul 26 21:29:22 2003 @@ -0,0 +1,220 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_duration_id.c,v 1.3 2003/07/27 01:29:22 andrew Exp $ */ + +/* sp_wifi_duration_id + * + * Purpose: + * + * Tests 802.11 frames duration_id field. + * + * Arguments: + * + * {{ '!' | {} } { 0 <= n <= 65535 } } + * + * Effect: + * + * Success on duration_id field match, failure otherwise. + * + */ + +#include +#include +#include +#include + +#include "rules.h" +#include "decode.h" +#include "plugbase.h" +#include "parser.h" +#include "debug.h" +#include "util.h" +#include "plugin_enum.h" + +#include "wifi_datatypes.h" + +/* don't forget to include the name of this file in plugbase.h! */ + +extern char *file_name; /* this is the file name from rules.c, generally used + for error messages */ + +extern int file_line; /* this is the file line number from rules.c that is + used to indicate file lines for error messages */ + +typedef struct _WifiDurationIdData +{ + u_int16_t duration_id; + u_int8_t not_flag; +} WifiDurationIdData; + +void WifiDurationIdInit(char *, OptTreeNode *, int); +void WifiDurationIdRuleParseFunction(char *, OptTreeNode *); +int WifiDurationIdDetectorFunction(Packet *, struct _OptTreeNode *, OptFpList *); + +/**************************************************************************** + * + * Function: SetupWifiDurationId() + * + * Purpose: Generic detection engine plugin template. Registers the + * configuration function and links it to a rule keyword. This is + * the function that gets called from InitPlugins in plugbase.c. + * + * Arguments: None. + * + * Returns: void function + * + ****************************************************************************/ +void SetupWifiDurationId() +{ + /* map the keyword to an initialization/processing function */ + RegisterPlugin("duration_id", WifiDurationIdInit); + + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Plugin: WifiDurationId Setup\n");); +} + + +/**************************************************************************** + * + * Function: WifiDurationIdInit(char *, OptTreeNode *) + * + * Purpose: Generic rule configuration function. Handles parsing the rule + * information and attaching the associated detection function to + * the OTN. + * + * Arguments: data => rule arguments/data + * otn => pointer to the current rule option list node + * + * Returns: void function + * + ****************************************************************************/ +void WifiDurationIdInit(char *data, OptTreeNode *otn, int protocol) +{ + /* allocate the data structure and attach it to the + rule's data struct list */ + otn->ds_list[PLUGIN_WIFI_DURATION_ID_CHECK] = (WifiDurationIdData *) calloc(sizeof(WifiDurationIdData), sizeof(char)); + + /* be sure to check that the protocol that is passed in matches the + transport layer protocol that you're using for this rule! */ + + /* this is where the keyword arguments are processed and placed into the + rule option's data structure */ + WifiDurationIdRuleParseFunction(data, otn); + + /* finally, attach the option's detection function to the rule's + detect function pointer list */ + AddOptFuncToList(WifiDurationIdDetectorFunction, otn); +} + + + +/**************************************************************************** + * + * Function: WifiDurationIdRuleParseFunction(char *, OptTreeNode *) + * + * Purpose: This is the function that is used to process the option keyword's + * arguments and attach them to the rule's data structures. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: void function + * + ****************************************************************************/ +void WifiDurationIdRuleParseFunction(char *data, OptTreeNode *otn) +{ + WifiDurationIdData *ds_ptr; /* data struct pointer */ + unsigned long val = 1 << 16; + + /* set the ds pointer to make it easier to reference the option's + particular data struct */ + ds_ptr = otn->ds_list[PLUGIN_WIFI_DURATION_ID_CHECK]; + + /* manipulate the option arguments here */ + while(isspace((int) *data)) data++; + + if(*data == '!'){ + ds_ptr->not_flag = 1; + data++; + } + + /* set the final option arguments here */ + + if(*data){ + if(strncmp(data, "0x", 2) == 0) + val = strtoul(data, NULL, 16); /* use strtoul so people don't have to do + sign-extended 2's complement hex*/ + else + val = strtol(data, NULL, 10); + } + + if(val < 0 || val > 65535) + FatalError("%s(%d) => duration_id value out of range \"%s\"\n", + file_name, file_line, data); + + ds_ptr->duration_id = val; +} + + +/**************************************************************************** + * + * Function: WifiDurationIdDetectorFunction(char *, OptTreeNode *) + * + * Purpose: Use this function to perform the particular detection routine + * that this rule keyword is supposed to encompass. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: If the detection test fails, this function *must* return a zero! + * On success, it calls the next function in the detection list + * + ****************************************************************************/ +int WifiDurationIdDetectorFunction(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list) +{ + + WifiDurationIdData *plugin_data; + plugin_data = otn->ds_list[PLUGIN_WIFI_DURATION_ID_CHECK]; + + if(!p->wifih){ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Not a WIFI frame\n");); + return 0; + } + + if(p->wifih->type == TYPE_CONTROL && p->wifih->stype == STYPE_PS){ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "duration_id field not present\n");); + return 0; + } + + /* your detection function tests go here */ + if((plugin_data->not_flag && (p->wifih->duration_id != plugin_data->duration_id)) || + (!plugin_data->not_flag && (p->wifih->duration_id == plugin_data->duration_id))) + { + return fp_list->next->OptTestFunc(p, otn, fp_list->next); + } +#ifdef DEBUG + else + { + /* you can put debug comments here or not */ + DebugMessage(DEBUG_PLUGIN,"No match\n"); + } +#endif + + /* if the test isn't successful, this function *must* return 0 */ + return 0; +} Index: snort/src/detection-plugins/sp_wifi_duration_id.h diff -u /dev/null snort/src/detection-plugins/sp_wifi_duration_id.h:1.1 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_duration_id.h Thu Jul 24 02:20:23 2003 @@ -0,0 +1,26 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_duration_id.h,v 1.1 2003/07/24 06:20:23 andrew Exp $ */ + +#ifndef __SP_WIFI_DURATION_ID_H__ +#define __SP_WIFI_DURATION_ID_H__ + +void SetupWifiDurationId(); + +#endif /* __SP_WIFI_DURATION_ID_H__ */ Index: snort/src/detection-plugins/sp_wifi_fragnum.c diff -u /dev/null snort/src/detection-plugins/sp_wifi_fragnum.c:1.3 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_fragnum.c Sat Jul 26 21:32:50 2003 @@ -0,0 +1,222 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_fragnum.c,v 1.3 2003/07/27 01:32:50 andrew Exp $ */ + +/* sp_wifi_fragnum + * + * Purpose: + * + * Tests 802.11 frames fragnum control field. + * + * Arguments: + * + * {{ '!' | {} } { 0 <= n <= 15 } } + * + * n may be specified in either hex or decimal + * + * Effect: + * + * Success on fragnum control field match, failure otherwise. + * + */ + +#include +#include +#include +#include + +#include "rules.h" +#include "decode.h" +#include "plugbase.h" +#include "parser.h" +#include "debug.h" +#include "util.h" +#include "plugin_enum.h" + +#include "wifi_datatypes.h" + +/* don't forget to include the name of this file in plugbase.h! */ + +extern char *file_name; /* this is the file name from rules.c, generally used + for error messages */ + +extern int file_line; /* this is the file line number from rules.c that is + used to indicate file lines for error messages */ + +typedef struct _WifiFragNumData +{ + u_int16_t fragnum; + u_int8_t not_flag; +} WifiFragNumData; + +void WifiFragNumInit(char *, OptTreeNode *, int); +void WifiFragNumRuleParseFunction(char *, OptTreeNode *); +int WifiFragNumDetectorFunction(Packet *, struct _OptTreeNode *, OptFpList *); + +/**************************************************************************** + * + * Function: SetupWifiFragNum() + * + * Purpose: Generic detection engine plugin template. Registers the + * configuration function and links it to a rule keyword. This is + * the function that gets called from InitPlugins in plugbase.c. + * + * Arguments: None. + * + * Returns: void function + * + ****************************************************************************/ +void SetupWifiFragNum() +{ + /* map the keyword to an initialization/processing function */ + RegisterPlugin("fragnum", WifiFragNumInit); + + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Plugin: WifiFragNum Setup\n");); +} + + +/**************************************************************************** + * + * Function: WifiFragNumInit(char *, OptTreeNode *) + * + * Purpose: Generic rule configuration function. Handles parsing the rule + * information and attaching the associated detection function to + * the OTN. + * + * Arguments: data => rule arguments/data + * otn => pointer to the current rule option list node + * + * Returns: void function + * + ****************************************************************************/ +void WifiFragNumInit(char *data, OptTreeNode *otn, int protocol) +{ + /* allocate the data structure and attach it to the + rule's data struct list */ + otn->ds_list[PLUGIN_WIFI_FRAGNUM_CHECK] = (WifiFragNumData *) calloc(sizeof(WifiFragNumData), sizeof(char)); + + /* be sure to check that the protocol that is passed in matches the + transport layer protocol that you're using for this rule! */ + + /* this is where the keyword arguments are processed and placed into the + rule option's data structure */ + WifiFragNumRuleParseFunction(data, otn); + + /* finally, attach the option's detection function to the rule's + detect function pointer list */ + AddOptFuncToList(WifiFragNumDetectorFunction, otn); +} + + + +/**************************************************************************** + * + * Function: WifiFragNumRuleParseFunction(char *, OptTreeNode *) + * + * Purpose: This is the function that is used to process the option keyword's + * arguments and attach them to the rule's data structures. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: void function + * + ****************************************************************************/ +void WifiFragNumRuleParseFunction(char *data, OptTreeNode *otn) +{ + WifiFragNumData *ds_ptr; /* data struct pointer */ + unsigned long val = 1 << 4; + + /* set the ds pointer to make it easier to reference the option's + particular data struct */ + ds_ptr = otn->ds_list[PLUGIN_WIFI_FRAGNUM_CHECK]; + + /* manipulate the option arguments here */ + while(isspace((int) *data)) data++; + + if(*data == '!'){ + ds_ptr->not_flag = 1; + data++; + } + + /* set the final option arguments here */ + + if(*data){ + if(strncmp(data, "0x", 2) == 0) + val = strtoul(data, NULL, 16); /* use strtoul so people don't have to do + sign-extended 2's complement hex*/ + else + val = strtol(data, NULL, 10); + } + + if(val < 0 || val > 15) + FatalError("%s(%d) => fragnum value out of range \"%s\"\n", + file_name, file_line, data); + + ds_ptr->fragnum = val; +} + + +/**************************************************************************** + * + * Function: WifiFragNumDetectorFunction(char *, OptTreeNode *) + * + * Purpose: Use this function to perform the particular detection routine + * that this rule keyword is supposed to encompass. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: If the detection test fails, this function *must* return a zero! + * On success, it calls the next function in the detection list + * + ****************************************************************************/ +int WifiFragNumDetectorFunction(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list) +{ + + WifiFragNumData *plugin_data; + plugin_data = otn->ds_list[PLUGIN_WIFI_FRAGNUM_CHECK]; + + if(!p->wifih){ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Not a WIFI frame\n");); + return 0; + } + + if(p->wifih->type == TYPE_CONTROL){ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Frame is TYPE_CONTROL\n");); + return 0; + } + + /* your detection function tests go here */ + if((plugin_data->not_flag && (p->wifih->fragnum != plugin_data->fragnum)) || + (!plugin_data->not_flag && (p->wifih->fragnum == plugin_data->fragnum))) + { + return fp_list->next->OptTestFunc(p, otn, fp_list->next); + } +#ifdef DEBUG + else + { + /* you can put debug comments here or not */ + DebugMessage(DEBUG_PLUGIN,"No match\n"); + } +#endif + + /* if the test isn't successful, this function *must* return 0 */ + return 0; +} Index: snort/src/detection-plugins/sp_wifi_fragnum.h diff -u /dev/null snort/src/detection-plugins/sp_wifi_fragnum.h:1.1 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_fragnum.h Fri Jul 25 06:02:56 2003 @@ -0,0 +1,26 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_fragnum.h,v 1.1 2003/07/25 10:02:56 andrew Exp $ */ + +#ifndef __SP_WIFI_FRAGNUM_H__ +#define __SP_WIFI_FRAGNUM_H__ + +void SetupWifiFragNum(); + +#endif /* __SP_WIFI_FRAGNUM_H__ */ Index: snort/src/detection-plugins/sp_wifi_frame_control.c diff -u /dev/null snort/src/detection-plugins/sp_wifi_frame_control.c:1.4 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_frame_control.c Sat Jul 26 21:32:50 2003 @@ -0,0 +1,215 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_frame_control.c,v 1.4 2003/07/27 01:32:50 andrew Exp $ */ + +/* sp_wifi_frame_control + * + * Purpose: + * + * Tests 802.11 frames frame_control field. + * + * Arguments: + * + * {{ '!' | {} } { 0 <= n <= 65535 } } + * + * n may be specified in either hex or decimal + * + * Effect: + * + * Success on frame_control field match, failure otherwise. + * + */ + +#include +#include +#include + +#include "rules.h" +#include "decode.h" +#include "plugbase.h" +#include "parser.h" +#include "debug.h" +#include "util.h" +#include "plugin_enum.h" + + +/* don't forget to include the name of this file in plugbase.h! */ + +extern char *file_name; /* this is the file name from rules.c, generally used + for error messages */ + +extern int file_line; /* this is the file line number from rules.c that is + used to indicate file lines for error messages */ + +typedef struct _WifiFrameControlData +{ + u_int16_t frame_control; + u_int8_t not_flag; +} WifiFrameControlData; + +void WifiFrameControlInit(char *, OptTreeNode *, int); +void WifiFrameControlRuleParseFunction(char *, OptTreeNode *); +int WifiFrameControlDetectorFunction(Packet *, struct _OptTreeNode *, OptFpList *); + +/**************************************************************************** + * + * Function: SetupWifiFrameControl() + * + * Purpose: Generic detection engine plugin template. Registers the + * configuration function and links it to a rule keyword. This is + * the function that gets called from InitPlugins in plugbase.c. + * + * Arguments: None. + * + * Returns: void function + * + ****************************************************************************/ +void SetupWifiFrameControl() +{ + /* map the keyword to an initialization/processing function */ + RegisterPlugin("frame_control", WifiFrameControlInit); + + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Plugin: WifiFrameControl Setup\n");); +} + + +/**************************************************************************** + * + * Function: WifiFrameControlInit(char *, OptTreeNode *) + * + * Purpose: Generic rule configuration function. Handles parsing the rule + * information and attaching the associated detection function to + * the OTN. + * + * Arguments: data => rule arguments/data + * otn => pointer to the current rule option list node + * + * Returns: void function + * + ****************************************************************************/ +void WifiFrameControlInit(char *data, OptTreeNode *otn, int protocol) +{ + /* allocate the data structure and attach it to the + rule's data struct list */ + otn->ds_list[PLUGIN_WIFI_FRAME_CONTROL_CHECK] = (WifiFrameControlData *) calloc(sizeof(WifiFrameControlData), sizeof(char)); + + /* be sure to check that the protocol that is passed in matches the + transport layer protocol that you're using for this rule! */ + + /* this is where the keyword arguments are processed and placed into the + rule option's data structure */ + WifiFrameControlRuleParseFunction(data, otn); + + /* finally, attach the option's detection function to the rule's + detect function pointer list */ + AddOptFuncToList(WifiFrameControlDetectorFunction, otn); +} + + + +/**************************************************************************** + * + * Function: WifiFrameControlRuleParseFunction(char *, OptTreeNode *) + * + * Purpose: This is the function that is used to process the option keyword's + * arguments and attach them to the rule's data structures. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: void function + * + ****************************************************************************/ +void WifiFrameControlRuleParseFunction(char *data, OptTreeNode *otn) +{ + WifiFrameControlData *ds_ptr; /* data struct pointer */ + unsigned long val = 1 << 16; + + /* set the ds pointer to make it easier to reference the option's + particular data struct */ + ds_ptr = otn->ds_list[PLUGIN_WIFI_FRAME_CONTROL_CHECK]; + + /* manipulate the option arguments here */ + while(isspace((int) *data)) data++; + + if(*data == '!'){ + ds_ptr->not_flag = 1; + data++; + } + + /* set the final option arguments here */ + + if(*data) + if(strncmp(data, "0x", 2) == 0) + val = strtoul(data, NULL, 16); /* use strtoul so people don't have to do + sign-extended 2's complement hex*/ + else + val = strtol(data, NULL, 10); + + + if(val < 0 || val > 65535) + FatalError("%s(%d) => frame_control value out of range \"%s\"\n", + file_name, file_line, data); + + ds_ptr->frame_control = val; +} + + +/**************************************************************************** + * + * Function: WifiFrameControlDetectorFunction(char *, OptTreeNode *) + * + * Purpose: Use this function to perform the particular detection routine + * that this rule keyword is supposed to encompass. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: If the detection test fails, this function *must* return a zero! + * On success, it calls the next function in the detection list + * + ****************************************************************************/ +int WifiFrameControlDetectorFunction(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list) +{ + + WifiFrameControlData *plugin_data; + plugin_data = otn->ds_list[PLUGIN_WIFI_FRAME_CONTROL_CHECK]; + + if(!p->wifih){ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Not a WIFI frame\n");); + return 0; + } + + /* your detection function tests go here */ + if((plugin_data->not_flag && (p->wifih->frame_control != plugin_data->frame_control)) || + (!plugin_data->not_flag && (p->wifih->frame_control == plugin_data->frame_control))) + { + return fp_list->next->OptTestFunc(p, otn, fp_list->next); + } +#ifdef DEBUG + else + { + /* you can put debug comments here or not */ + DebugMessage(DEBUG_PLUGIN,"No match\n"); + } +#endif + + /* if the test isn't successful, this function *must* return 0 */ + return 0; +} Index: snort/src/detection-plugins/sp_wifi_frame_control.h diff -u /dev/null snort/src/detection-plugins/sp_wifi_frame_control.h:1.1 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_frame_control.h Thu Jul 24 02:33:56 2003 @@ -0,0 +1,26 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_frame_control.h,v 1.1 2003/07/24 06:33:56 andrew Exp $ */ + +#ifndef __SP_WIFI_FRAME_CONTROL_H__ +#define __SP_WIFI_FRAME_CONTROL_H__ + +void SetupWifiFrameControl(); + +#endif /* __SP_WIFI_FRAME_CONTROL_H__ */ Index: snort/src/detection-plugins/sp_wifi_from_ds.c diff -u /dev/null snort/src/detection-plugins/sp_wifi_from_ds.c:1.2 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_from_ds.c Fri Jul 25 05:13:46 2003 @@ -0,0 +1,218 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_from_ds.c,v 1.2 2003/07/25 09:13:46 andrew Exp $ */ + +/* sp_wifi_from_ds + * + * Purpose: + * + * Tests 802.11 frames from_ds control field. + * + * Arguments: + * + * {{ '!' | {} } { ON | OFF | TRUE | FALSE } } + * + * Effect: + * + * Success on from_ds match, failure otherwise. + * + */ + +#include +#include +#include + +#include "rules.h" +#include "decode.h" +#include "plugbase.h" +#include "parser.h" +#include "debug.h" +#include "util.h" +#include "plugin_enum.h" + + +/* don't forget to include the name of this file in plugbase.h! */ + +extern char *file_name; /* this is the file name from rules.c, generally used + for error messages */ + +extern int file_line; /* this is the file line number from rules.c that is + used to indicate file lines for error messages */ + +typedef struct _WifiFromDsData +{ + int val; +} WifiFromDsData; + +void WifiFromDsInit(char *, OptTreeNode *, int); +void WifiFromDsRuleParseFunction(char *, OptTreeNode *); +int WifiFromDsDetectorFunction(Packet *, struct _OptTreeNode *, OptFpList *); + +/**************************************************************************** + * + * Function: SetupWifiFromDs() + * + * Purpose: Generic detection engine plugin template. Registers the + * configuration function and links it to a rule keyword. This is + * the function that gets called from InitPlugins in plugbase.c. + * + * Arguments: None. + * + * Returns: void function + * + ****************************************************************************/ +void SetupWifiFromDs() +{ + /* map the keyword to an initialization/processing function */ + RegisterPlugin("from_ds", WifiFromDsInit); + + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Plugin: WifiFromDs Setup\n");); +} + + +/**************************************************************************** + * + * Function: WifiFromDsInit(char *, OptTreeNode *) + * + * Purpose: Generic rule configuration function. Handles parsing the rule + * information and attaching the associated detection function to + * the OTN. + * + * Arguments: data => rule arguments/data + * otn => pointer to the current rule option list node + * + * Returns: void function + * + ****************************************************************************/ +void WifiFromDsInit(char *data, OptTreeNode *otn, int protocol) +{ + /* allocate the data structure and attach it to the + rule's data struct list */ + otn->ds_list[PLUGIN_WIFI_FROM_DS_CHECK] = (WifiFromDsData *) calloc(sizeof(WifiFromDsData), sizeof(char)); + + /* be sure to check that the protocol that is passed in matches the + transport layer protocol that you're using for this rule! */ + + /* this is where the keyword arguments are processed and placed into the + rule option's data structure */ + WifiFromDsRuleParseFunction(data, otn); + + /* finally, attach the option's detection function to the rule's + detect function pointer list */ + AddOptFuncToList(WifiFromDsDetectorFunction, otn); +} + + + +/**************************************************************************** + * + * Function: WifiFromDsRuleParseFunction(char *, OptTreeNode *) + * + * Purpose: This is the function that is used to process the option keyword's + * arguments and attach them to the rule's data structures. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: void function + * + ****************************************************************************/ +void WifiFromDsRuleParseFunction(char *data, OptTreeNode *otn) +{ + WifiFromDsData *ds_ptr; /* data struct pointer */ + int not_flag = 0; + + /* set the ds pointer to make it easier to reference the option's + particular data struct */ + ds_ptr = otn->ds_list[PLUGIN_WIFI_FROM_DS_CHECK]; + + /* manipulate the option arguments here */ + while(isspace((int) *data)) data++; + + if(*data == '!'){ + not_flag = 1; + data++; + } + + /* set the final option arguments here */ + if(strcmp(data, "FALSE") == 0) + ds_ptr->val = 0; + else if(strcmp(data, "OFF") == 0) + ds_ptr->val = 0; + else if(strcmp(data, "NO") == 0) + ds_ptr->val = 0; + + else if(strcmp(data, "TRUE") == 0) + ds_ptr->val = 1; + else if(strcmp(data, "ON") == 0) + ds_ptr->val = 1; + else if(strcmp(data, "YES") == 0) + ds_ptr->val = 1; + + else + FatalError("%s(%d) => Bad from_ds flag value \"%s\"\n", + file_name, file_line, data); + + if(not_flag) + ds_ptr->val = (ds_ptr->val) ? 0 : 1; + +} + + +/**************************************************************************** + * + * Function: WifiFromDsDetectorFunction(char *, OptTreeNode *) + * + * Purpose: Use this function to perform the particular detection routine + * that this rule keyword is supposed to encompass. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: If the detection test fails, this function *must* return a zero! + * On success, it calls the next function in the detection list + * + ****************************************************************************/ +int WifiFromDsDetectorFunction(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list) +{ + + WifiFromDsData *plugin_data; + plugin_data = otn->ds_list[PLUGIN_WIFI_FROM_DS_CHECK]; + + if(!p->wifih){ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Not a WIFI frame\n");); + return 0; + } + + /* your detection function tests go here */ + if (p->wifih->from_ds == plugin_data->val) + { + return fp_list->next->OptTestFunc(p, otn, fp_list->next); + } +#ifdef DEBUG + else + { + /* you can put debug comments here or not */ + DebugMessage(DEBUG_PLUGIN,"No match\n"); + } +#endif + + /* if the test isn't successful, this function *must* return 0 */ + return 0; +} Index: snort/src/detection-plugins/sp_wifi_from_ds.h diff -u /dev/null snort/src/detection-plugins/sp_wifi_from_ds.h:1.1 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_from_ds.h Thu Jul 24 02:20:23 2003 @@ -0,0 +1,26 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_from_ds.h,v 1.1 2003/07/24 06:20:23 andrew Exp $ */ + +#ifndef __SP_WIFI_FROM_DS_H__ +#define __SP_WIFI_FROM_DS_H__ + +void SetupWifiFromDs(); + +#endif /* __SP_WIFI_FROM_DS_H__ */ Index: snort/src/detection-plugins/sp_wifi_more_data.c diff -u /dev/null snort/src/detection-plugins/sp_wifi_more_data.c:1.2 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_more_data.c Fri Jul 25 05:12:40 2003 @@ -0,0 +1,218 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_more_data.c,v 1.2 2003/07/25 09:12:40 andrew Exp $ */ + +/* sp_wifi_more_data + * + * Purpose: + * + * Tests 802.11 frames more_data control field. + * + * Arguments: + * + * {{ '!' | {} } { ON | OFF | TRUE | FALSE } } + * + * Effect: + * + * Success on more_data flag match, failure otherwise. + * + */ + +#include +#include +#include + +#include "rules.h" +#include "decode.h" +#include "plugbase.h" +#include "parser.h" +#include "debug.h" +#include "util.h" +#include "plugin_enum.h" + + +/* don't forget to include the name of this file in plugbase.h! */ + +extern char *file_name; /* this is the file name from rules.c, generally used + for error messages */ + +extern int file_line; /* this is the file line number from rules.c that is + used to indicate file lines for error messages */ + +typedef struct _WifiMoreDataData +{ + int val; +} WifiMoreDataData; + +void WifiMoreDataInit(char *, OptTreeNode *, int); +void WifiMoreDataRuleParseFunction(char *, OptTreeNode *); +int WifiMoreDataDetectorFunction(Packet *, struct _OptTreeNode *, OptFpList *); + +/**************************************************************************** + * + * Function: SetupWifiMoreData() + * + * Purpose: Generic detection engine plugin template. Registers the + * configuration function and links it to a rule keyword. This is + * the function that gets called from InitPlugins in plugbase.c. + * + * Arguments: None. + * + * Returns: void function + * + ****************************************************************************/ +void SetupWifiMoreData() +{ + /* map the keyword to an initialization/processing function */ + RegisterPlugin("more_data", WifiMoreDataInit); + + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Plugin: WifiMoreData Setup\n");); +} + + +/**************************************************************************** + * + * Function: WifiMoreDataInit(char *, OptTreeNode *) + * + * Purpose: Generic rule configuration function. Handles parsing the rule + * information and attaching the associated detection function to + * the OTN. + * + * Arguments: data => rule arguments/data + * otn => pointer to the current rule option list node + * + * Returns: void function + * + ****************************************************************************/ +void WifiMoreDataInit(char *data, OptTreeNode *otn, int protocol) +{ + /* allocate the data structure and attach it to the + rule's data struct list */ + otn->ds_list[PLUGIN_WIFI_MORE_DATA_CHECK] = (WifiMoreDataData *) calloc(sizeof(WifiMoreDataData), sizeof(char)); + + /* be sure to check that the protocol that is passed in matches the + transport layer protocol that you're using for this rule! */ + + /* this is where the keyword arguments are processed and placed into the + rule option's data structure */ + WifiMoreDataRuleParseFunction(data, otn); + + /* finally, attach the option's detection function to the rule's + detect function pointer list */ + AddOptFuncToList(WifiMoreDataDetectorFunction, otn); +} + + + +/**************************************************************************** + * + * Function: WifiMoreDataRuleParseFunction(char *, OptTreeNode *) + * + * Purpose: This is the function that is used to process the option keyword's + * arguments and attach them to the rule's data structures. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: void function + * + ****************************************************************************/ +void WifiMoreDataRuleParseFunction(char *data, OptTreeNode *otn) +{ + WifiMoreDataData *ds_ptr; /* data struct pointer */ + int not_flag = 0; + + /* set the ds pointer to make it easier to reference the option's + particular data struct */ + ds_ptr = otn->ds_list[PLUGIN_WIFI_MORE_DATA_CHECK]; + + /* manipulate the option arguments here */ + while(isspace((int) *data)) data++; + + if(*data == '!'){ + not_flag = 1; + data++; + } + + /* set the final option arguments here */ + if(strcmp(data, "FALSE") == 0) + ds_ptr->val = 0; + else if(strcmp(data, "OFF") == 0) + ds_ptr->val = 0; + else if(strcmp(data, "NO") == 0) + ds_ptr->val = 0; + + else if(strcmp(data, "TRUE") == 0) + ds_ptr->val = 1; + else if(strcmp(data, "ON") == 0) + ds_ptr->val = 1; + else if(strcmp(data, "YES") == 0) + ds_ptr->val = 1; + + else + FatalError("%s(%d) => Bad more_data flag value \"%s\"\n", + file_name, file_line, data); + + if(not_flag) + ds_ptr->val = (ds_ptr->val) ? 0 : 1; + +} + + +/**************************************************************************** + * + * Function: WifiMoreDataDetectorFunction(char *, OptTreeNode *) + * + * Purpose: Use this function to perform the particular detection routine + * that this rule keyword is supposed to encompass. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: If the detection test fails, this function *must* return a zero! + * On success, it calls the next function in the detection list + * + ****************************************************************************/ +int WifiMoreDataDetectorFunction(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list) +{ + + WifiMoreDataData *plugin_data; + plugin_data = otn->ds_list[PLUGIN_WIFI_MORE_DATA_CHECK]; + + if(!p->wifih){ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Not a WIFI frame\n");); + return 0; + } + + /* your detection function tests go here */ + if (p->wifih->more_data == plugin_data->val) + { + return fp_list->next->OptTestFunc(p, otn, fp_list->next); + } +#ifdef DEBUG + else + { + /* you can put debug comments here or not */ + DebugMessage(DEBUG_PLUGIN,"No match\n"); + } +#endif + + /* if the test isn't successful, this function *must* return 0 */ + return 0; +} Index: snort/src/detection-plugins/sp_wifi_more_data.h diff -u /dev/null snort/src/detection-plugins/sp_wifi_more_data.h:1.1 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_more_data.h Thu Jul 24 02:20:23 2003 @@ -0,0 +1,26 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_more_data.h,v 1.1 2003/07/24 06:20:23 andrew Exp $ */ + +#ifndef __SP_WIFI_MORE_DATA_H__ +#define __SP_WIFI_MORE_DATA_H__ + +void SetupWifiMoreData(); + +#endif /* __SP_WIFI_MORE_DATA_H__ */ Index: snort/src/detection-plugins/sp_wifi_more_frags.c diff -u /dev/null snort/src/detection-plugins/sp_wifi_more_frags.c:1.2 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_more_frags.c Fri Jul 25 05:10:54 2003 @@ -0,0 +1,218 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_more_frags.c,v 1.2 2003/07/25 09:10:54 andrew Exp $ */ + +/* sp_wifi_more_frags + * + * Purpose: + * + * Tests 802.11 frames more_frags control field. + * + * Arguments: + * + * {{ '!' | {} } { ON | OFF | TRUE | FALSE } } + * + * Effect: + * + * Success on more_frags flag match, failure otherwise. + * + */ + +#include +#include +#include + +#include "rules.h" +#include "decode.h" +#include "plugbase.h" +#include "parser.h" +#include "debug.h" +#include "util.h" +#include "plugin_enum.h" + + +/* don't forget to include the name of this file in plugbase.h! */ + +extern char *file_name; /* this is the file name from rules.c, generally used + for error messages */ + +extern int file_line; /* this is the file line number from rules.c that is + used to indicate file lines for error messages */ + +typedef struct _WifiMoreFragsData +{ + int val; +} WifiMoreFragsData; + +void WifiMoreFragsInit(char *, OptTreeNode *, int); +void WifiMoreFragsRuleParseFunction(char *, OptTreeNode *); +int WifiMoreFragsDetectorFunction(Packet *, struct _OptTreeNode *, OptFpList *); + +/**************************************************************************** + * + * Function: SetupWifiMoreFrags() + * + * Purpose: Generic detection engine plugin template. Registers the + * configuration function and links it to a rule keyword. This is + * the function that gets called from InitPlugins in plugbase.c. + * + * Arguments: None. + * + * Returns: void function + * + ****************************************************************************/ +void SetupWifiMoreFrags() +{ + /* map the keyword to an initialization/processing function */ + RegisterPlugin("more_frags", WifiMoreFragsInit); + + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Plugin: WifiMoreFrags Setup\n");); +} + + +/**************************************************************************** + * + * Function: WifiMoreFragsInit(char *, OptTreeNode *) + * + * Purpose: Generic rule configuration function. Handles parsing the rule + * information and attaching the associated detection function to + * the OTN. + * + * Arguments: data => rule arguments/data + * otn => pointer to the current rule option list node + * + * Returns: void function + * + ****************************************************************************/ +void WifiMoreFragsInit(char *data, OptTreeNode *otn, int protocol) +{ + /* allocate the data structure and attach it to the + rule's data struct list */ + otn->ds_list[PLUGIN_WIFI_MORE_FRAGS_CHECK] = (WifiMoreFragsData *) calloc(sizeof(WifiMoreFragsData), sizeof(char)); + + /* be sure to check that the protocol that is passed in matches the + transport layer protocol that you're using for this rule! */ + + /* this is where the keyword arguments are processed and placed into the + rule option's data structure */ + WifiMoreFragsRuleParseFunction(data, otn); + + /* finally, attach the option's detection function to the rule's + detect function pointer list */ + AddOptFuncToList(WifiMoreFragsDetectorFunction, otn); +} + + + +/**************************************************************************** + * + * Function: WifiMoreFragsRuleParseFunction(char *, OptTreeNode *) + * + * Purpose: This is the function that is used to process the option keyword's + * arguments and attach them to the rule's data structures. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: void function + * + ****************************************************************************/ +void WifiMoreFragsRuleParseFunction(char *data, OptTreeNode *otn) +{ + WifiMoreFragsData *ds_ptr; /* data struct pointer */ + int not_flag = 0; + + /* set the ds pointer to make it easier to reference the option's + particular data struct */ + ds_ptr = otn->ds_list[PLUGIN_WIFI_MORE_FRAGS_CHECK]; + + /* manipulate the option arguments here */ + while(isspace((int) *data)) data++; + + if(*data == '!'){ + not_flag = 1; + data++; + } + + /* set the final option arguments here */ + if(strcmp(data, "FALSE") == 0) + ds_ptr->val = 0; + else if(strcmp(data, "OFF") == 0) + ds_ptr->val = 0; + else if(strcmp(data, "NO") == 0) + ds_ptr->val = 0; + + else if(strcmp(data, "TRUE") == 0) + ds_ptr->val = 1; + else if(strcmp(data, "ON") == 0) + ds_ptr->val = 1; + else if(strcmp(data, "YES") == 0) + ds_ptr->val = 1; + + else + FatalError("%s(%d) => Bad more_frags flag value \"%s\"\n", + file_name, file_line, data); + + if(not_flag) + ds_ptr->val = (ds_ptr->val) ? 0 : 1; + +} + + +/**************************************************************************** + * + * Function: WifiMoreFragsDetectorFunction(char *, OptTreeNode *) + * + * Purpose: Use this function to perform the particular detection routine + * that this rule keyword is supposed to encompass. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: If the detection test fails, this function *must* return a zero! + * On success, it calls the next function in the detection list + * + ****************************************************************************/ +int WifiMoreFragsDetectorFunction(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list) +{ + + WifiMoreFragsData *plugin_data; + plugin_data = otn->ds_list[PLUGIN_WIFI_MORE_FRAGS_CHECK]; + + if(!p->wifih){ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Not a WIFI frame\n");); + return 0; + } + + /* your detection function tests go here */ + if (p->wifih->more_frags == plugin_data->val) + { + return fp_list->next->OptTestFunc(p, otn, fp_list->next); + } +#ifdef DEBUG + else + { + /* you can put debug comments here or not */ + DebugMessage(DEBUG_PLUGIN,"No match\n"); + } +#endif + + /* if the test isn't successful, this function *must* return 0 */ + return 0; +} Index: snort/src/detection-plugins/sp_wifi_more_frags.h diff -u /dev/null snort/src/detection-plugins/sp_wifi_more_frags.h:1.1 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_more_frags.h Thu Jul 24 02:20:23 2003 @@ -0,0 +1,26 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_more_frags.h,v 1.1 2003/07/24 06:20:23 andrew Exp $ */ + +#ifndef __SP_WIFI_MORE_FRAGS_H__ +#define __SP_WIFI_MORE_FRAGS_H__ + +void SetupWifiMoreFrags(); + +#endif /* __SP_WIFI_MORE_FRAGS_H__ */ Index: snort/src/detection-plugins/sp_wifi_order.c diff -u /dev/null snort/src/detection-plugins/sp_wifi_order.c:1.2 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_order.c Fri Jul 25 05:09:34 2003 @@ -0,0 +1,218 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_order.c,v 1.2 2003/07/25 09:09:34 andrew Exp $ */ + +/* sp_wifi_order + * + * Purpose: + * + * Tests 802.11 frames order control field. + * + * Arguments: + * + * {{ '!' | {} } { ON | OFF | TRUE | FALSE } } + * + * Effect: + * + * Success on order flag match, failure otherwise. + * + */ + +#include +#include +#include + +#include "rules.h" +#include "decode.h" +#include "plugbase.h" +#include "parser.h" +#include "debug.h" +#include "util.h" +#include "plugin_enum.h" + + +/* don't forget to include the name of this file in plugbase.h! */ + +extern char *file_name; /* this is the file name from rules.c, generally used + for error messages */ + +extern int file_line; /* this is the file line number from rules.c that is + used to indicate file lines for error messages */ + +typedef struct _WifiOrderData +{ + int val; +} WifiOrderData; + +void WifiOrderInit(char *, OptTreeNode *, int); +void WifiOrderRuleParseFunction(char *, OptTreeNode *); +int WifiOrderDetectorFunction(Packet *, struct _OptTreeNode *, OptFpList *); + +/**************************************************************************** + * + * Function: SetupWifiOrder() + * + * Purpose: Generic detection engine plugin template. Registers the + * configuration function and links it to a rule keyword. This is + * the function that gets called from InitPlugins in plugbase.c. + * + * Arguments: None. + * + * Returns: void function + * + ****************************************************************************/ +void SetupWifiOrder() +{ + /* map the keyword to an initialization/processing function */ + RegisterPlugin("order", WifiOrderInit); + + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Plugin: WifiOrder Setup\n");); +} + + +/**************************************************************************** + * + * Function: WifiOrderInit(char *, OptTreeNode *) + * + * Purpose: Generic rule configuration function. Handles parsing the rule + * information and attaching the associated detection function to + * the OTN. + * + * Arguments: data => rule arguments/data + * otn => pointer to the current rule option list node + * + * Returns: void function + * + ****************************************************************************/ +void WifiOrderInit(char *data, OptTreeNode *otn, int protocol) +{ + /* allocate the data structure and attach it to the + rule's data struct list */ + otn->ds_list[PLUGIN_WIFI_ORDER_CHECK] = (WifiOrderData *) calloc(sizeof(WifiOrderData), sizeof(char)); + + /* be sure to check that the protocol that is passed in matches the + transport layer protocol that you're using for this rule! */ + + /* this is where the keyword arguments are processed and placed into the + rule option's data structure */ + WifiOrderRuleParseFunction(data, otn); + + /* finally, attach the option's detection function to the rule's + detect function pointer list */ + AddOptFuncToList(WifiOrderDetectorFunction, otn); +} + + + +/**************************************************************************** + * + * Function: WifiOrderRuleParseFunction(char *, OptTreeNode *) + * + * Purpose: This is the function that is used to process the option keyword's + * arguments and attach them to the rule's data structures. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: void function + * + ****************************************************************************/ +void WifiOrderRuleParseFunction(char *data, OptTreeNode *otn) +{ + WifiOrderData *ds_ptr; /* data struct pointer */ + int not_flag = 0; + + /* set the ds pointer to make it easier to reference the option's + particular data struct */ + ds_ptr = otn->ds_list[PLUGIN_WIFI_ORDER_CHECK]; + + /* manipulate the option arguments here */ + while(isspace((int) *data)) data++; + + if(*data == '!'){ + not_flag = 1; + data++; + } + + /* set the final option arguments here */ + if(strcmp(data, "FALSE") == 0) + ds_ptr->val = 0; + else if(strcmp(data, "OFF") == 0) + ds_ptr->val = 0; + else if(strcmp(data, "NO") == 0) + ds_ptr->val = 0; + + else if(strcmp(data, "TRUE") == 0) + ds_ptr->val = 1; + else if(strcmp(data, "ON") == 0) + ds_ptr->val = 1; + else if(strcmp(data, "YES") == 0) + ds_ptr->val = 1; + + else + FatalError("%s(%d) => Bad order flag value \"%s\"\n", + file_name, file_line, data); + + if(not_flag) + ds_ptr->val = (ds_ptr->val) ? 0 : 1; + +} + + +/**************************************************************************** + * + * Function: WifiOrderDetectorFunction(char *, OptTreeNode *) + * + * Purpose: Use this function to perform the particular detection routine + * that this rule keyword is supposed to encompass. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: If the detection test fails, this function *must* return a zero! + * On success, it calls the next function in the detection list + * + ****************************************************************************/ +int WifiOrderDetectorFunction(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list) +{ + + WifiOrderData *plugin_data; + plugin_data = otn->ds_list[PLUGIN_WIFI_ORDER_CHECK]; + + if(!p->wifih){ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Not a WIFI frame\n");); + return 0; + } + + /* your detection function tests go here */ + if (p->wifih->order == plugin_data->val) + { + return fp_list->next->OptTestFunc(p, otn, fp_list->next); + } +#ifdef DEBUG + else + { + /* you can put debug comments here or not */ + DebugMessage(DEBUG_PLUGIN,"No match\n"); + } +#endif + + /* if the test isn't successful, this function *must* return 0 */ + return 0; +} Index: snort/src/detection-plugins/sp_wifi_order.h diff -u /dev/null snort/src/detection-plugins/sp_wifi_order.h:1.1 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_order.h Thu Jul 24 02:20:23 2003 @@ -0,0 +1,26 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_order.h,v 1.1 2003/07/24 06:20:23 andrew Exp $ */ + +#ifndef __SP_WIFI_ORDER_H__ +#define __SP_WIFI_ORDER_H__ + +void SetupWifiOrder(); + +#endif /* __SP_WIFI_ORDER_H__ */ Index: snort/src/detection-plugins/sp_wifi_pwr_mgmt.c diff -u /dev/null snort/src/detection-plugins/sp_wifi_pwr_mgmt.c:1.2 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_pwr_mgmt.c Fri Jul 25 05:08:23 2003 @@ -0,0 +1,218 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_pwr_mgmt.c,v 1.2 2003/07/25 09:08:23 andrew Exp $ */ + +/* sp_wifi_pwr_mgmt + * + * Purpose: + * + * Tests 802.11 frames pwr_mgmt control field. + * + * Arguments: + * + * {{ '!' | {} } { ON | OFF | TRUE | FALSE } } + * + * Effect: + * + * Success on pwr_mgmt flag match, failure otherwise. + * + */ + +#include +#include +#include + +#include "rules.h" +#include "decode.h" +#include "plugbase.h" +#include "parser.h" +#include "debug.h" +#include "util.h" +#include "plugin_enum.h" + + +/* don't forget to include the name of this file in plugbase.h! */ + +extern char *file_name; /* this is the file name from rules.c, generally used + for error messages */ + +extern int file_line; /* this is the file line number from rules.c that is + used to indicate file lines for error messages */ + +typedef struct _WifiPwrMgmtData +{ + int val; +} WifiPwrMgmtData; + +void WifiPwrMgmtInit(char *, OptTreeNode *, int); +void WifiPwrMgmtRuleParseFunction(char *, OptTreeNode *); +int WifiPwrMgmtDetectorFunction(Packet *, struct _OptTreeNode *, OptFpList *); + +/**************************************************************************** + * + * Function: SetupWifiPwrMgmt() + * + * Purpose: Generic detection engine plugin template. Registers the + * configuration function and links it to a rule keyword. This is + * the function that gets called from InitPlugins in plugbase.c. + * + * Arguments: None. + * + * Returns: void function + * + ****************************************************************************/ +void SetupWifiPwrMgmt() +{ + /* map the keyword to an initialization/processing function */ + RegisterPlugin("pwr_mgmt", WifiPwrMgmtInit); + + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Plugin: WifiPwrMgmt Setup\n");); +} + + +/**************************************************************************** + * + * Function: WifiPwrMgmtInit(char *, OptTreeNode *) + * + * Purpose: Generic rule configuration function. Handles parsing the rule + * information and attaching the associated detection function to + * the OTN. + * + * Arguments: data => rule arguments/data + * otn => pointer to the current rule option list node + * + * Returns: void function + * + ****************************************************************************/ +void WifiPwrMgmtInit(char *data, OptTreeNode *otn, int protocol) +{ + /* allocate the data structure and attach it to the + rule's data struct list */ + otn->ds_list[PLUGIN_WIFI_PWR_MGMT_CHECK] = (WifiPwrMgmtData *) calloc(sizeof(WifiPwrMgmtData), sizeof(char)); + + /* be sure to check that the protocol that is passed in matches the + transport layer protocol that you're using for this rule! */ + + /* this is where the keyword arguments are processed and placed into the + rule option's data structure */ + WifiPwrMgmtRuleParseFunction(data, otn); + + /* finally, attach the option's detection function to the rule's + detect function pointer list */ + AddOptFuncToList(WifiPwrMgmtDetectorFunction, otn); +} + + + +/**************************************************************************** + * + * Function: WifiPwrMgmtRuleParseFunction(char *, OptTreeNode *) + * + * Purpose: This is the function that is used to process the option keyword's + * arguments and attach them to the rule's data structures. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: void function + * + ****************************************************************************/ +void WifiPwrMgmtRuleParseFunction(char *data, OptTreeNode *otn) +{ + WifiPwrMgmtData *ds_ptr; /* data struct pointer */ + int not_flag = 0; + + /* set the ds pointer to make it easier to reference the option's + particular data struct */ + ds_ptr = otn->ds_list[PLUGIN_WIFI_PWR_MGMT_CHECK]; + + /* manipulate the option arguments here */ + while(isspace((int) *data)) data++; + + if(*data == '!'){ + not_flag = 1; + data++; + } + + /* set the final option arguments here */ + if(strcmp(data, "FALSE") == 0) + ds_ptr->val = 0; + else if(strcmp(data, "OFF") == 0) + ds_ptr->val = 0; + else if(strcmp(data, "NO") == 0) + ds_ptr->val = 0; + + else if(strcmp(data, "TRUE") == 0) + ds_ptr->val = 1; + else if(strcmp(data, "ON") == 0) + ds_ptr->val = 1; + else if(strcmp(data, "YES") == 0) + ds_ptr->val = 1; + + else + FatalError("%s(%d) => Bad pwr_mgmt flag value \"%s\"\n", + file_name, file_line, data); + + if(not_flag) + ds_ptr->val = (ds_ptr->val) ? 0 : 1; + +} + + +/**************************************************************************** + * + * Function: WifiPwrMgmtDetectorFunction(char *, OptTreeNode *) + * + * Purpose: Use this function to perform the particular detection routine + * that this rule keyword is supposed to encompass. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: If the detection test fails, this function *must* return a zero! + * On success, it calls the next function in the detection list + * + ****************************************************************************/ +int WifiPwrMgmtDetectorFunction(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list) +{ + + WifiPwrMgmtData *plugin_data; + plugin_data = otn->ds_list[PLUGIN_WIFI_PWR_MGMT_CHECK]; + + if(!p->wifih){ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Not a WIFI frame\n");); + return 0; + } + + /* your detection function tests go here */ + if (p->wifih->pwr_mgmt == plugin_data->val) + { + return fp_list->next->OptTestFunc(p, otn, fp_list->next); + } +#ifdef DEBUG + else + { + /* you can put debug comments here or not */ + DebugMessage(DEBUG_PLUGIN,"No match\n"); + } +#endif + + /* if the test isn't successful, this function *must* return 0 */ + return 0; +} Index: snort/src/detection-plugins/sp_wifi_pwr_mgmt.h diff -u /dev/null snort/src/detection-plugins/sp_wifi_pwr_mgmt.h:1.1 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_pwr_mgmt.h Thu Jul 24 02:20:23 2003 @@ -0,0 +1,26 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_pwr_mgmt.h,v 1.1 2003/07/24 06:20:23 andrew Exp $ */ + +#ifndef __SP_WIFI_PWR_MGMT_H__ +#define __SP_WIFI_PWR_MGMT_H__ + +void SetupWifiPwrMgmt(); + +#endif /* __SP_WIFI_PWR_MGMT_H__ */ Index: snort/src/detection-plugins/sp_wifi_retry.c diff -u /dev/null snort/src/detection-plugins/sp_wifi_retry.c:1.2 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_retry.c Fri Jul 25 05:07:07 2003 @@ -0,0 +1,218 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_retry.c,v 1.2 2003/07/25 09:07:07 andrew Exp $ */ + +/* sp_wifi_retry + * + * Purpose: + * + * Tests 802.11 frames retry control field. + * + * Arguments: + * + * {{ '!' | {} } { ON | OFF | TRUE | FALSE } } + * + * Effect: + * + * Success on retry flag match, failure otherwise. + * + */ + +#include +#include +#include + +#include "rules.h" +#include "decode.h" +#include "plugbase.h" +#include "parser.h" +#include "debug.h" +#include "util.h" +#include "plugin_enum.h" + + +/* don't forget to include the name of this file in plugbase.h! */ + +extern char *file_name; /* this is the file name from rules.c, generally used + for error messages */ + +extern int file_line; /* this is the file line number from rules.c that is + used to indicate file lines for error messages */ + +typedef struct _WifiRetryData +{ + int val; +} WifiRetryData; + +void WifiRetryInit(char *, OptTreeNode *, int); +void WifiRetryRuleParseFunction(char *, OptTreeNode *); +int WifiRetryDetectorFunction(Packet *, struct _OptTreeNode *, OptFpList *); + +/**************************************************************************** + * + * Function: SetupWifiRetry() + * + * Purpose: Generic detection engine plugin template. Registers the + * configuration function and links it to a rule keyword. This is + * the function that gets called from InitPlugins in plugbase.c. + * + * Arguments: None. + * + * Returns: void function + * + ****************************************************************************/ +void SetupWifiRetry() +{ + /* map the keyword to an initialization/processing function */ + RegisterPlugin("retry", WifiRetryInit); + + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Plugin: WifiRetry Setup\n");); +} + + +/**************************************************************************** + * + * Function: WifiRetryInit(char *, OptTreeNode *) + * + * Purpose: Generic rule configuration function. Handles parsing the rule + * information and attaching the associated detection function to + * the OTN. + * + * Arguments: data => rule arguments/data + * otn => pointer to the current rule option list node + * + * Returns: void function + * + ****************************************************************************/ +void WifiRetryInit(char *data, OptTreeNode *otn, int protocol) +{ + /* allocate the data structure and attach it to the + rule's data struct list */ + otn->ds_list[PLUGIN_WIFI_RETRY_CHECK] = (WifiRetryData *) calloc(sizeof(WifiRetryData), sizeof(char)); + + /* be sure to check that the protocol that is passed in matches the + transport layer protocol that you're using for this rule! */ + + /* this is where the keyword arguments are processed and placed into the + rule option's data structure */ + WifiRetryRuleParseFunction(data, otn); + + /* finally, attach the option's detection function to the rule's + detect function pointer list */ + AddOptFuncToList(WifiRetryDetectorFunction, otn); +} + + + +/**************************************************************************** + * + * Function: WifiRetryRuleParseFunction(char *, OptTreeNode *) + * + * Purpose: This is the function that is used to process the option keyword's + * arguments and attach them to the rule's data structures. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: void function + * + ****************************************************************************/ +void WifiRetryRuleParseFunction(char *data, OptTreeNode *otn) +{ + WifiRetryData *ds_ptr; /* data struct pointer */ + int not_flag = 0; + + /* set the ds pointer to make it easier to reference the option's + particular data struct */ + ds_ptr = otn->ds_list[PLUGIN_WIFI_RETRY_CHECK]; + + /* manipulate the option arguments here */ + while(isspace((int) *data)) data++; + + if(*data == '!'){ + not_flag = 1; + data++; + } + + /* set the final option arguments here */ + if(strcmp(data, "FALSE") == 0) + ds_ptr->val = 0; + else if(strcmp(data, "OFF") == 0) + ds_ptr->val = 0; + else if(strcmp(data, "NO") == 0) + ds_ptr->val = 0; + + else if(strcmp(data, "TRUE") == 0) + ds_ptr->val = 1; + else if(strcmp(data, "ON") == 0) + ds_ptr->val = 1; + else if(strcmp(data, "YES") == 0) + ds_ptr->val = 1; + + else + FatalError("%s(%d) => Bad retry flag value \"%s\"\n", + file_name, file_line, data); + + if(not_flag) + ds_ptr->val = (ds_ptr->val) ? 0 : 1; + +} + + +/**************************************************************************** + * + * Function: WifiRetryDetectorFunction(char *, OptTreeNode *) + * + * Purpose: Use this function to perform the particular detection routine + * that this rule keyword is supposed to encompass. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: If the detection test fails, this function *must* return a zero! + * On success, it calls the next function in the detection list + * + ****************************************************************************/ +int WifiRetryDetectorFunction(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list) +{ + + WifiRetryData *plugin_data; + plugin_data = otn->ds_list[PLUGIN_WIFI_RETRY_CHECK]; + + if(!p->wifih){ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Not a WIFI frame\n");); + return 0; + } + + /* your detection function tests go here */ + if (p->wifih->retry == plugin_data->val) + { + return fp_list->next->OptTestFunc(p, otn, fp_list->next); + } +#ifdef DEBUG + else + { + /* you can put debug comments here or not */ + DebugMessage(DEBUG_PLUGIN,"No match\n"); + } +#endif + + /* if the test isn't successful, this function *must* return 0 */ + return 0; +} Index: snort/src/detection-plugins/sp_wifi_retry.h diff -u /dev/null snort/src/detection-plugins/sp_wifi_retry.h:1.1 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_retry.h Thu Jul 24 02:20:23 2003 @@ -0,0 +1,26 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_retry.h,v 1.1 2003/07/24 06:20:23 andrew Exp $ */ + +#ifndef __SP_WIFI_RETRY_H__ +#define __SP_WIFI_RETRY_H__ + +void SetupWifiRetry(); + +#endif /* __SP_WIFI_RETRY_H__ */ Index: snort/src/detection-plugins/sp_wifi_seqnum.c diff -u /dev/null snort/src/detection-plugins/sp_wifi_seqnum.c:1.4 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_seqnum.c Sat Jul 26 21:32:50 2003 @@ -0,0 +1,222 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_seqnum.c,v 1.4 2003/07/27 01:32:50 andrew Exp $ */ + +/* sp_wifi_seqnum + * + * Purpose: + * + * Tests 802.11 frames seqnum control field. + * + * Arguments: + * + * {{ '!' | {} } { 0 <= n <= 4095 } } + * + * n may be specified in either hex or decimal + * + * Effect: + * + * Success on seqnum control field match, failure otherwise. + * + */ + +#include +#include +#include +#include + +#include "rules.h" +#include "decode.h" +#include "plugbase.h" +#include "parser.h" +#include "debug.h" +#include "util.h" +#include "plugin_enum.h" + +#include "wifi_datatypes.h" + +/* don't forget to include the name of this file in plugbase.h! */ + +extern char *file_name; /* this is the file name from rules.c, generally used + for error messages */ + +extern int file_line; /* this is the file line number from rules.c that is + used to indicate file lines for error messages */ + +typedef struct _WifiSeqNumData +{ + u_int16_t seqnum; + u_int8_t not_flag; +} WifiSeqNumData; + +void WifiSeqNumInit(char *, OptTreeNode *, int); +void WifiSeqNumRuleParseFunction(char *, OptTreeNode *); +int WifiSeqNumDetectorFunction(Packet *, struct _OptTreeNode *, OptFpList *); + +/**************************************************************************** + * + * Function: SetupWifiSeqNum() + * + * Purpose: Generic detection engine plugin template. Registers the + * configuration function and links it to a rule keyword. This is + * the function that gets called from InitPlugins in plugbase.c. + * + * Arguments: None. + * + * Returns: void function + * + ****************************************************************************/ +void SetupWifiSeqNum() +{ + /* map the keyword to an initialization/processing function */ + RegisterPlugin("seqnum", WifiSeqNumInit); + + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Plugin: WifiSeqNum Setup\n");); +} + + +/**************************************************************************** + * + * Function: WifiSeqNumInit(char *, OptTreeNode *) + * + * Purpose: Generic rule configuration function. Handles parsing the rule + * information and attaching the associated detection function to + * the OTN. + * + * Arguments: data => rule arguments/data + * otn => pointer to the current rule option list node + * + * Returns: void function + * + ****************************************************************************/ +void WifiSeqNumInit(char *data, OptTreeNode *otn, int protocol) +{ + /* allocate the data structure and attach it to the + rule's data struct list */ + otn->ds_list[PLUGIN_WIFI_SEQNUM_CHECK] = (WifiSeqNumData *) calloc(sizeof(WifiSeqNumData), sizeof(char)); + + /* be sure to check that the protocol that is passed in matches the + transport layer protocol that you're using for this rule! */ + + /* this is where the keyword arguments are processed and placed into the + rule option's data structure */ + WifiSeqNumRuleParseFunction(data, otn); + + /* finally, attach the option's detection function to the rule's + detect function pointer list */ + AddOptFuncToList(WifiSeqNumDetectorFunction, otn); +} + + + +/**************************************************************************** + * + * Function: WifiSeqNumRuleParseFunction(char *, OptTreeNode *) + * + * Purpose: This is the function that is used to process the option keyword's + * arguments and attach them to the rule's data structures. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: void function + * + ****************************************************************************/ +void WifiSeqNumRuleParseFunction(char *data, OptTreeNode *otn) +{ + WifiSeqNumData *ds_ptr; /* data struct pointer */ + unsigned long val = 1 << 12; + + /* set the ds pointer to make it easier to reference the option's + particular data struct */ + ds_ptr = otn->ds_list[PLUGIN_WIFI_SEQNUM_CHECK]; + + /* manipulate the option arguments here */ + while(isspace((int) *data)) data++; + + if(*data == '!'){ + ds_ptr->not_flag = 1; + data++; + } + + /* set the final option arguments here */ + + if(*data){ + if(strncmp(data, "0x", 2) == 0) + val = strtoul(data, NULL, 16); /* use strtoul so people don't have to do + sign-extended 2's complement hex */ + else + val = strtol(data, NULL, 10); + } + + if(val < 0 || val > 4095) + FatalError("%s(%d) => seqnum value out of range \"%s\"\n", + file_name, file_line, data); + + ds_ptr->seqnum = val; +} + + +/**************************************************************************** + * + * Function: WifiSeqNumDetectorFunction(char *, OptTreeNode *) + * + * Purpose: Use this function to perform the particular detection routine + * that this rule keyword is supposed to encompass. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: If the detection test fails, this function *must* return a zero! + * On success, it calls the next function in the detection list + * + ****************************************************************************/ +int WifiSeqNumDetectorFunction(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list) +{ + + WifiSeqNumData *plugin_data; + plugin_data = otn->ds_list[PLUGIN_WIFI_SEQNUM_CHECK]; + + if(!p->wifih){ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Not a WIFI frame\n");); + return 0; + } + + if(p->wifih->type == TYPE_CONTROL){ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Frame is TYPE_CONTROL\n");); + return 0; + } + + /* your detection function tests go here */ + if((plugin_data->not_flag && (p->wifih->seqnum != plugin_data->seqnum)) || + (!plugin_data->not_flag && (p->wifih->seqnum == plugin_data->seqnum))) + { + return fp_list->next->OptTestFunc(p, otn, fp_list->next); + } +#ifdef DEBUG + else + { + /* you can put debug comments here or not */ + DebugMessage(DEBUG_PLUGIN,"No match\n"); + } +#endif + + /* if the test isn't successful, this function *must* return 0 */ + return 0; +} Index: snort/src/detection-plugins/sp_wifi_seqnum.h diff -u /dev/null snort/src/detection-plugins/sp_wifi_seqnum.h:1.1 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_seqnum.h Fri Jul 25 05:51:44 2003 @@ -0,0 +1,26 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_seqnum.h,v 1.1 2003/07/25 09:51:44 andrew Exp $ */ + +#ifndef __SP_WIFI_SEQNUM_H__ +#define __SP_WIFI_SEQNUM_H__ + +void SetupWifiSeqNum(); + +#endif /* __SP_WIFI_SEQNUM_H__ */ Index: snort/src/detection-plugins/sp_wifi_ssid.c diff -u /dev/null snort/src/detection-plugins/sp_wifi_ssid.c:1.3 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_ssid.c Sun Jul 27 03:03:04 2003 @@ -0,0 +1,257 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_ssid.c,v 1.3 2003/07/27 07:03:04 andrew Exp $ */ + +/* sp_wifi_ssid + * + * Purpose: + * + * Tests 802.11 frames SSID. + * + * Arguments: + * + * {{ '!' | {} } } + * + * Effect: + * + * Success on SSID match, failure otherwise. + * + */ + +#include +#include +#include +#include + +#include "rules.h" +#include "decode.h" +#include "plugbase.h" +#include "parser.h" +#include "debug.h" +#include "util.h" +#include "plugin_enum.h" + +#include "wifi_datatypes.h" + +/* don't forget to include the name of this file in plugbase.h! */ + +extern char *file_name; /* this is the file name from rules.c, generally used + for error messages */ + +extern int file_line; /* this is the file line number from rules.c that is + used to indicate file lines for error messages */ + +typedef struct _WifiSsidData +{ + char *ssid; + u_int8_t ssid_len; + u_int8_t not_flag; +} WifiSsidData; + +void WifiSsidInit(char *, OptTreeNode *, int); +void WifiSsidRuleParseFunction(char *, OptTreeNode *); +int WifiSsidDetectorFunction(Packet *, struct _OptTreeNode *, OptFpList *); + +/**************************************************************************** + * + * Function: SetupWifiSsid() + * + * Purpose: Generic detection engine plugin template. Registers the + * configuration function and links it to a rule keyword. This is + * the function that gets called from InitPlugins in plugbase.c. + * + * Arguments: None. + * + * Returns: void function + * + ****************************************************************************/ +void SetupWifiSsid() +{ + /* map the keyword to an initialization/processing function */ + RegisterPlugin("ssid", WifiSsidInit); + + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Plugin: WifiSsid Setup\n");); +} + + +/**************************************************************************** + * + * Function: WifiSsidInit(char *, OptTreeNode *) + * + * Purpose: Generic rule configuration function. Handles parsing the rule + * information and attaching the associated detection function to + * the OTN. + * + * Arguments: data => rule arguments/data + * otn => pointer to the current rule option list node + * + * Returns: void function + * + ****************************************************************************/ +void WifiSsidInit(char *data, OptTreeNode *otn, int protocol) +{ + /* allocate the data structure and attach it to the + rule's data struct list */ + otn->ds_list[PLUGIN_WIFI_SSID_CHECK] = (WifiSsidData *) calloc(sizeof(WifiSsidData), sizeof(char)); + + /* be sure to check that the protocol that is passed in matches the + transport layer protocol that you're using for this rule! */ + + /* this is where the keyword arguments are processed and placed into the + rule option's data structure */ + WifiSsidRuleParseFunction(data, otn); + + /* finally, attach the option's detection function to the rule's + detect function pointer list */ + AddOptFuncToList(WifiSsidDetectorFunction, otn); +} + + + +/**************************************************************************** + * + * Function: WifiSsidRuleParseFunction(char *, OptTreeNode *) + * + * Purpose: This is the function that is used to process the option keyword's + * arguments and attach them to the rule's data structures. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: void function + * + ****************************************************************************/ +void WifiSsidRuleParseFunction(char *data, OptTreeNode *otn) +{ + WifiSsidData *ds_ptr; /* data struct pointer */ + + /* set the ds pointer to make it easier to reference the option's + particular data struct */ + ds_ptr = otn->ds_list[PLUGIN_WIFI_SSID_CHECK]; + + /* manipulate the option arguments here */ + while(isspace((int) *data)) data++; + + if(*data == '!'){ + ds_ptr->not_flag = 1; + data++; + } + + /* set the final option arguments here */ + + ds_ptr->ssid = data; + if((ds_ptr->ssid_len = strlen(data)) > 32) + FatalError("%s (%d) => SSID exceeds maximum length \"%s\"\n", file_name, file_line, data); +} + + +/**************************************************************************** + * + * Function: WifiSsidDetectorFunction(char *, OptTreeNode *) + * + * Purpose: Use this function to perform the particular detection routine + * that this rule keyword is supposed to encompass. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: If the detection test fails, this function *must* return a zero! + * On success, it calls the next function in the detection list + * + ****************************************************************************/ +int WifiSsidDetectorFunction(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list) +{ + + WifiSsidData *plugin_data; + WifiElementID *ssid_id; + u_int8_t *ssid; + + plugin_data = otn->ds_list[PLUGIN_WIFI_SSID_CHECK]; + + if(!p->wifih){ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Not a WIFI frame\n");); + return 0; + } + + + if(p->wifih->type != TYPE_MANAGEMENT){ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Frame is not TYPE_MANAGEMENT\n");); + return 0; + } + + ssid_id = (u_int8_t *)p->wifih + _OFFSET_MANAGEMENT_BODY; + ssid = (u_int8_t *)p->wifih + _OFFSET_MANAGEMENT_BODY; + + switch(p->wifih->stype){ + case STYPE_BEACON: + ssid_id +=_OFFSET_BEACON_SSID_ID; + ssid +=_OFFSET_BEACON_SSID; + break; + case STYPE_ASSOCREQ: + ssid_id += _OFFSET_ASSOCREQ_SSID_ID; + ssid += _OFFSET_ASSOCREQ_SSID; + break; + + case STYPE_REASSOC_REQ: + ssid_id += _OFFSET_REASSOC_REQ_SSID_ID; + ssid += _OFFSET_REASSOC_REQ_SSID; + break; + + case STYPE_PROBEREQ: + ssid_id += _OFFSET_PROBEREQ_SSID_ID; + ssid += _OFFSET_PROBEREQ_SSID; + break; + + case STYPE_PROBERESP: + ssid_id += _OFFSET_PROBERESP_SSID_ID; + ssid += _OFFSET_PROBERESP_SSID; + break; + + case STYPE_ASSOCRESP: + case STYPE_REASSOC_RESP: + case STYPE_ATIM: + case STYPE_DISASSOC: + case STYPE_AUTH: + case STYPE_DEAUTH: + default: + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Management frame subtype does not contain SSID\n");); + return 0; + } + + /* your detection function tests go here */ + + if((plugin_data->not_flag && (memcmp(ssid, plugin_data->ssid, plugin_data->ssid_len) != 0)) || + (!plugin_data->not_flag && (memcmp(ssid, plugin_data->ssid, plugin_data->ssid_len) == 0))) + { + return fp_list->next->OptTestFunc(p, otn, fp_list->next); + } +#ifdef DEBUG + else + { + /* you can put debug comments here or not */ + DebugMessage(DEBUG_PLUGIN,"No match\n"); + } +#endif + + /* if the test isn't successful, this function *must* return 0 */ + return 0; +} + + + Index: snort/src/detection-plugins/sp_wifi_ssid.h diff -u /dev/null snort/src/detection-plugins/sp_wifi_ssid.h:1.1 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_ssid.h Sat Jul 26 23:26:08 2003 @@ -0,0 +1,26 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_ssid.h,v 1.1 2003/07/27 03:26:08 andrew Exp $ */ + +#ifndef __SP_WIFI_SSID_H__ +#define __SP_WIFI_SSID_H__ + +void SetupWifiSsid(); + +#endif /* __SP_WIFI_SSID_H__ */ Index: snort/src/detection-plugins/sp_wifi_stype.c diff -u /dev/null snort/src/detection-plugins/sp_wifi_stype.c:1.5 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_stype.c Thu Aug 14 22:17:48 2003 @@ -0,0 +1,292 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + + +/* $Id: sp_wifi_stype.c,v 1.5 2003/08/15 02:17:48 andrew Exp $ */ + +/* sp_wifi_stype + * + * Purpose: + * + * Tests 802.11 frames for their frame subtype and implicitly tests the frame's type too + * so that using a symbollic name for the subtype works in the assumed manner. + * + * Arguments: + * + * {{ '!' | {} } { wifi_stype_t } + * + * Effect: + * + * Success on frame sub-type match, failure otherwise. + * + */ + +#include +#include +#include +#include + +#include "rules.h" +#include "decode.h" +#include "plugbase.h" +#include "parser.h" +#include "debug.h" +#include "util.h" +#include "plugin_enum.h" + + +/* don't forget to include the name of this file in plugbase.h! */ + +extern char *file_name; /* this is the file name from rules.c, generally used + for error messages */ + +extern int file_line; /* this is the file line number from rules.c that is + used to indicate file lines for error messages */ +#define NUM_WIFI_STYPES 40 +char *_wifi_stype_strs[] = { + "STYPE_ASSOCREQ", /* 0x00 */ + "STYPE_ASSOCRESP", /* 0x01 */ + "STYPE_REASSOC_REQ", /* 0x02 */ + "STYPE_REASSOC_RESP", /* 0x03 */ + "STYPE_PROBEREQ", /* 0x04 */ + "STYPE_PROBERESP", /* 0x05 */ + "STYPE_INVALID", /* 0x06 */ + "STYPE_INVALID", /* 0x07 */ + "STYPE_BEACON", /* 0x08 */ + "STYPE_ATIM", /* 0x09 */ + "STYPE_DISASSOC", /* 0x0a */ + "STYPE_AUTH", /* 0x0b */ + "STYPE_DEAUTH", /* 0x0c */ + "STYPE_INVALID", /* 0x0d */ + "STYPE_INVALID", /* 0x0e */ + "STYPE_INVALID", /* 0x0f */ + "STYPE_INVALID", /* 0x10 */ + "STYPE_INVALID", /* 0x11 */ + "STYPE_INVALID", /* 0x12 */ + "STYPE_INVALID", /* 0x13 */ + "STYPE_INVALID", /* 0x14 */ + "STYPE_INVALID", /* 0x15 */ + "STYPE_INVALID", /* 0x16 */ + "STYPE_INVALID", /* 0x17 */ + "STYPE_INVALID", /* 0x18 */ + "STYPE_INVALID", /* 0x19 */ + "STYPE_PSPOLL", /* 0x1a */ + "STYPE_RTS", /* 0x1b */ + "STYPE_CTS", /* 0x1c */ + "STYPE_ACK", /* 0x1d */ + "STYPE_CFEND", /* 0x1e */ + "STYPE_CFEND_CFACK", /* 0x1f */ + "STYPE_DATA", /* 0x20 */ + "STYPE_CFACK", /* 0x21 */ + "STYPE_CFPOLL", /* 0x22 */ + "STYPE_CFACK_CFPOLL", /* 0x23 */ + "STYPE_NULLFUNC", /* 0x24 */ + "STYPE_CFACK_NULLFUNC", /* 0x25 */ + "STYPE_CFPOLL_NULLFUNC", /* 0x26 */ + "STYPE_CFACK_CFPOLL_NULLFUNC" /* 0x27 */ +}; + +typedef enum { /* 802.11 management frame subtypes */ + STYPE_INVALID = -1, + STYPE_ASSOCREQ = 0x00, /* Subtypes are already AND'ed with their corresponding Types */ + STYPE_ASSOCRESP = 0x01, /* to prevent false positives and the need for checking the type */ + STYPE_REASSOC_REQ = 0x02, /* independently */ + STYPE_REASSOC_RESP = 0x03, + STYPE_PROBEREQ = 0x04, + STYPE_PROBERESP = 0x05, + STYPE_BEACON = 0x08, + STYPE_ATIM = 0x09, + STYPE_DIASSOC = 0x0a, + STYPE_AUTH = 0x0b, + STYPE_DEAUTH = 0x0c, + +/* 802.11 control frame subtypes */ + STYPE_PSPOLL = 0x1a, + STYPE_RTS = 0x1b, + STYPE_CTS = 0x1c, + STYPE_ACK = 0x1d, + STYPE_CFEND = 0x1e, + STYPE_CFEND_CFACK = 0x1f, + +/* 802.11 data frame subtypes */ + STYPE_DATA = 0x20, + STYPE_CFACK = 0x21, + STYPE_CFPOLL = 0x22, + STYPE_CFACK_CFPOLL = 0x23, + STYPE_NULLFUNC = 0x24, + STYPE_CFACK_NULLFUNC = 0x25, + STYPE_CFPOLL_NULLFUNC = 0x26, + STYPE_CFACK_CFPOLL_NULLFUNC = 0x27 +} wifi_stype_t; + +typedef struct _WifiStypeData +{ + wifi_stype_t stype; + u_int8_t not_flag; + +} WifiStypeData; + +void WifiStypeInit(char *, OptTreeNode *, int); +void WifiStypeRuleParseFunction(char *, OptTreeNode *); +int WifiStypeDetectorFunction(Packet *, struct _OptTreeNode *, OptFpList *); + +/**************************************************************************** + * + * Function: SetupWifiStype() + * + * Purpose: Generic detection engine plugin template. Registers the + * configuration function and links it to a rule keyword. This is + * the function that gets called from InitPlugins in plugbase.c. + * + * Arguments: None. + * + * Returns: void function + * + ****************************************************************************/ +void SetupWifiStype() +{ + /* map the keyword to an initialization/processing function */ + RegisterPlugin("stype", WifiStypeInit); + + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Plugin: WifiStype Setup\n");); +} + + +/**************************************************************************** + * + * Function: WifiStypeInit(char *, OptTreeNode *) + * + * Purpose: Generic rule configuration function. Handles parsing the rule + * information and attaching the associated detection function to + * the OTN. + * + * Arguments: data => rule arguments/data + * otn => pointer to the current rule option list node + * + * Returns: void function + * + ****************************************************************************/ +void WifiStypeInit(char *data, OptTreeNode *otn, int protocol) +{ + /* allocate the data structure and attach it to the + rule's data struct list */ + otn->ds_list[PLUGIN_WIFI_STYPE_CHECK] = (WifiStypeData *) calloc(sizeof(WifiStypeData), sizeof(char)); + + /* be sure to check that the protocol that is passed in matches the + transport layer protocol that you're using for this rule! */ + + /* this is where the keyword arguments are processed and placed into the + rule option's data structure */ + WifiStypeRuleParseFunction(data, otn); + + /* finally, attach the option's detection function to the rule's + detect function pointer list */ + AddOptFuncToList(WifiStypeDetectorFunction, otn); +} + + + +/**************************************************************************** + * + * Function: WifiStypeRuleParseFunction(char *, OptTreeNode *) + * + * Purpose: This is the function that is used to process the option keyword's + * arguments and attach them to the rule's data structures. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: void function + * + ****************************************************************************/ +void WifiStypeRuleParseFunction(char *data, OptTreeNode *otn) +{ + int i; + WifiStypeData *ds_ptr; /* data struct pointer */ + + /* set the ds pointer to make it easier to reference the option's + particular data struct */ + ds_ptr = otn->ds_list[PLUGIN_WIFI_STYPE_CHECK]; + + /* manipulate the option arguments here */ + while(isspace((int)*data)) data++; + + if(*data == '!'){ + ds_ptr->not_flag = 1; + data++; + } + + ds_ptr->stype = STYPE_INVALID; + + /* set the final option arguments here */ + for(i = 0; i < NUM_WIFI_STYPES; i++) + if(strcmp(data, _wifi_stype_strs[i]) == 0 && + strcmp(data, "STYPE_INVALID") != 0){ + ds_ptr->stype = i; + break; + } + + if(ds_ptr->stype == STYPE_INVALID) + FatalError("%s(%d) => Bad frame sub-type \"%s\"\n", file_name, file_line, data); +} + + +/**************************************************************************** + * + * Function: WifiStypeDetectorFunction(char *, OptTreeNode *) + * + * Purpose: Use this function to perform the particular detection routine + * that this rule keyword is supposed to encompass. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: If the detection test fails, this function *must* return a zero! + * On success, it calls the next function in the detection list + * + ****************************************************************************/ +int WifiStypeDetectorFunction(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list) +{ + WifiStypeData *wtd; + u_int8_t stype; + wtd = otn->ds_list[PLUGIN_WIFI_STYPE_CHECK]; + + if(!p->wifih) + { + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Not WIFI\n");); + return 0; + } + + stype = p->wifih->stype | (p->wifih->type << 4); + + if((wtd->not_flag && (stype != wtd->stype)) || + (!wtd->not_flag && (stype == wtd->stype))) + { + return fp_list->next->OptTestFunc(p, otn, fp_list->next); + } +#ifdef DEBUG + else + { + /* you can put debug comments here or not */ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"No match\n");); + } +#endif + + /* if the test isn't successful, this function *must* return 0 */ + return 0; +} Index: snort/src/detection-plugins/sp_wifi_stype.h diff -u /dev/null snort/src/detection-plugins/sp_wifi_stype.h:1.2 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_stype.h Sat Jul 26 20:34:00 2003 @@ -0,0 +1,26 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_stype.h,v 1.2 2003/07/27 00:34:00 andrew Exp $ */ + +#ifndef __SP_WIFI_STYPE_H__ +#define __SP_WIFI_STYPE_H__ + +void SetupWifiStype(); + +#endif /* __SP_WIFI_STYPE_H__ */ Index: snort/src/detection-plugins/sp_wifi_to_ds.c diff -u /dev/null snort/src/detection-plugins/sp_wifi_to_ds.c:1.2 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_to_ds.c Fri Jul 25 04:59:01 2003 @@ -0,0 +1,218 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_to_ds.c,v 1.2 2003/07/25 08:59:01 andrew Exp $ */ + +/* sp_wifi_to_ds + * + * Purpose: + * + * Tests 802.11 frames to_ds control field. + * + * Arguments: + * + * {{ '!' | {} } { ON | OFF | TRUE | FALSE } } + * + * Effect: + * + * Success on to_ds match, failure otherwise. + * + */ + +#include +#include +#include + +#include "rules.h" +#include "decode.h" +#include "plugbase.h" +#include "parser.h" +#include "debug.h" +#include "util.h" +#include "plugin_enum.h" + + +/* don't forget to include the name of this file in plugbase.h! */ + +extern char *file_name; /* this is the file name from rules.c, generally used + for error messages */ + +extern int file_line; /* this is the file line number from rules.c that is + used to indicate file lines for error messages */ + +typedef struct _WifiToDsData +{ + int val; +} WifiToDsData; + +void WifiToDsInit(char *, OptTreeNode *, int); +void WifiToDsRuleParseFunction(char *, OptTreeNode *); +int WifiToDsDetectorFunction(Packet *, struct _OptTreeNode *, OptFpList *); + +/**************************************************************************** + * + * Function: SetupWifiToDs() + * + * Purpose: Generic detection engine plugin template. Registers the + * configuration function and links it to a rule keyword. This is + * the function that gets called from InitPlugins in plugbase.c. + * + * Arguments: None. + * + * Returns: void function + * + ****************************************************************************/ +void SetupWifiToDs() +{ + /* map the keyword to an initialization/processing function */ + RegisterPlugin("to_ds", WifiToDsInit); + + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Plugin: WifiToDs Setup\n");); +} + + +/**************************************************************************** + * + * Function: WifiToDsInit(char *, OptTreeNode *) + * + * Purpose: Generic rule configuration function. Handles parsing the rule + * information and attaching the associated detection function to + * the OTN. + * + * Arguments: data => rule arguments/data + * otn => pointer to the current rule option list node + * + * Returns: void function + * + ****************************************************************************/ +void WifiToDsInit(char *data, OptTreeNode *otn, int protocol) +{ + /* allocate the data structure and attach it to the + rule's data struct list */ + otn->ds_list[PLUGIN_WIFI_TO_DS_CHECK] = (WifiToDsData *) calloc(sizeof(WifiToDsData), sizeof(char)); + + /* be sure to check that the protocol that is passed in matches the + transport layer protocol that you're using for this rule! */ + + /* this is where the keyword arguments are processed and placed into the + rule option's data structure */ + WifiToDsRuleParseFunction(data, otn); + + /* finally, attach the option's detection function to the rule's + detect function pointer list */ + AddOptFuncToList(WifiToDsDetectorFunction, otn); +} + + + +/**************************************************************************** + * + * Function: WifiToDsRuleParseFunction(char *, OptTreeNode *) + * + * Purpose: This is the function that is used to process the option keyword's + * arguments and attach them to the rule's data structures. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: void function + * + ****************************************************************************/ +void WifiToDsRuleParseFunction(char *data, OptTreeNode *otn) +{ + WifiToDsData *ds_ptr; /* data struct pointer */ + int not_flag = 0; + + /* set the ds pointer to make it easier to reference the option's + particular data struct */ + ds_ptr = otn->ds_list[PLUGIN_WIFI_TO_DS_CHECK]; + + /* manipulate the option arguments here */ + while(isspace((int) *data)) data++; + + if(*data == '!'){ + not_flag = 1; + data++; + } + + /* set the final option arguments here */ + if(strcmp(data, "FALSE") == 0) + ds_ptr->val = 0; + else if(strcmp(data, "OFF") == 0) + ds_ptr->val = 0; + else if(strcmp(data, "NO") == 0) + ds_ptr->val = 0; + + else if(strcmp(data, "TRUE") == 0) + ds_ptr->val = 1; + else if(strcmp(data, "ON") == 0) + ds_ptr->val = 1; + else if(strcmp(data, "YES") == 0) + ds_ptr->val = 1; + + else + FatalError("%s(%d) => Bad to_ds flag value \"%s\"\n", + file_name, file_line, data); + + if(not_flag) + ds_ptr->val = (ds_ptr->val) ? 0 : 1; + +} + + +/**************************************************************************** + * + * Function: WifiToDsDetectorFunction(char *, OptTreeNode *) + * + * Purpose: Use this function to perform the particular detection routine + * that this rule keyword is supposed to encompass. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: If the detection test fails, this function *must* return a zero! + * On success, it calls the next function in the detection list + * + ****************************************************************************/ +int WifiToDsDetectorFunction(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list) +{ + + WifiToDsData *plugin_data; + plugin_data = otn->ds_list[PLUGIN_WIFI_TO_DS_CHECK]; + + if(!p->wifih){ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Not a WIFI frame\n");); + return 0; + } + + /* your detection function tests go here */ + if (p->wifih->to_ds == plugin_data->val) + { + return fp_list->next->OptTestFunc(p, otn, fp_list->next); + } +#ifdef DEBUG + else + { + /* you can put debug comments here or not */ + DebugMessage(DEBUG_PLUGIN,"No match\n"); + } +#endif + + /* if the test isn't successful, this function *must* return 0 */ + return 0; +} Index: snort/src/detection-plugins/sp_wifi_to_ds.h diff -u /dev/null snort/src/detection-plugins/sp_wifi_to_ds.h:1.1 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_to_ds.h Thu Jul 24 02:20:23 2003 @@ -0,0 +1,26 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_to_ds.h,v 1.1 2003/07/24 06:20:23 andrew Exp $ */ + +#ifndef __SP_WIFI_TO_DS_H__ +#define __SP_WIFI_TO_DS_H__ + +void SetupWifiToDs(); + +#endif /* __SP_WIFI_TO_DS_H__ */ Index: snort/src/detection-plugins/sp_wifi_type.c diff -u /dev/null snort/src/detection-plugins/sp_wifi_type.c:1.2 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_type.c Sat Jul 26 20:33:01 2003 @@ -0,0 +1,221 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + + + +/* $Id: sp_wifi_type.c,v 1.2 2003/07/27 00:33:01 andrew Exp $ */ +/* Snort Detection Plugin Source File WifiType */ + +/* sp_wifi_type + * + * Purpose: + * + * Tests 802.11 frames for their frame type. + * + * Arguments: + * + * {{ '!' | {} } { TYPE_MANAGEMENT | TYPE_CONTROL | TYPE_DATA } } + * + * Effect: + * + * Success on frame type match, failure otherwise. + * + */ + +#include +#include +#include +#include + +#include "rules.h" +#include "decode.h" +#include "plugbase.h" +#include "parser.h" +#include "debug.h" +#include "util.h" +#include "plugin_enum.h" + +#include "wifi_datatypes.h" + +/* don't forget to include the name of this file in plugbase.h! */ + +extern char *file_name; /* this is the file name from rules.c, generally used + for error messages */ + +extern int file_line; /* this is the file line number from rules.c that is + used to indicate file lines for error messages */ + +char *_wifi_type_strs[] = { + "TYPE_MANAGEMENT", + "TYPE_CONTROL", + "TYPE_DATA" +}; + +typedef struct _WifiTypeData +{ + wifi_type_t type; + u_int8_t not_flag; + +} WifiTypeData; + +void WifiTypeInit(char *, OptTreeNode *, int); +void WifiTypeRuleParseFunction(char *, OptTreeNode *); +int WifiTypeDetectorFunction(Packet *, struct _OptTreeNode *, OptFpList *); + +/**************************************************************************** + * + * Function: SetupWifiType() + * + * Purpose: Generic detection engine plugin template. Registers the + * configuration function and links it to a rule keyword. This is + * the function that gets called from InitPlugins in plugbase.c. + * + * Arguments: None. + * + * Returns: void function + * + ****************************************************************************/ +void SetupWifiType() +{ + /* map the keyword to an initialization/processing function */ + RegisterPlugin("type", WifiTypeInit); + + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Plugin: WifiType Setup\n");); +} + + +/**************************************************************************** + * + * Function: WifiTypeInit(char *, OptTreeNode *) + * + * Purpose: Generic rule configuration function. Handles parsing the rule + * information and attaching the associated detection function to + * the OTN. + * + * Arguments: data => rule arguments/data + * otn => pointer to the current rule option list node + * + * Returns: void function + * + ****************************************************************************/ +void WifiTypeInit(char *data, OptTreeNode *otn, int protocol) +{ + /* allocate the data structure and attach it to the + rule's data struct list */ + otn->ds_list[PLUGIN_WIFI_TYPE_CHECK] = (WifiTypeData *) calloc(sizeof(WifiTypeData), sizeof(char)); + + /* be sure to check that the protocol that is passed in matches the + transport layer protocol that you're using for this rule! */ + + /* this is where the keyword arguments are processed and placed into the + rule option's data structure */ + WifiTypeRuleParseFunction(data, otn); + + /* finally, attach the option's detection function to the rule's + detect function pointer list */ + AddOptFuncToList(WifiTypeDetectorFunction, otn); +} + + + +/**************************************************************************** + * + * Function: WifiTypeRuleParseFunction(char *, OptTreeNode *) + * + * Purpose: This is the function that is used to process the option keyword's + * arguments and attach them to the rule's data structures. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: void function + * + ****************************************************************************/ +void WifiTypeRuleParseFunction(char *data, OptTreeNode *otn) +{ + int i; + WifiTypeData *ds_ptr; /* data struct pointer */ + + /* set the ds pointer to make it easier to reference the option's + particular data struct */ + ds_ptr = otn->ds_list[PLUGIN_WIFI_TYPE_CHECK]; + + /* manipulate the option arguments here */ + while(isspace((int)*data)) data++; + + if(*data == '!'){ + ds_ptr->not_flag = 1; + data++; + } + + ds_ptr->type = TYPE_INVALID; + + /* set the final option arguments here */ + for(i = 0; i < 3; i++) + if(strcmp(data, _wifi_type_strs[i]) == 0){ + ds_ptr->type = i; + break; + } + + if(ds_ptr->type == TYPE_INVALID) + FatalError("%s(%d) => Bad frame type \"%s\"\n", + file_name, file_line, data); +} + + +/**************************************************************************** + * + * Function: WifiTypeDetectorFunction(char *, OptTreeNode *) + * + * Purpose: Use this function to perform the particular detection routine + * that this rule keyword is supposed to encompass. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: If the detection test fails, this function *must* return a zero! + * On success, it calls the next function in the detection list + * + ****************************************************************************/ +int WifiTypeDetectorFunction(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list) +{ + WifiTypeData *wtd; + wtd = otn->ds_list[PLUGIN_WIFI_TYPE_CHECK]; + + if(!p->wifih) + { + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Not WIFI\n");); + return 0; + } + + if((wtd->not_flag && (p->wifih->type != wtd->type)) || + (!wtd->not_flag && (p->wifih->type == wtd->type))) + { + return fp_list->next->OptTestFunc(p, otn, fp_list->next); + } +#ifdef DEBUG + else + { + /* you can put debug comments here or not */ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"No match\n");); + } +#endif + + /* if the test isn't successful, this function *must* return 0 */ + return 0; +} Index: snort/src/detection-plugins/sp_wifi_type.h diff -u /dev/null snort/src/detection-plugins/sp_wifi_type.h:1.2 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_type.h Sat Jul 26 20:33:01 2003 @@ -0,0 +1,26 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_type.h,v 1.2 2003/07/27 00:33:01 andrew Exp $ */ + +#ifndef __SP_WIFI_TYPE_H__ +#define __SP_WIFI_TYPE_H__ + +void SetupWifiType(); + +#endif /* __SP_WIFI_TYPE_H__ */ Index: snort/src/detection-plugins/sp_wifi_wep.c diff -u /dev/null snort/src/detection-plugins/sp_wifi_wep.c:1.2 --- /dev/null Sat Nov 5 19:10:43 2005 +++ snort/src/detection-plugins/sp_wifi_wep.c Fri Jul 25 04:55:58 2003 @@ -0,0 +1,218 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_wep.c,v 1.2 2003/07/25 08:55:58 andrew Exp $ */ + +/* sp_wifi_wep + * + * Purpose: + * + * Tests 802.11 frames WEP control field. + * + * Arguments: + * + * {{ '!' | {} } { ON | OFF | TRUE | FALSE } } + * + * Effect: + * + * Success on WEP control field match, failure otherwise. + * + */ + +#include +#include +#include + +#include "rules.h" +#include "decode.h" +#include "plugbase.h" +#include "parser.h" +#include "debug.h" +#include "util.h" +#include "plugin_enum.h" + + +/* don't forget to include the name of this file in plugbase.h! */ + +extern char *file_name; /* this is the file name from rules.c, generally used + for error messages */ + +extern int file_line; /* this is the file line number from rules.c that is + used to indicate file lines for error messages */ + +typedef struct _WifiWepData +{ + int val; +} WifiWepData; + +void WifiWepInit(char *, OptTreeNode *, int); +void WifiWepRuleParseFunction(char *, OptTreeNode *); +int WifiWepDetectorFunction(Packet *, struct _OptTreeNode *, OptFpList *); + +/**************************************************************************** + * + * Function: SetupWifiWep() + * + * Purpose: Generic detection engine plugin template. Registers the + * configuration function and links it to a rule keyword. This is + * the function that gets called from InitPlugins in plugbase.c. + * + * Arguments: None. + * + * Returns: void function + * + ****************************************************************************/ +void SetupWifiWep() +{ + /* map the keyword to an initialization/processing function */ + RegisterPlugin("wep", WifiWepInit); + + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Plugin: WifiWep Setup\n");); +} + + +/**************************************************************************** + * + * Function: WifiWepInit(char *, OptTreeNode *) + * + * Purpose: Generic rule configuration function. Handles parsing the rule + * information and attaching the associated detection function to + * the OTN. + * + * Arguments: data => rule arguments/data + * otn => pointer to the current rule option list node + * + * Returns: void function + * + ****************************************************************************/ +void WifiWepInit(char *data, OptTreeNode *otn, int protocol) +{ + /* allocate the data structure and attach it to the + rule's data struct list */ + otn->ds_list[PLUGIN_WIFI_WEP_CHECK] = (WifiWepData *) calloc(sizeof(WifiWepData), sizeof(char)); + + /* be sure to check that the protocol that is passed in matches the + transport layer protocol that you're using for this rule! */ + + /* this is where the keyword arguments are processed and placed into the + rule option's data structure */ + WifiWepRuleParseFunction(data, otn); + + /* finally, attach the option's detection function to the rule's + detect function pointer list */ + AddOptFuncToList(WifiWepDetectorFunction, otn); +} + + + +/**************************************************************************** + * + * Function: WifiWepRuleParseFunction(char *, OptTreeNode *) + * + * Purpose: This is the function that is used to process the option keyword's + * arguments and attach them to the rule's data structures. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: void function + * + ****************************************************************************/ +void WifiWepRuleParseFunction(char *data, OptTreeNode *otn) +{ + WifiWepData *ds_ptr; /* data struct pointer */ + int not_flag = 0; + + /* set the ds pointer to make it easier to reference the option's + particular data struct */ + ds_ptr = otn->ds_list[PLUGIN_WIFI_WEP_CHECK]; + + /* manipulate the option arguments here */ + while(isspace((int) *data)) data++; + + if(*data == '!'){ + not_flag = 1; + data++; + } + + /* set the final option arguments here */ + if(strcmp(data, "FALSE") == 0) + ds_ptr->val = 0; + else if(strcmp(data, "OFF") == 0) + ds_ptr->val = 0; + else if(strcmp(data, "NO") == 0) + ds_ptr->val = 0; + + else if(strcmp(data, "TRUE") == 0) + ds_ptr->val = 1; + else if(strcmp(data, "ON") == 0) + ds_ptr->val = 1; + else if(strcmp(data, "YES") == 0) + ds_ptr->val = 1; + + else + FatalError("%s(%d) => Bad wep flag value \"%s\"\n", + file_name, file_line, data); + + if(not_flag) + ds_ptr->val = (ds_ptr->val) ? 0 : 1; + +} + + +/**************************************************************************** + * + * Function: WifiWepDetectorFunction(char *, OptTreeNode *) + * + * Purpose: Use this function to perform the particular detection routine + * that this rule keyword is supposed to encompass. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: If the detection test fails, this function *must* return a zero! + * On success, it calls the next function in the detection list + * + ****************************************************************************/ +int WifiWepDetectorFunction(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list) +{ + + WifiWepData *plugin_data; + plugin_data = otn->ds_list[PLUGIN_WIFI_WEP_CHECK]; + + if(!p->wifih){ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Not a WIFI frame\n");); + return 0; + } + + /* your detection function tests go here */ + if (p->wifih->wep == plugin_data->val) + { + return fp_list->next->OptTestFunc(p, otn, fp_list->next); + } +#ifdef DEBUG + else + { + /* you can put debug comments here or not */ + DebugMessage(DEBUG_PLUGIN,"No match\n"); + } +#endif + + /* if the test isn't successful, this function *must* return 0 */ + return 0; +} Index: snort/src/detection-plugins/sp_wifi_wep.h diff -u /dev/null snort/src/detection-plugins/sp_wifi_wep.h:1.1 --- /dev/null Sat Nov 5 19:10:44 2005 +++ snort/src/detection-plugins/sp_wifi_wep.h Thu Jul 24 02:20:23 2003 @@ -0,0 +1,26 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_wifi_wep.h,v 1.1 2003/07/24 06:20:23 andrew Exp $ */ + +#ifndef __SP_WIFI_WEP_H__ +#define __SP_WIFI_WEP_H__ + +void SetupWifiWep(); + +#endif /* __SP_WIFI_WEP_H__ */ Index: snort/src/detection-plugins/wifi_datatypes.h diff -u /dev/null snort/src/detection-plugins/wifi_datatypes.h:1.3 --- /dev/null Sat Nov 5 19:10:44 2005 +++ snort/src/detection-plugins/wifi_datatypes.h Sat Jul 26 23:22:30 2003 @@ -0,0 +1,162 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: wifi_datatypes.h,v 1.3 2003/07/27 03:22:30 andrew Exp $ */ + +/* Data types for wifi plugins */ + +#ifndef __WIFI_DATATYPES_H__ +#define __WIFI_DATATYPES_H__ + +typedef enum { /* 802.11 frame types */ + TYPE_INVALID = -1, + TYPE_MANAGEMENT = 0x00, + TYPE_CONTROL = 0x01, + TYPE_DATA = 0x02 +} wifi_type_t; + +typedef enum { /* 802.11 management frame subtypes */ + STYPE_INVALID = -1, + STYPE_ASSOCREQ = 0x00, + STYPE_ASSOCRESP = 0x01, + STYPE_REASSOC_REQ = 0x02, + STYPE_REASSOC_RESP = 0x03, + STYPE_PROBEREQ = 0x04, + STYPE_PROBERESP = 0x05, + STYPE_BEACON = 0x08, + STYPE_ATIM = 0x09, + STYPE_DISASSOC = 0x0a, + STYPE_AUTH = 0x0b, + STYPE_DEAUTH = 0x0c, + +/* 802.11 control frame subtypes */ + STYPE_PS = 0x0a, + STYPE_RTS = 0x0b, + STYPE_CTS = 0x0c, + STYPE_ACK = 0x0d, + STYPE_CFEND = 0x0e, + STYPE_CFEND_CFACK = 0x0f, + +/* 802.11 data frame subtypes */ + STYPE_DATA = 0x00, + STYPE_CFACK = 0x01, + STYPE_CFPOLL = 0x02, + STYPE_CFACK_CFPOLL = 0x03, + STYPE_NULL = 0x04, + STYPE_CFACK_NULL = 0x05, + STYPE_CFPOLL_NULL = 0x06, + STYPE_CFACK_CFPOLL_NULL = 0x07 +} wifi_stype_t; + +typedef struct _WifiElementID{ /* 802.11 element id */ + u_int8_t id; + u_int8_t len; +} WifiElementID; + +typedef struct _WifiCapInfo{ /* 802.11 capability information */ + u_int16_t cap_ess:1; + u_int16_t cap_ibss:1; + u_int16_t cap_cfpoll:1; + u_int16_t cap_cfpoll_req:1; + u_int16_t cap_wep:1; + u_int16_t cap_reserved:11; +} WifiCapInfo; + +#define _OFFSET_MANAGEMENT_BODY sizeof(WifiHdr) - 6 + +typedef struct _WifiBeacon{ /* 802.11 beacon body */ +#define _OFFSET_TIMESTAMP 0x00 + u_int32_t *timestamp1; + u_int32_t *timestamp2; +#define _OFFSET_BEACON_INT _OFFSET_TIMESTAMP + 2 * sizeof(u_int32_t) + u_int16_t *beacon_int; +#define _OFFSET_BEACON_CAP_INFO _OFFSET_BEACON_INT + sizeof(u_int16_t) + WifiCapInfo *cap_info; +#define _OFFSET_BEACON_SSID_ID _OFFSET_BEACON_CAP_INFO + sizeof(WifiCapInfo) + WifiElementID *ssid_id; +#define _OFFSET_BEACON_SSID _OFFSET_BEACON_SSID_ID + sizeof(WifiElementID) + u_int8_t *ssid; + WifiElementID *rates_id; + u_int8_t *rates; + u_int8_t *current_chan; + /* we don't care about the rest right now */ +} WifiBeacon; + + +typedef struct _WifiAssocReq{ /* 802.11 association request body */ +#define _OFFSET_ASSOCREQ_CAP_INFO 0x00 + WifiCapInfo *cap_info; +#define _OFFSET_ASSOCREQ_LISTEN_INT _OFFSET_ASSOCREQ_CAP_INFO + sizeof(WifiCapInfo) + u_int16_t *listen_int; +#define _OFFSET_ASSOCREQ_SSID_ID _OFFSET_ASSOCREQ_LISTEN_INT + sizeof(u_int16_t) + WifiElementID *ssid_id; +#define _OFFSET_ASSOCREQ_SSID _OFFSET_ASSOCREQ_SSID_ID + sizeof(WifiElementID) + u_int8_t *ssid; + WifiElementID *rates_id; + u_int8_t *rates; +} WifiAssocReq; + +typedef struct _WifiReAssocReq{ /* 802.11 re-association request body */ +#define _OFFSET_REASSOC_REQ 0x00 + WifiCapInfo *cap_info; +#define _OFFSET_REASSOC_REQ_LISTEN_INT _OFFSET_REASSOC_REQ + sizeof(WifiCapInfo) + u_int16_t *listen_int; +#define _OFFSET_REASSOC_REQ_CURRENT_AP _OFFSET_REASSOC_REQ_LISTEN_INT + sizeof(u_int16_t) + u_int8_t *current_ap; +#define _OFFSET_REASSOC_REQ_SSID_ID _OFFSET_REASSOC_REQ_CURRENT_AP + 6 + WifiElementID *ssid_id; +#define _OFFSET_REASSOC_REQ_SSID _OFFSET_REASSOC_REQ_SSID_ID + sizeof(WifiElementID) + u_int8_t *ssid; + WifiElementID *rates_id; + u_int8_t *rates; +} WifiReAssocReq; + + +typedef struct _WifiProbeReq{ /* 802.11 probe request body */ +#define _OFFSET_PROBEREQ_SSID_ID 0 + WifiElementID *ssid_id; +#define _OFFSET_PROBEREQ_SSID _OFFSET_PROBEREQ_SSID_ID + sizeof(WifiElementID) + u_int8_t *ssid; + WifiElementID *rates_id; + u_int8_t *rates; +} WifiProbeReq; + + +typedef struct _WifiProbeResp{ /* 802.11 probe response body */ +#define _OFFSET_TIMESTAMP 0x00 + u_int32_t *timestamp1; + u_int32_t *timestamp2; +#define _OFFSET_BEACON_INT _OFFSET_TIMESTAMP + 2 * sizeof(u_int32_t) + u_int16_t *beacon_int; +#define _OFFSET_PROBERESP_CAP_INFO _OFFSET_BEACON_INT + sizeof(u_int16_t) + WifiCapInfo *cap_info; +#define _OFFSET_PROBERESP_SSID_ID _OFFSET_PROBERESP_CAP_INFO + sizeof(WifiCapInfo) + WifiElementID *ssid_id; +#define _OFFSET_PROBERESP_SSID _OFFSET_PROBERESP_SSID_ID + sizeof(WifiElementID) + u_int8_t *ssid; + WifiElementID *rates_id; + u_int8_t *rates; + u_int8_t *current_chan; + /* we don't care about the rest right now */ +} WifiProbeResp; + + + + + +#endif /* __WIFI_DATATYPES_H__ */ Index: snort/src/preprocessors/Makefile.am diff -u snort/src/preprocessors/Makefile.am:1.1.1.6 snort/src/preprocessors/Makefile.am:1.8 --- snort/src/preprocessors/Makefile.am:1.1.1.6 Sat Oct 1 16:16:15 2005 +++ snort/src/preprocessors/Makefile.am Sat Oct 1 20:07:05 2005 @@ -27,6 +27,11 @@ spp_xlink2state.c spp_xlink2state.h \ xlink2state.c xlink2state.h \ str_search.c str_search.h \ -stream.h +stream.h \ +spp_rogue_ap.c spp_rogue_ap.h \ +spp_antistumbler.c spp_antistumbler.h \ +spp_deauth_flood.c spp_deauth_flood.h \ +spp_auth_flood.c spp_auth_flood.h \ +spp_macspoof.c spp_macspoof.h INCLUDES = @INCLUDES@ Index: snort/src/preprocessors/spp_antistumbler.c diff -u /dev/null snort/src/preprocessors/spp_antistumbler.c:1.3 --- /dev/null Sat Nov 5 19:10:45 2005 +++ snort/src/preprocessors/spp_antistumbler.c Sat Jun 25 01:46:21 2005 @@ -0,0 +1,432 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: spp_antistumbler.c,v 1.3 2005/06/25 05:46:21 andrew Exp $ */ + +/* spp_antistumbler + * + * Purpose: + * + * Detects wireless stations actively scanning for APs + * + * Arguments: + * + * probe_reqs => number of probe requests during time delta it takes to trigger an alert + * + * probe_period => time period used to keep count of probe requests over + * + * expire_timeout => number of seconds to wait for removing a MAC address from + * the list of detected Netstumblers + * + * Effect: + * + * Sends an alert for each station it detects actively scanning for APs + * + * Comments: + * + * Any comments? + * + */ + + +#include "generators.h" +#include "log.h" +#include "detect.h" +#include "decode.h" +#include "event.h" +#include "plugbase.h" +#include "parser.h" +#include "mstring.h" +#include "debug.h" +#include "util.h" + + +#ifndef __SPP_ANTISTUMBLER_C__ +#define __SPP_ANTISTUMBLER_C__ +#include "spp_antistumbler.h" +#endif + + +#define MODNAME "spp_antistumbler" + +/* external globals from rules.c */ +extern char *file_name; +extern int file_line; + + +AntiStumblerData antistumbler_data; + +/* + * Function: SetupAntiStumbler() + * + * Purpose: Registers the preprocessor keyword and initialization + * function into the preprocessor list. This is the function that + * gets called from InitPreprocessors() in plugbase.c. + * + * Arguments: None. + * + * Returns: void function + * + */ +void SetupAntiStumbler() +{ + /* link the preprocessor keyword to the init function in + the preproc list */ + RegisterPreprocessor("antistumbler", AntiStumblerInit); + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Preprocessor: AntiStumbler is setup...\n");) +} + + +/* + * Function: AntiStumblerInit(u_char *) + * + * Purpose: Calls the argument parsing function, performs final setup on data + * structs, links the preproc function into the function list. + * + * Arguments: args => ptr to argument string + * + * Returns: void function + * + */ +void AntiStumblerInit(u_char *args) +{ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Preprocessor: AntiStumbler Initialized\n");); + + /* parse the argument list from the rules file */ + AntiStumblerParseArgs(args); + + /* Set the preprocessor function into the function list */ + AddFuncToPreprocList(AntiStumblerDetect); +/* AddFuncToCleanExitList(PreprocCleanExitFunction); */ +/* AddFuncToRestartList(PreprocRestartFunction); */ +} + + + +/* + * Function: AntiStumblerParseArgs(char *) + * + * Purpose: Process the preprocessor arguements from the rules file and + * initialize the preprocessor's data struct. This function doesn't + * have to exist if it makes sense to parse the args in the init + * function. + * + * Arguments: args => argument list + * + * Returns: void function + * + */ +void AntiStumblerParseArgs(char *args) +{ + int i, n, n_args, n_arg_args; + char **arg_toks = NULL, **arg_args = NULL; + + /* init preproc data with defaults */ + antistumbler_data.probe_reqs = ANTISTUMBLER_PROBE_REQS; + antistumbler_data.probe_period = ANTISTUMBLER_PROBE_PERIOD; + antistumbler_data.expire_timeout = ANTISTUMBLER_EXPIRE_TIMEOUT; + antistumbler_data.stumblers = NULL; + + if(args == NULL) + return; + + if(*args){ + + arg_toks = mSplit(args, ",", 3, &n_args, 0); + if(n_args != 3){ + FatalError("%s: %s (%d) => antistumbler configuration format: probe_reqs , probe_period , expire_timeout \n", + MODNAME, file_name, file_line); + } + + for(i = 0; i < n_args; i++){ + + arg_args = mSplit(arg_toks[i], " ", 2, &n_arg_args, 0); + if(n_arg_args != 2){ + FatalError("%s: %s (%d) => antistumbler configuration format: probe_reqs , probe_period , expire_timeout \n", + MODNAME, file_name, file_line); + } + + if(strcmp(arg_args[0], "probe_reqs") == 0){ + n = strtol(arg_args[1], NULL, 10); + if(n <= 0){ + FatalError("%s: %s (%d) => \"probe_reqs\" must be greater than 0\n", MODNAME, file_name, file_line); + } + antistumbler_data.probe_reqs = n; + } + else if(strcmp(arg_args[0], "probe_period") == 0){ + n = strtol(arg_args[1], NULL, 10); + if(n <= 0){ + FatalError("%s: %s (%d) => \"probe_period\" must be greater than 0\n", MODNAME, file_name, file_line); + } + antistumbler_data.probe_period = n; + } + else if(strcmp(arg_args[0], "expire_timeout") == 0){ + n = strtol(arg_args[1], NULL, 10); + if(n <= 0){ + FatalError("%s: %s (%d) => \"expire_timeout\" must be greater than 0\n", MODNAME, file_name, file_line); + } + antistumbler_data.expire_timeout = n; + } + else{ + FatalError("%s: %s (%d) => Invalid argument \"%s %s\"\n", MODNAME, file_name, file_line, arg_args[0], arg_args[1]); + } + } + } + else{ + FatalError("%s: %s (%d) => antistumbler configuration format: probe_reqs , probe_period , expire_timeout \n", + MODNAME, file_name, file_line); + } +} + +/* + * Function: AntiStumblerDetect(Packet *) + * + * Purpose: Perform the preprocessor's intended function. This can be + * simple (statistics collection) or complex (IP defragmentation) + * as you like. Try not to destroy the performance of the whole + * system by trying to do too much.... + * + * Arguments: p => pointer to the current packet data struct + * + * Returns: void function + * + */ +void AntiStumblerDetect(Packet *p) +{ + int on_list = 0; + time_t time_curr; + Stumbler *stumbler_ptr = NULL; + Event event; + char log_message[128]; + ProbeReq fixed_params; + Beacon beacon_body; + + time_curr = time(NULL); + + if(p->wifih == NULL) + return; + + + if(p->wifih->type == TYPE_MANAGEMENT && p->wifih->stype == STYPE_BEACON){ + beacon_body.ssid_id = p->wifih + _OFFSET_BEACON_SSID_ID; + beacon_body.ssid = p->wifih + _OFFSET_BEACON_SSID; + + if(beacon_body.ssid_id->len == 15 && beacon_body.cap_info->cap_ibss){ + if(strncmp(beacon_body.ssid, "Wavelan Network", 15) == 0){ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "%s: AdHoc network detected (SSID \"Wavelan Network\")\n");); + if(antistumbler_data.stumblers == NULL) + antistumbler_data.stumblers = AllocStumblerList(); + + stumbler_ptr = InsertStumbler(p->wifih->addr3, antistumbler_data.stumblers); + + snprintf(log_message, 128, "Detected possible Kismet use from %.2X:%.2X:%.2X:%.2X:%.2X:%.2X", + stumbler_ptr->addr[0], stumbler_ptr->addr[1], stumbler_ptr->addr[2], + stumbler_ptr->addr[3], stumbler_ptr->addr[4], stumbler_ptr->addr[5]); + SetEvent(&event, GENERATOR_SPP_ANTISTUMBLER, STUMBLER_DETECTED, 1, 4, 2, 0); +/* if(p->iph == NULL) */ /* ugh, the horrible hack arises once again */ +/* p->iph = (IPHdr *)calloc(1, sizeof(IPHdr)); */ + + CallAlertFuncs(p, log_message, NULL, &event); /* send alert */ + } + } + return; + } + + + if(p->wifih->type != TYPE_MANAGEMENT || p->wifih->stype != STYPE_PROBEREQ) + return; + + fixed_params.ssid_id = p->pkt + _OFFSET_PROBEREQ_SSID_ID; + fixed_params.ssid = p->pkt + _OFFSET_PROBEREQ_SSID; +/* fixed_params.rates_id = fixed_params.ssid + fixed_params.ssid_id->len; */ +/* fixed_params.rates = fixed_params.rates_id + sizeof(ElementID); */ + + if(fixed_params.ssid_id->len != 0){ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "%s: SSID in probe request not NULL\n", MODNAME);); + return; + } + + if(antistumbler_data.stumblers == NULL) + antistumbler_data.stumblers = AllocStumblerList(); + + stumbler_ptr = antistumbler_data.stumblers->head; + while(stumbler_ptr){ + + + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "%s: STA: %.2X:%.2X:%.2X:%.2X:%.2X:%.2X (probe_cnt: %d, ts_init: %d, ts_last: %d, ts_diff: %d)\n", + MODNAME, stumbler_ptr->addr[0], stumbler_ptr->addr[1], stumbler_ptr->addr[2], + stumbler_ptr->addr[3], stumbler_ptr->addr[4], stumbler_ptr->addr[5], + stumbler_ptr->probe_cnt, stumbler_ptr->ts_init, stumbler_ptr->ts_last, + stumbler_ptr->ts_last - stumbler_ptr->ts_init);); + + if(memcmp(p->wifih->addr2, stumbler_ptr->addr, 6) == 0){ /* check to see if STA is on list */ + on_list = 1; + stumbler_ptr->probe_cnt++; + stumbler_ptr->ts_last = time_curr; + + + if(stumbler_ptr->probe_cnt >= antistumbler_data.probe_reqs){ + + if(stumbler_ptr->alert_flag == 0){ + stumbler_ptr->alert_flag = 1; + + snprintf(log_message, 128, "Detected Netstumbler traffic from %.2X:%.2X:%.2X:%.2X:%.2X:%.2X", + stumbler_ptr->addr[0], stumbler_ptr->addr[1], stumbler_ptr->addr[2], + stumbler_ptr->addr[3], stumbler_ptr->addr[4], stumbler_ptr->addr[5]); + + SetEvent(&event, GENERATOR_SPP_ANTISTUMBLER, STUMBLER_DETECTED, 1, 4, 2, 0); +/* if(p->iph == NULL) */ /* horrible hack to get this to show up in ACID */ +/* p->iph = (IPHdr *)calloc(1, sizeof(IPHdr)); */ + + CallAlertFuncs(p, log_message, NULL, &event); /* send alert */ + } + } + + if(stumbler_ptr->ts_last - stumbler_ptr->ts_init >= antistumbler_data.probe_period){ + stumbler_ptr->ts_init = time_curr; + stumbler_ptr->probe_cnt = 1; + } + + } + if(time_curr - stumbler_ptr->ts_last >= antistumbler_data.expire_timeout){ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "%s: Removing expired STA (%.2X:%.2X:%.2X:%.2X:%.2X:%.2X) from stumbler list\n", + MODNAME, stumbler_ptr->addr[0], stumbler_ptr->addr[1], stumbler_ptr->addr[2], + stumbler_ptr->addr[3], stumbler_ptr->addr[4], stumbler_ptr->addr[5]);); + stumbler_ptr = RemoveStumbler(stumbler_ptr, antistumbler_data.stumblers); + continue; + } + + stumbler_ptr = stumbler_ptr->next; + } + + if(!on_list){ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "%s: Adding STA (%.2X:%.2X:%.2X:%.2X:%.2X:%.2X) to stumbler list\n", MODNAME, + p->wifih->addr2[0], p->wifih->addr2[1], p->wifih->addr2[2], + p->wifih->addr2[3], p->wifih->addr2[4], p->wifih->addr2[5]);); + + InsertStumbler(p->wifih->addr2, antistumbler_data.stumblers); + } +} + + + + void PreprocCleanExitFunction(int signal) +{ + /* clean exit code goes here */ +} + +void PreprocRestartFunction(int signal) +{ + /* restart code goes here */ +} + + +StumblerList *AllocStumblerList(void){ + return (StumblerList *)calloc(1, sizeof(StumblerList)); +} + + +void DestroyStumblerList(StumblerList *list){ +#warning "Implement DestroyStumblerList()" +} + + +/* + * Function: InsertStumbler(u_int8_t *, StumblerList *) + * + * Purpose: Creates a Stumbler node from a byte array and inserts + * it into the specified StumblerList + * + * Arguments: addr => byte array containing a MAC address + * list => StumblerList to insert new node in + * + * Returns: pointer to newly inserted Stumbler node or NULL + * if bssid or list is NULL + * + */ + +Stumbler *InsertStumbler(u_int8_t *addr, StumblerList *list){ + Stumbler *stumbler_ptr = NULL; + + if(list == NULL || addr == NULL) + return NULL; + + /* allocate new Stumbler node */ + stumbler_ptr = (Stumbler *)malloc(sizeof(Stumbler)); + memcpy(stumbler_ptr->addr, addr, 6); + stumbler_ptr->alert_flag = 0; + stumbler_ptr->probe_cnt = 1; + stumbler_ptr->ts_init = time(NULL); + stumbler_ptr->ts_last = stumbler_ptr->ts_init; + stumbler_ptr->next = NULL; + stumbler_ptr->prev = NULL; + + if(list->head == NULL && list->tail == NULL){ /* if empty list, set head and tail */ + list->head = stumbler_ptr; + list->tail = stumbler_ptr; + } + else{ /* if already a tail, link new node in */ + stumbler_ptr->prev = list->tail; + list->tail->next = stumbler_ptr; + list->tail = stumbler_ptr; + } + + return stumbler_ptr; /* return pointer to new Stumbler node */ +} + + + +/* + * Function: RemoveStumbler(Stumbler *, StumblerList *) + * + * Purpose: Removes a Stumbler node from a StumblerList + * + * Arguments: node => pointer to Stumbler node to be removed + * list => StumblerList to remove node from + * + * Returns: next Stumbler node in the list or NULL if one + * does not exist + */ + +Stumbler *RemoveStumbler(Stumbler *node, StumblerList *list){ + Stumbler *stumbler_ptr; + + if(list == NULL) + return node; + + if(node == list->head){ + if((list->head = node->next) == NULL) + list->tail = NULL; + else + node->next->prev = NULL; + } + else{ + if((node->next->prev = node->next) == NULL) + list->tail = node->prev; + else + node->next->prev = node->prev; + } + + stumbler_ptr = node->next; + free(node); + + return stumbler_ptr; +} + + + Index: snort/src/preprocessors/spp_antistumbler.h diff -u /dev/null snort/src/preprocessors/spp_antistumbler.h:1.2 --- /dev/null Sat Nov 5 19:10:45 2005 +++ snort/src/preprocessors/spp_antistumbler.h Thu Jul 24 02:32:37 2003 @@ -0,0 +1,166 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: spp_antistumbler.h,v 1.2 2003/07/24 06:32:37 andrew Exp $ */ + +#include "snort.h" + +#ifndef __SPP_ANTISTUMBLER_H__ +#define __SPP_ANTISTUMBLER_H__ + +#ifdef __SPP_ANTISTUMBLER_C__ + +#define ANTISTUMBLER_PROBE_REQS 5 +#define ANTISTUMBLER_PROBE_PERIOD 3 +#define ANTISTUMBLER_EXPIRE_TIMEOUT 60 + +typedef struct _Stumbler { + u_int8_t addr[6]; + int alert_flag; + int probe_cnt; + time_t ts_init, ts_last; + struct _Stumbler *next, *prev; +} Stumbler; + +typedef struct _StumblerList { + struct _Stumbler *head, *tail; +} StumblerList; + +typedef struct _AntiStumblerData +{ + int probe_reqs; + time_t probe_period; + time_t expire_timeout; + StumblerList *stumblers; +} AntiStumblerData; + + +typedef enum { /* 802.11 frame types */ + TYPE_INVALID = -1, + TYPE_MANAGEMENT = 0x00, + TYPE_CONTROL = 0x01, + TYPE_DATA = 0x02 +} wifi_type_t; + + +typedef enum { /* 802.11 management frame subtypes */ + STYPE_ASSOCREQ = 0x00, /* Subtypes are already AND'ed with their corresponding Types */ + STYPE_ASSOCRESP = 0x01, /* to prevent false positives and the need for checking the type */ + STYPE_REASSOC_REQ = 0x02, /* independently */ + STYPE_REASSOC_RESP = 0x03, + STYPE_PROBEREQ = 0x04, + STYPE_PROBERESP = 0x05, + STYPE_BEACON = 0x08, + STYPE_ATIM = 0x09, + STYPE_DIASSOC = 0x0a, + STYPE_AUTH = 0x0b, + STYPE_DEAUTH = 0x0c, + + STYPE_INVALID = 0x0d, + +/* 802.11 control frame subtypes */ + STYPE_PS = 0x0a, + STYPE_RTS = 0x0b, + STYPE_CTS = 0x0c, + STYPE_ACK = 0x0d, + STYPE_CFEND = 0x0e, + STYPE_CFEND_CFACK = 0x0f, + +/* 802.11 data frame subtypes */ + STYPE_DATA = 0x00, + STYPE_CFACK = 0x01, + STYPE_CFPOLL = 0x02, + STYPE_CFACK_CFPOLL = 0x03, + STYPE_NULLFUNC = 0x04, + STYPE_CFACK_NULLFUNC = 0x05, + STYPE_CFPOLL_NULLFUNC = 0x06, + STYPE_CFACK_CFPOLL_NULLFUNC = 0x07 +} wifi_stype_t; + +typedef struct _ElementID{ /* 802.11 element id */ + u_int8_t id; + u_int8_t len; +} ElementID; + +typedef struct _CapInfo{ /* 802.11 capability information */ + u_int16_t cap_ess:1; + u_int16_t cap_ibss:1; + u_int16_t cap_cfpoll:1; + u_int16_t cap_cfpoll_req:1; + u_int16_t cap_wep:1; + u_int16_t cap_reserved:11; +} CapInfo; + +#define _OFFSET_MANAGEMENT_BODY sizeof(WifiHdr) - 6 + +typedef struct _ProbeReq{ /* 802.11 probe request body */ +#define _OFFSET_PROBEREQ_SSID_ID 0 + ElementID *ssid_id; +#define _OFFSET_PROBEREQ_SSID _OFFSET_PROBEREQ_SSID_ID + sizeof(ElementID) + u_int8_t *ssid; + ElementID *rates_id; + u_int8_t *rates; +} ProbeReq; + + + + +typedef struct _Beacon{ /* relevant portion of beacon frame + for detecting Orinoco cards in monitor mode */ +#define _OFFSET_TIMESTAMP 0x00 + u_int32_t *timestamp1; + u_int32_t *timestamp2; + +#define _OFFSET_BEACON_INT _OFFSET_TIMESTAMP + 2 * sizeof(u_int32_t) + u_int16_t *beacon_interval; + +#define _OFFSET_BEACON_CAP_INFO _OFFSET_BEACON_INT + sizeof(u_int16_t) + CapInfo *cap_info; + +#define _OFFSET_BEACON_SSID_ID _OFFSET_BEACON_CAP_INFO + sizeof(CapInfo) + ElementID *ssid_id; +#define _OFFSET_BEACON_SSID _OFFSET_BEACON_SSID_ID + sizeof(ElementID) + u_int8_t *ssid; + + ElementID *rates_id; + u_int8_t *rates; + + u_int8_t *current_chan; + + /* we don't care about the rest right now */ +} Beacon; + +#define DECODE_PARAMS + +StumblerList *AllocStumblerList(void); +void DestroyStumblerList(StumblerList *); +Stumbler *InsertStumbler(u_int8_t *, StumblerList *); +Stumbler *RemoveStumbler(Stumbler *, StumblerList *); + +#endif /* __SPP_ANTISBUMBLER_C__ */ + +/* list of function prototypes for this preprocessor */ +void SetupAntiStumbler(); +void AntiStumblerInit(u_char *); +void AntiStumblerParseArgs(char *); +void AntiStumblerDetect(Packet *); +void PreprocRestartFunction(int); +void PreprocCleanExitFunction(int); + + +#endif /* __SPP_ANTISTUMBLER_H__ */ Index: snort/src/preprocessors/spp_auth_flood.c diff -u /dev/null snort/src/preprocessors/spp_auth_flood.c:1.2 --- /dev/null Sat Nov 5 19:10:45 2005 +++ snort/src/preprocessors/spp_auth_flood.c Fri Jun 24 17:22:16 2005 @@ -0,0 +1,672 @@ +/* +** Copyright (C) 2004 Sebastien Gracia +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Copyright disclaimers: +** The Directeur Central de la sécurité des systèmes d'information hereby +** disclaims all copyright interest in the changes and enhancements +** made by sebastien Gracia. +** 5th Fev 2004. +*/ + + +/* spp_auth_flood + * + * Purpose: Detects wireless access point flooded with auth frames. + * + * auth_threshold => number of auth frames during time delta it takes + * to trigger an alert + * + * expire_timeout => time period used to keep count of auth frames + * + * target_limit => maximum number of access point inserted inside authAP + * mempool + * + * prune_period => number of seconds to wait for looking after some decayed + * flooded AP inside mempool + * + * Effect: + * + * Sends an alert for each access point having been detected as flooded + * with auth frames. + * + * Comments: + * + * Any comments? + * + */ + +#include + +#include "plugbase.h" +#include "mstring.h" +#include "debug.h" +#include "log.h" +#include "wifi_statetable.h" +#include "generators.h" +#include "ubi_BinTree.h" +#include "mempool.h" +#include "detect.h" +#include "util.h" + + +#ifndef __SPP_AUTH_FLOOD__C__ +#define __SPP_AUTH_FLOOD_C__ +#include "spp_auth_flood.h" +#endif + +#define MODNAME "spp_auth_flood" + +AuthFloodData auth_flood_data; +char logpath[STD_BUF]; + +/* external globals from rules.c */ + +extern char *file_name; +extern int file_line; + + +/* + * Function: SetupAuthFlood() + * + * Purpose: Registers the preprocessor keyword and initialization + * function into the preprocessor list. This is the function that + * gets called from InitPreprocessors() in plugbase.c. + * + * Arguments: None. + * + * Returns: void function + * + */ +void SetupAuthFlood() +{ + /* link the preprocessor keyword to the init function in + the preproc list */ + + RegisterPreprocessor("auth_flood", AuthFloodInit); + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Preprocessor: auth_flood is setup...\n");); + return; +} + + +/* + * Function: AuthFloodInit(u_char *) + * + * Purpose: Calls the argument parsing function, performs final setup on data + * structs, links the preproc function into the function list. + * + * Arguments: args => ptr to argument string + * + * Returns: void function + * + */ +void AuthFloodInit(u_char *args) +{ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Preprocessor: auth_flood Initialized\n");); + + memset(&auth_flood_data, 0, sizeof(AuthFloodData)); + + /* parse the argument list from the rules file */ + + AuthFloodParseArgs(args); + + auth_flood_data.AuthAPsPtr = &auth_flood_data.AuthAPs; + + /* set up the flooded AP tree */ + + ubi_trInitTree(auth_flood_data.AuthAPsPtr, authAPCompareFunc, 0); + + /* set up the node pools */ + + if(mempool_init(&auth_flood_data.AuthAPPool, + auth_flood_data.target_limit, + sizeof(AuthAP))){ + FatalError("ERROR: Can't initialize mempool for flooded APs\n"); + } + + /* setup logpath */ + + strncpy(logpath, pv.log_dir, STD_BUF); + strncat(logpath, "/authflood.log", STD_BUF); + + auth_flood_data.logfile = fopen(logpath, "a+"); + if(auth_flood_data.logfile == NULL){ + FatalError("Can't open logfile: %s", logpath); + } + auth_flood_data.offset_alert_flag = WSTInit(sizeof(u_int8_t)); + auth_flood_data.offset_nbr = WSTInit(sizeof(u_int16_t)); + auth_flood_data.offset_time = WSTInit(sizeof(struct timeval)); + + /* Set the preprocessor function into the function list */ + + AddFuncToPreprocList(AuthFloodDetect); + + AddFuncToCleanExitList(AuthFloodCleanExitFunction, &auth_flood_data); + AddFuncToRestartList(AuthFloodRestartFunction, &auth_flood_data); + return; +} + + +/* + * Function: AuthFloodParseArgs(char *) + * + * Purpose: Process the preprocessor arguments from the rules file and + * initialize the preprocessor's data struct. This function doesn't + * have to exist if it makes sense to parse the args in the init + * function. + * + * Arguments: args => argument list + * + * Returns: void function + * + */ +void AuthFloodParseArgs(char *args) +{ + int i, n, n_args, n_arg_args; + char **arg_toks = NULL, **arg_args = NULL; + + /* init preproc data with defaults */ + + auth_flood_data.auth_threshold = AUTH_FLOOD_THRESHOLD; + auth_flood_data.expire_timeout = AUTH_FLOOD_EXPIRE_TIMEOUT; + auth_flood_data.target_limit = AUTH_FLOOD_TARGET_LIMIT; + auth_flood_data.prune_period = AUTH_FLOOD_PRUNE_PERIOD; + + if(args == NULL){ + LogMessage("auth_flood initialized with defaults:\n"); + LogMessage(" %s: %u\n", AUTH_OPT_threshold, auth_flood_data.auth_threshold); + LogMessage(" %s: %u\n", AUTH_OPT_EXPIRE_TIMEOUT, auth_flood_data.expire_timeout); + LogMessage(" %s: %u\n", AUTH_OPT_TARGET_LIMIT, auth_flood_data.target_limit); + LogMessage(" %s: %u\n", AUTH_OPT_PRUNE_PERIOD, auth_flood_data.prune_period); + + /* Update wifi_statetable timeout */ + + WSTUpdateTimeout(auth_flood_data.expire_timeout); + return; + } + + arg_toks = mSplit(args, ",", 4, &n_args, 0); + if(n_args != 4){ + FatalError("%s: %s (%d) => auth_flood configuration format:" + " auth_threshold , expire_timeout ,\ntarget_limit ," + " prune_period \n", + MODNAME, file_name, file_line); + } + + for(i = 0; i < n_args; i++){ + arg_args = mSplit(arg_toks[i], " ", 2, &n_arg_args, 0); + if(n_arg_args != 2){ + FatalError("%s: %s (%d) => auth_flood configuration format:" + " auth_threshold , expire_timeout ,\ntarget_limit ," + " prune_period \n", + MODNAME, file_name, file_line); + } + + if(strcmp(arg_args[0], "auth_threshold") == 0){ + n = strtol(arg_args[1], NULL, 10); + if(n <= 0){ + FatalError("%s: %s (%d) => \"auth_threshold\" must be greater than 0\n" + , MODNAME, file_name, file_line); + } + auth_flood_data.auth_threshold = n; + } + else if(strcmp(arg_args[0], "expire_timeout") == 0){ + n = strtol(arg_args[1], NULL, 10); + if(n <= 0){ + FatalError("%s: %s (%d) => \"expire_timeout\" must be greater than 0\n", + MODNAME, file_name, file_line); + } + auth_flood_data.expire_timeout = n; + } + else if(strcmp(arg_args[0], "target_limit") == 0){ + n = strtol(arg_args[1], NULL, 10); + if(n <= 0){ + FatalError("%s: %s (%d) => \"target_limit\" must be greater than 0\n", + MODNAME, file_name, file_line); + } + auth_flood_data.target_limit = n; + } + else if(strcmp(arg_args[0], "prune_period") == 0){ + n = strtol(arg_args[1], NULL, 10); + if(n <= 0){ + FatalError("%s: %s (%d) => \"prune_period\" must be greater than 0\n", + MODNAME, file_name, file_line); + } + auth_flood_data.prune_period = n; + } + else{ + FatalError("%s: %s (%d) => Invalid argument \"%s %s\"\n", + MODNAME, file_name, file_line, arg_args[0], arg_args[1]); + } + } + + if(auth_flood_data.expire_timeout <= auth_flood_data.prune_period){ + FatalError("%s: %s (%d) => \"expire_timeout\" must be greater than prune_period\n", + MODNAME, file_name, file_line); + } + + LogMessage("auth_flood arguments:\n"); + LogMessage(" %s: %u\n", AUTH_OPT_threshold, auth_flood_data.auth_threshold); + LogMessage(" %s: %u\n", AUTH_OPT_EXPIRE_TIMEOUT, auth_flood_data.expire_timeout); + LogMessage(" %s: %u\n", AUTH_OPT_TARGET_LIMIT, auth_flood_data.target_limit); + LogMessage(" %s: %u\n", AUTH_OPT_PRUNE_PERIOD, auth_flood_data.prune_period); + + /* Update wifi_statetable timeout */ + + WSTUpdateTimeout(auth_flood_data.expire_timeout); + return; +} + + +/* + * Function: AuthFloodDetect(Packet *) + * + * Purpose: Detect wireless auth flood traffic + * + * Arguments: p => pointer to the current packet data struct + * + * Returns: void function + * + */ +void AuthFloodDetect(Packet *p) +{ + wst_flag_type flag_addr; + u_int32_t pruned; + u_int16_t *n_auth_ptr; + u_int8_t *alert_flag_ptr; + struct timeval wst_tv, tv_diff; + Event event; + char outstring[255]; + + /* Cull any expired sessions out */ + + if(p->pkth->ts.tv_sec >= (auth_flood_data.prune_time.tv_sec + auth_flood_data.prune_period)){ + DEBUG_WRAP(DebugMessage(DEBUG_AUTHFLOOD, + "Pruning out AP flooded memory pool due to expired prune_period\n");); + auth_flood_data.prune_time.tv_sec = p->pkth->ts.tv_sec; + pruned=PruneAuthAPs(p->pkth->ts.tv_sec); + DEBUG_WRAP(DebugMessage(DEBUG_AUTHFLOOD, + "%u AP removed from AuthAP memory pool\n", pruned);); + } + + DEBUG_WRAP(DebugMessage(DEBUG_AUTHFLOOD, + "AP flooded with auth frames count: %u\n", + ubi_trCount(auth_flood_data.AuthAPsPtr));); + + if(p->wifih == NULL){ + return; + } + + /* Is it an auth frame? */ + + if((p->wifih->type != TYPE_MANAGEMENT) || (p->wifih->stype != STYPE_AUTH)){ + return; + } + + flag_addr = WST_FLAG_DESTADDR; + + /* Calls WSTMain to fill up p->wstidx.cache_addr[flag_addr] with memory address corresponding + * with the place where destination MAC address (target) is recorded inside WST. */ + + WSTMain(p, flag_addr); + + if( p->wstidx.cache_addr[flag_addr] == WST_FAILED){ + return; + } + + /* check wheter or not an alert is already reported */ + + alert_flag_ptr = (u_int8_t *) ((u_int8_t *) (p->wstidx.cache_addr[flag_addr] + + auth_flood_data.offset_alert_flag)); + + /* n_auth_ptr points to the number of auth frame received by target + according to expire_timeout condition */ + + n_auth_ptr = (u_int16_t *) ((u_int8_t *) (p->wstidx.cache_addr[flag_addr] + + auth_flood_data.offset_nbr)); + if(*alert_flag_ptr){ + + /* Alert has already been sent. Purpose is now to update WST time data in order + to avoid concerned auth flooded AP to be removed from auth flooded AP + memory pool throught PruneAuthAPs function and uptade received auth + frames number */ + + memcpy((u_int8_t *) (p->wstidx.cache_addr[flag_addr] + auth_flood_data.offset_time), + &p->pkth->ts, sizeof(struct timeval)); + *n_auth_ptr = (*n_auth_ptr) + 1 ; + return; + } + + memcpy(&wst_tv, ((u_int8_t *) (p->wstidx.cache_addr[flag_addr] + auth_flood_data.offset_time)), + sizeof(struct timeval)); + tv_diff = WSTTimevalSubtract(p->pkth->ts, wst_tv); + + /* check wether or not dezs station should be considered as a new potential flooded AP. + * Update WST data */ + + if( tv_diff.tv_sec > auth_flood_data.expire_timeout ){ + + /* dest station is a new potential AP flooded with auth frames. + * Update WST data */ + + *n_auth_ptr = 1; + memcpy((u_int8_t *) (p->wstidx.cache_addr[flag_addr] + auth_flood_data.offset_time), + &p->pkth->ts, sizeof(struct timeval)); + } + else{ + *n_auth_ptr = (*n_auth_ptr) + 1 ; + } + + /* check whether or not threshold is reached */ + + if( *n_auth_ptr == auth_flood_data.auth_threshold){ + + /* alert condition are reached */ + + memcpy((u_int8_t *) (p->wstidx.cache_addr[flag_addr] + auth_flood_data.offset_time), + &p->pkth->ts, sizeof(struct timeval)); + (*alert_flag_ptr) = 1; + + snprintf(outstring, 255, AUTHFLOOD_PREFIX_STR + "\nAddr src: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x -> Addr dst: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x" + ", Bssid: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x.", + p->wifih->addr2[0], p->wifih->addr2[1], p->wifih->addr2[2], + p->wifih->addr2[3], p->wifih->addr2[4], p->wifih->addr2[5], + p->wifih->addr1[0], p->wifih->addr1[1], p->wifih->addr1[2], + p->wifih->addr1[3], p->wifih->addr1[4], p->wifih->addr1[5], + p->wifih->addr3[0], p->wifih->addr3[1], p->wifih->addr3[2], + p->wifih->addr3[3], p->wifih->addr3[4], p->wifih->addr3[5]); + + DEBUG_WRAP(DebugMessage(DEBUG_AUTHFLOOD, "%s\n", outstring);); + + SetEvent(&event, GENERATOR_SPP_AUTHFLOOD, AUTHFLOOD_DETECTED, 1, 0, 0, 0); + CallAlertFuncs(p, outstring, NULL, &event); /* send alert & log data */ + AuthAPLog(p, 0); + + /* insert dest station inside authAP mempool */ + + AddAuthAP(p->wstidx.cache_addr[flag_addr]); + } + return; +} + + +/* + * Function: int authAPCompareFunc(ubi_trItemPtrItemPtr, + * ubi_trNodePtr NodePtr) + * + * Purpose: Callback function used by splay trees to sort authAP node + * + * Arguments: + * + * Returns: + * + */ +int authAPCompareFunc(ubi_trItemPtr ItemPtr, ubi_trNodePtr NodePtr) +{ + AuthAP *A = (AuthAP *) NodePtr; + AuthAP *B = (AuthAP *) ItemPtr; + int32_t memcmp_result; + + + memcmp_result = memcmp(&A->addr[0], &B->addr[0], 6); + if(memcmp_result < 0){ + return 1; + } + else if(memcmp_result > 0){ + return -1; + } + return 0; +} + + +/* + * Function: void AddAuthAP(u_int32_t wst_addr) + * + * Purpose: Adds a new AP to the AP flooded with auth frames tree + * + * Arguments: wst_addr => memory address where MAC address is recorded inside wst. + * + * Returns: + * + */ + +void AddAuthAP(u_int32_t wst_addr) +{ + AuthAP *authap = NULL; + MemBucket *mb = NULL; + + /* borrow a AP node from the AP node pool */ + + mb = mempool_alloc(&auth_flood_data.AuthAPPool); + + if(mb == NULL){ + DEBUG_WRAP(DebugMessage(DEBUG_AUTHFLOOD, "out of AP Nodes\n");); + return; + } + + authap = (AuthAP *) mb->data; + authap->bucket = mb; + + /* fill in the authAP struct */ + authap->wst_addr = wst_addr; + memcpy(&authap->addr[0], (u_int8_t *) wst_addr, 6); + + DEBUG_WRAP(DebugMessage(DEBUG_AUTHFLOOD, + "Assigning a AP with MAC addr of" + " %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", + authap->addr[0],authap->addr[1],authap->addr[2],authap->addr[3],authap->addr[4],authap->addr[5]);); + + /* add this flooded AP to AP tree */ + + if(ubi_sptInsert(auth_flood_data.AuthAPsPtr, + (ubi_btNodePtr)authap, + (ubi_btNodePtr)authap, NULL) == ubi_trFALSE){ + DEBUG_WRAP(DebugMessage(DEBUG_AUTHFLOOD, + "Insert into flooded AP tree failed\n");); + } + else{ + DEBUG_WRAP(DebugMessage(DEBUG_AUTHFLOOD, + "Insert into flooded AP tree successful\n");); + } + return; +} + + +/* + * Function: u_int32_t PruneAuthAPs(u_int32_t now) + * + * Purpose: Checks whether or not AP inserted inside flooded AP tree are still + * auth flooded or not. + * If not, removes concerned APs from flooded AP tree and calls AUTHAPLogs function. + * + * Arguments: now => packet's capture time in sec + * + * Returns: number of APs removed from flooded AP tree + * + */ +u_int32_t PruneAuthAPs(u_int32_t now) +{ + AuthAP *idx; + u_int32_t pruned = 0; + u_int32_t authap_sec; + u_int8_t *alert_flag_ptr; + + DEBUG_WRAP(DebugMessage(DEBUG_AUTHFLOOD, + "Prune flooded AP called now: " + " %u , count: %u\n", + now, ubi_trCount(auth_flood_data.AuthAPsPtr));); + + if(ubi_trCount(auth_flood_data.AuthAPsPtr) < 1){ + DEBUG_WRAP(DebugMessage(DEBUG_AUTHFLOOD, + "exit PruneAuthAP function since flooded AP tree" + " is free\n");); + return(0); + } + + /* number of thing that need to be deleted */ + + idx = (AuthAP *) ubi_btFirst((ubi_btNodePtr)auth_flood_data.AuthAPsPtr->root); + + if(idx == NULL){ + return(0); + } + + do{ + authap_sec = *((u_int32_t *) (idx->wst_addr + auth_flood_data.offset_time)); + if((authap_sec + auth_flood_data.expire_timeout) < now){ + + /* AP shouldn't be much more considered as a auth flooded one. + Removes it from authAP pool */ + + alert_flag_ptr = (u_int8_t *) (idx->wst_addr + auth_flood_data.offset_alert_flag); + *alert_flag_ptr = 0; + + AuthAPLog(NULL, idx->wst_addr); + AuthAP *savidx = idx; + if(ubi_trCount(auth_flood_data.AuthAPsPtr) > 1){ + idx = (AuthAP *) ubi_btNext((ubi_btNodePtr)idx); + DEBUG_WRAP(DebugMessage(DEBUG_AUTHFLOOD, + "pruning stale flooded AP\n");); + DeleteAuthAP(savidx); + pruned++; + } + else{ + DeleteAuthAP(savidx); + pruned++; + return(pruned); + } + } + else{ + if(idx != NULL && ubi_trCount(auth_flood_data.AuthAPsPtr)){ + idx = (AuthAP *) ubi_btNext((ubi_btNodePtr)idx); + } + else{ + return pruned; + } + } + } while(idx != NULL); + + return pruned; +} + + +/* + * Function: void DeleteAuthAP(AuthAP *authap) + * + * Purpose: removed flooded auth AP from authAP mempool + * + * Arguments: + * + * Returns: + * + */ +void DeleteAuthAP(AuthAP *authap) +{ +AuthAP *oldauthap; + +oldauthap = (AuthAP *) ubi_sptRemove(auth_flood_data.AuthAPsPtr, + (ubi_btNodePtr) authap); +mempool_free(&auth_flood_data.AuthAPPool,authap->bucket); + return; +} + + +/* + * Function: void AUTHAPLog(Packet *p, u_int32_t wst_addr) + * + * Purpose: Called either when AP authentication flood is detected or finished. + * Logs data to a text file: auth_flood_data.logfile. + * + * Arguments: + * + * Returns: + * + */ +void AuthAPLog(Packet *p, u_int32_t wst_addr) +{ + char timestamp[TIMEBUF_SIZE]; + + if(p){ + ts_print((struct timeval *) &p->pkth->ts, timestamp); + fprintf(auth_flood_data.logfile, "\n%s Auth flood reported\n", timestamp); + PrintWifiHeader(auth_flood_data.logfile, p); + } + else{ + ts_print((struct timeval *) (wst_addr + auth_flood_data.offset_time), timestamp); + fprintf(auth_flood_data.logfile, "\n%s End Auth flood :" + " -> Addr dst: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x,\n" + "%u auth frame reported.\n", + timestamp, + *((u_int8_t *)(wst_addr)), *((u_int8_t *)(wst_addr + 1)), *((u_int8_t *)(wst_addr + 2)), + *((u_int8_t *)(wst_addr + 3)), *((u_int8_t *)(wst_addr + 4)), *((u_int8_t *)(wst_addr + 5)), + *((u_int16_t*)(wst_addr + auth_flood_data.offset_nbr))); + } + fflush(auth_flood_data.logfile); + return; +} + + +/* + * Function: void AuthCleanExitFunction(int, void *) + * + * Purpose: + * + * Arguments: + * + * Returns: + */ +void AuthFloodCleanExitFunction(int signal, void *arg) +{ + AuthFloodData *dfd_ptr = (AuthFloodData *) arg; + + DEBUG_WRAP(DebugMessage(DEBUG_AUTHFLOOD, "AuthFloodCleanExitFunction\n");); + + if(fclose(dfd_ptr->logfile)) + LogMessage("%s: fclose function failed while snort exiting: %s\n", + MODNAME, strerror(errno)); + return; +} + + + +/* + * Function: void AuthFloodCleanRestartFunction(int, void *) + * + * Purpose: + * + * Arguments: + * + * Returns: + */ +void AuthFloodRestartFunction(int signal, void *arg) +{ + AuthFloodData *dfd_ptr = (AuthFloodData *) arg; + + DEBUG_WRAP(DebugMessage(DEBUG_AUTHFLOOD, "AuthFloodRestartFunction\n");); + + if(fclose(dfd_ptr->logfile)) + LogMessage("%s: fclose function failed while snort restarting: %s\n", + MODNAME, strerror(errno)); + return; +} + + + + + + + Index: snort/src/preprocessors/spp_auth_flood.h diff -u /dev/null snort/src/preprocessors/spp_auth_flood.h:1.2 --- /dev/null Sat Nov 5 19:10:45 2005 +++ snort/src/preprocessors/spp_auth_flood.h Fri Jun 24 17:22:16 2005 @@ -0,0 +1,98 @@ +/* +** Copyright (C) 2004 sebastien Gracia +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Copyright disclaimers: +** The Directeur Central de la sécurité des systèmes d'information hereby +** disclaims all copyright interest in the changes and enhancements +** made by sebastien Gracia. +** 5th Fev 2004. +*/ + + +#ifndef __SPP_AUTH_FLOOD_H__ +#define __SPP_AUTH_FLOOD_H__ + + +/* I N C L U D E S +*******************************************************************************/ +#include "snort.h" + + +/* D E F I N E S +*******************************************************************************/ + +#define AUTH_OPT_threshold "auth-threshold" +#define AUTH_OPT_EXPIRE_TIMEOUT "expire_timeout" +#define AUTH_OPT_TARGET_LIMIT "target_limit" +#define AUTH_OPT_PRUNE_PERIOD "prune_period" + + +#define AUTH_FLOOD_THRESHOLD 100 +#define AUTH_FLOOD_EXPIRE_TIMEOUT 60 +#define AUTH_FLOOD_TARGET_LIMIT 10 +#define AUTH_FLOOD_PRUNE_PERIOD 30 + +typedef struct _AuthFloodData +{ + ubi_trRoot AuthAPs; + ubi_trRootPtr AuthAPsPtr; + + MemPool AuthAPPool; + + u_int16_t offset_alert_flag; + u_int16_t offset_nbr; + u_int16_t offset_time; + + u_int32_t auth_threshold; + u_int32_t expire_timeout; + u_int32_t target_limit; + u_int32_t prune_period; + + struct timeval prune_time; + + /** Global Program Data **/ + FILE *logfile; +} AuthFloodData; + +/* this represent the authenticated station */ +typedef struct _AuthAP +{ + ubi_trNode Node; /* for the splay tree */ + MemBucket *bucket; + + u_int32_t wst_addr; + u_int8_t addr[6]; +} AuthAP; + + +/* P R O T O T Y P E S +*******************************************************************************/ + +void SetupAuthFlood(); +void AuthFloodInit(u_char *); +void AuthFloodParseArgs(char *); +void AuthFloodDetect(Packet *); +int authAPCompareFunc(ubi_trItemPtr, ubi_trNodePtr); +void AddAuthAP(u_int32_t); +u_int32_t PruneAuthAPs(u_int32_t); +void DeleteAuthAP(AuthAP *); +void AuthAPLog(Packet *, u_int32_t); +void AuthFloodRestartFunction(int, void *); +void AuthFloodCleanExitFunction(int, void *); + + +#endif /* __SPP_DESFLOOD_H__ */ Index: snort/src/preprocessors/spp_deauth_flood.c diff -u /dev/null snort/src/preprocessors/spp_deauth_flood.c:1.2 --- /dev/null Sat Nov 5 19:10:45 2005 +++ snort/src/preprocessors/spp_deauth_flood.c Fri Jun 24 17:22:16 2005 @@ -0,0 +1,671 @@ +/* +** Copyright (C) 2004 Sebastien Gracia +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Copyright disclaimers: +** The Directeur Central de la sécurité des systèmes d'information hereby +** disclaims all copyright interest in the changes and enhancements +** made by sebastien Gracia. +** 5th Fev 2004. +*/ + + +/* spp_deauth_flood + * + * Purpose: Detects wireless station flooded with dehaut frames. + * + * deauth_threshold => number of deauth frames during time delta it takes + * to trigger an alert + * + * expire_timeout => time period used to keep count of deauth frames + * + * target_limit => maximum number of station inserted inside deauthstation + * mempool + * + * prune_period => number of seconds to wait for looking after some decayed + * deauthstations inside mempool + * + * Effect: + * + * Sends an alert for each station having been detected as flooded + * with deauth frames. + * + * Comments: + * + * Any comments? + * + */ + +#include + +#include "plugbase.h" +#include "mstring.h" +#include "debug.h" +#include "log.h" +#include "wifi_statetable.h" +#include "generators.h" +#include "ubi_BinTree.h" +#include "mempool.h" +#include "detect.h" +#include "util.h" + + +#ifndef __SPP_DEAUTH_FLOOD__C__ +#define __SPP_DEAUTH_FLOOD_C__ +#include "spp_deauth_flood.h" +#endif + +#define MODNAME "spp_deauth_flood" + +DeauthFloodData deauth_flood_data; +char logpath[STD_BUF]; + +/* external globals from rules.c */ + +extern char *file_name; +extern int file_line; + + +/* + * Function: SetupDeauthFlood() + * + * Purpose: Registers the preprocessor keyword and initialization + * function into the preprocessor list. This is the function that + * gets called from InitPreprocessors() in plugbase.c. + * + * Arguments: None. + * + * Returns: void function + * + */ +void SetupDeauthFlood() +{ + /* link the preprocessor keyword to the init function in + the preproc list */ + + RegisterPreprocessor("deauth_flood", DeauthFloodInit); + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Preprocessor: deauth_flood is setup...\n");); + return; +} + + +/* + * Function: DeauthFloodInit(u_char *) + * + * Purpose: Calls the argument parsing function, performs final setup on data + * structs, links the preproc function into the function list. + * + * Arguments: args => ptr to argument string + * + * Returns: void function + * + */ +void DeauthFloodInit(u_char *args) +{ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Preprocessor: deauth_flood Initialized\n");); + + memset(&deauth_flood_data, 0, sizeof(DeauthFloodData)); + + /* parse the argument list from the rules file */ + + DeauthFloodParseArgs(args); + + deauth_flood_data.DeauthstationsPtr = &deauth_flood_data.Deauthstations; + + /* set up the deauthenticated station tree */ + + ubi_trInitTree(deauth_flood_data.DeauthstationsPtr, deauthstationCompareFunc, 0); + + /* set up the node pools */ + + if(mempool_init(&deauth_flood_data.DeauthstationPool, + deauth_flood_data.target_limit, + sizeof(Deauthstation))){ + FatalError("ERROR: Can't initialize mempool for deauthenticated stations\n"); + } + + /* setup logpath */ + + strncpy(logpath, pv.log_dir, STD_BUF); + strncat(logpath, "/deauthflood.log", STD_BUF); + + deauth_flood_data.logfile = fopen(logpath, "a+"); + if(deauth_flood_data.logfile == NULL){ + FatalError("Can't open logfile: %s", logpath); + } + + deauth_flood_data.offset_alert_flag = WSTInit(sizeof(u_int8_t)); + deauth_flood_data.offset_nbr = WSTInit(sizeof(u_int16_t)); + deauth_flood_data.offset_time = WSTInit(sizeof(struct timeval)); + + /* Set the preprocessor function into the function list */ + + AddFuncToPreprocList(DeauthFloodDetect); + + AddFuncToCleanExitList(DeauthFloodCleanExitFunction, &deauth_flood_data); + AddFuncToRestartList(DeauthFloodRestartFunction, &deauth_flood_data); + return; +} + + +/* + * Function: DeauthFloodParseArgs(char *) + * + * Purpose: Process the preprocessor arguments from the rules file and + * initialize the preprocessor's data struct. This function doesn't + * have to exist if it makes sense to parse the args in the init + * function. + * + * Arguments: args => argument list + * + * Returns: void function + * + */ +void DeauthFloodParseArgs(char *args) +{ + int i, n, n_args, n_arg_args; + char **arg_toks = NULL, **arg_args = NULL; + + /* init preproc data with defaults */ + + deauth_flood_data.deauth_threshold = DEAUTH_FLOOD_THRESHOLD; + deauth_flood_data.expire_timeout = DEAUTH_FLOOD_EXPIRE_TIMEOUT; + deauth_flood_data.target_limit = DEAUTH_FLOOD_TARGET_LIMIT; + deauth_flood_data.prune_period = DEAUTH_FLOOD_PRUNE_PERIOD; + + if(args == NULL){ + LogMessage("deauth_flood initialized with defaults:\n"); + LogMessage(" %s: %u\n", DEAUTH_OPT_threshold, deauth_flood_data.deauth_threshold); + LogMessage(" %s: %u\n", DEAUTH_OPT_EXPIRE_TIMEOUT, deauth_flood_data.expire_timeout); + LogMessage(" %s: %u\n", DEAUTH_OPT_TARGET_LIMIT, deauth_flood_data.target_limit); + LogMessage(" %s: %u\n", DEAUTH_OPT_PRUNE_PERIOD, deauth_flood_data.prune_period); + + /* Update wifi_statetable timeout */ + + WSTUpdateTimeout(deauth_flood_data.expire_timeout); + return; + } + + arg_toks = mSplit(args, ",", 4, &n_args, 0); + if(n_args != 4){ + FatalError("%s: %s (%d) => deauth_flood configuration format:" + " deauth_threshold , expire_timeout ,\ntarget_limit ," + " prune_period \n", + MODNAME, file_name, file_line); + } + + for(i = 0; i < n_args; i++){ + arg_args = mSplit(arg_toks[i], " ", 2, &n_arg_args, 0); + if(n_arg_args != 2){ + FatalError("%s: %s (%d) => deauth_flood configuration format:" + " deauth_threshold , expire_timeout ,\ntarget_limit ," + " prune_period \n", + MODNAME, file_name, file_line); + } + + if(strcmp(arg_args[0], "deauth_threshold") == 0){ + n = strtol(arg_args[1], NULL, 10); + if(n <= 0){ + FatalError("%s: %s (%d) => \"deauth_threshold\" must be greater than 0\n" + , MODNAME, file_name, file_line); + } + deauth_flood_data.deauth_threshold = n; + } + else if(strcmp(arg_args[0], "expire_timeout") == 0){ + n = strtol(arg_args[1], NULL, 10); + if(n <= 0){ + FatalError("%s: %s (%d) => \"expire_timeout\" must be greater than 0\n", + MODNAME, file_name, file_line); + } + deauth_flood_data.expire_timeout = n; + } + else if(strcmp(arg_args[0], "target_limit") == 0){ + n = strtol(arg_args[1], NULL, 10); + if(n <= 0){ + FatalError("%s: %s (%d) => \"target_limit\" must be greater than 0\n", + MODNAME, file_name, file_line); + } + deauth_flood_data.target_limit = n; + } + else if(strcmp(arg_args[0], "prune_period") == 0){ + n = strtol(arg_args[1], NULL, 10); + if(n <= 0){ + FatalError("%s: %s (%d) => \"prune_period\" must be greater than 0\n", + MODNAME, file_name, file_line); + } + deauth_flood_data.prune_period = n; + } + else{ + FatalError("%s: %s (%d) => Invalid argument \"%s %s\"\n", + MODNAME, file_name, file_line, arg_args[0], arg_args[1]); + } + } + + if(deauth_flood_data.expire_timeout <= deauth_flood_data.prune_period){ + FatalError("%s: %s (%d) => \"expire_timeout\" must be greater than prune_period\n", + MODNAME, file_name, file_line); + } + + LogMessage("deauth_flood arguments:\n"); + LogMessage(" %s: %u\n", DEAUTH_OPT_threshold, deauth_flood_data.deauth_threshold); + LogMessage(" %s: %u\n", DEAUTH_OPT_EXPIRE_TIMEOUT, deauth_flood_data.expire_timeout); + LogMessage(" %s: %u\n", DEAUTH_OPT_TARGET_LIMIT, deauth_flood_data.target_limit); + LogMessage(" %s: %u\n", DEAUTH_OPT_PRUNE_PERIOD, deauth_flood_data.prune_period); + + /* Update wifi_statetable timeout */ + + WSTUpdateTimeout(deauth_flood_data.expire_timeout); + return; +} + + +/* + * Function: DeauthFloodDetect(Packet *) + * + * Purpose: Detect wireless auth flood traffic + * + * Arguments: p => pointer to the current packet data struct + * + * Returns: void function + * + */ +void DeauthFloodDetect(Packet *p) +{ + wst_flag_type flag_addr; + u_int32_t pruned; + u_int16_t *n_deauth_ptr; + u_int8_t *alert_flag_ptr; + struct timeval wst_tv, tv_diff; + Event event; + char outstring[255]; + + /* Cull any expired sessions out */ + + if(p->pkth->ts.tv_sec >= (deauth_flood_data.prune_time.tv_sec + deauth_flood_data.prune_period)){ + DEBUG_WRAP(DebugMessage(DEBUG_DEAUTHFLOOD, + "Pruning out deauthenticated stations due to expired prune_period\n");); + deauth_flood_data.prune_time.tv_sec = p->pkth->ts.tv_sec; + pruned = PruneDeauthstations(p->pkth->ts.tv_sec); + DEBUG_WRAP(DebugMessage(DEBUG_DEAUTHFLOOD, + "%u stations removed from Deauthstation memory pool\n", pruned);); + } + + DEBUG_WRAP(DebugMessage(DEBUG_DEAUTHFLOOD, + "Deauthenticated station count: %u\n", + ubi_trCount(deauth_flood_data.DeauthstationsPtr));); + + if(p->wifih == NULL){ + return; + } + + /* Is it a deauth frame? */ + + if((p->wifih->type != TYPE_MANAGEMENT) || (p->wifih->stype != STYPE_DEAUTH)){ + return; + } + + flag_addr = WST_FLAG_DESTADDR; + + /* Calls WSTMain to fill up p->wstidx.cache_addr[flag_addr] with memory address corresponding + * with the place where destination MAC address (target) is recorded inside WST. */ + + WSTMain(p, flag_addr); + + if( p->wstidx.cache_addr[flag_addr] == WST_FAILED){ + return; + } + + /* check wheter or not an alert is already reported */ + + alert_flag_ptr = (u_int8_t *) ((u_int8_t *) (p->wstidx.cache_addr[flag_addr] + + deauth_flood_data.offset_alert_flag)); + + /* n_deauth_ptr points to the number of deauth frame received by target + according to expire_timeout condition */ + + n_deauth_ptr = (u_int16_t *) ((u_int8_t *) (p->wstidx.cache_addr[flag_addr] + + deauth_flood_data.offset_nbr)); + + if(*alert_flag_ptr){ + + /* Alert has already been sent. Purpose is now to update WST time data in order + to avoid concerned deauth station to be removed from deauth stations + memory pool throught PruneDeauthstations function and uptade received deauth + frames number */ + + memcpy((u_int8_t *) (p->wstidx.cache_addr[flag_addr] + deauth_flood_data.offset_time), + &p->pkth->ts, sizeof(struct timeval)); + *n_deauth_ptr = (*n_deauth_ptr) + 1 ; + return; + } + + memcpy(&wst_tv, ((u_int8_t *) (p->wstidx.cache_addr[flag_addr] + deauth_flood_data.offset_time)), + sizeof(struct timeval)); + tv_diff = WSTTimevalSubtract(p->pkth->ts, wst_tv); + + /* check wether or not station should be considered as a new potential deauthstation. + * Update WST data */ + + if( tv_diff.tv_sec > deauth_flood_data.expire_timeout ){ + + /* station is a new potential deauthstation. + * Update WST data */ + + *n_deauth_ptr = 1; + memcpy((u_int8_t *) (p->wstidx.cache_addr[flag_addr] + deauth_flood_data.offset_time), + &p->pkth->ts, sizeof(struct timeval)); + } + else { + *n_deauth_ptr = (*n_deauth_ptr) + 1 ; + } + + /* check whether or not threshold is reached */ + + if( *n_deauth_ptr == deauth_flood_data.deauth_threshold){ + + /* alert condition are reached */ + + memcpy((u_int8_t *) (p->wstidx.cache_addr[flag_addr] + deauth_flood_data.offset_time), + &p->pkth->ts, sizeof(struct timeval)); + (*alert_flag_ptr) = 1; + + snprintf(outstring, 255, DEAUTHFLOOD_PREFIX_STR + "\nAddr src: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x -> Addr dst: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x" + ", Bssid: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x.", + p->wifih->addr2[0], p->wifih->addr2[1], p->wifih->addr2[2], + p->wifih->addr2[3], p->wifih->addr2[4], p->wifih->addr2[5], + p->wifih->addr1[0], p->wifih->addr1[1], p->wifih->addr1[2], + p->wifih->addr1[3], p->wifih->addr1[4], p->wifih->addr1[5], + p->wifih->addr3[0], p->wifih->addr3[1], p->wifih->addr3[2], + p->wifih->addr3[3], p->wifih->addr3[4], p->wifih->addr3[5]); + + DEBUG_WRAP(DebugMessage(DEBUG_DEAUTHFLOOD, "%s\n", outstring);); + + SetEvent(&event, GENERATOR_SPP_DEAUTHFLOOD, DEAUTHFLOOD_DETECTED, 1, 0, 0, 0); + CallAlertFuncs(p, outstring, NULL, &event); /* send alert & log data */ + DSLog(p, 0); + + /* insert station inside deauthstation mempool */ + + AddDeauthStation(p->wstidx.cache_addr[flag_addr]); + } + return; +} + + +/* + * Function: int deauthstationCompareFunc(ubi_trItemPtrItemPtr, + * ubi_trNodePtr NodePtr) + * + * Purpose: Callback function used by splay trees to sort deauthstation node + * + * Arguments: + * + * Returns: + * + */ +int deauthstationCompareFunc(ubi_trItemPtr ItemPtr, ubi_trNodePtr NodePtr) +{ + Deauthstation *A = (Deauthstation *) NodePtr; + Deauthstation *B = (Deauthstation *) ItemPtr; + int32_t memcmp_result; + + + memcmp_result = memcmp(&A->addr[0], &B->addr[0], 6); + if(memcmp_result < 0){ + return 1; + } + else if(memcmp_result > 0){ + return -1; + } + return 0; +} + + +/* + * Function: void AddDeauthStation(u_int32_t wst_addr) + * + * Purpose: Adds a new deauthenticated station to the deauthenticated station tree + * + * Arguments: wst_addr => memory address where MAC address is recorded inside wst. + * + * Returns: + * + */ +void AddDeauthStation(u_int32_t wst_addr) +{ + Deauthstation *ds = NULL; + MemBucket *mb = NULL; + + /* borrow a deauthenticated station node from the deauthenticated station node pool */ + + mb = mempool_alloc(&deauth_flood_data.DeauthstationPool); + + if(mb == NULL){ + DEBUG_WRAP(DebugMessage(DEBUG_DEAUTHFLOOD, "out of deauthenticated station Nodes\n");); + return; + } + + ds = (Deauthstation *) mb->data; + ds->bucket = mb; + + /* fill in the deauthstation struct */ + + ds->wst_addr = wst_addr; + memcpy(&ds->addr[0], (u_int8_t *) wst_addr, 6); + + DEBUG_WRAP(DebugMessage(DEBUG_DEAUTHFLOOD, + "Assigning a deauthenticated station with MAC addr of" + " %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", + ds->addr[0],ds->addr[1],ds->addr[2],ds->addr[3],ds->addr[4],ds->addr[5]);); + + /* add this deauthenticated station to deauthtenticated station tree */ + + if(ubi_sptInsert(deauth_flood_data.DeauthstationsPtr, + (ubi_btNodePtr)ds, + (ubi_btNodePtr)ds, NULL) == ubi_trFALSE){ + DEBUG_WRAP(DebugMessage(DEBUG_DEAUTHFLOOD, + "Insert into deauthenticated station tree failed\n");); + } + else{ + DEBUG_WRAP(DebugMessage(DEBUG_DEAUTHFLOOD, + "Insert into deauthenticated station tree successful\n");); + } + return; +} + + +/* + * Function: u_int32_t PruneDeauthstations(u_int32_t now) + * + * Purpose: Checks whether or not stations inserted inside deauthenticated + * station tree are still deauthenticated or not. + * If not, removes concerned stations from deauthenticated station tree and + * calls DSLogs function. + * + * Arguments: now => packet's capture time in sec + * + * Returns: number of station removed from deauthenticated station tree + * + */ +u_int32_t PruneDeauthstations(u_int32_t now) +{ + Deauthstation *idx; + u_int32_t pruned = 0; + u_int32_t ds_sec; + u_int8_t *alert_flag_ptr; + + DEBUG_WRAP(DebugMessage(DEBUG_DEAUTHFLOOD, + "Prune deauthenticated stations called now: " + " %u , count: %u\n", + now, ubi_trCount(deauth_flood_data.DeauthstationsPtr));); + + + if(ubi_trCount(deauth_flood_data.DeauthstationsPtr) < 1){ + DEBUG_WRAP(DebugMessage(DEBUG_DEAUTHFLOOD, + "exit PruneDeauthstation function since deauthenticated" + " station tree is free\n");); + return(0); + } + + /* number of thing that need to be deleted */ + + idx = (Deauthstation *) ubi_btFirst((ubi_btNodePtr)deauth_flood_data.DeauthstationsPtr->root); + + if(idx == NULL){ + return(0); + } + + do{ + ds_sec = *((u_int32_t *) (idx->wst_addr + deauth_flood_data.offset_time)); + if((ds_sec + deauth_flood_data.expire_timeout) < now){ + + /* station shouldn't be much more considered as a deauthedtified one. + Removes it from deauthstation pool */ + + alert_flag_ptr = (u_int8_t *) (idx->wst_addr + deauth_flood_data.offset_alert_flag); + *alert_flag_ptr = 0; + + DSLog(NULL, idx->wst_addr); + Deauthstation *savidx = idx; + if(ubi_trCount(deauth_flood_data.DeauthstationsPtr) > 1){ + idx = (Deauthstation *) ubi_btNext((ubi_btNodePtr)idx); + DEBUG_WRAP(DebugMessage(DEBUG_DEAUTHFLOOD, + "pruning stale deauthenticated station\n");); + DeleteDeauthstation(savidx); + pruned++; + } + else{ + DeleteDeauthstation(savidx); + pruned++; + return(pruned); + } + } + else{ + if(idx != NULL && ubi_trCount(deauth_flood_data.DeauthstationsPtr)){ + idx = (Deauthstation *) ubi_btNext((ubi_btNodePtr)idx); + } + else{ + return pruned; + } + } + } while(idx != NULL); + + return pruned; +} + + +/* + * Function: void DeleteDeauthstation(Deauthstation *ds) + * + * Purpose: removed ds from deauthstation mempool + * + * Arguments: + * + * Returns: + * + */ +void DeleteDeauthstation(Deauthstation *ds) +{ + Deauthstation *oldds; + + oldds = (Deauthstation *) ubi_sptRemove(deauth_flood_data.DeauthstationsPtr, + (ubi_btNodePtr) ds); + mempool_free(&deauth_flood_data.DeauthstationPool,ds->bucket); + return; +} + + +/* + * Function: void DSLog(Packet *p, u_int32_t wst_addr) + * + * Purpose: Called either when deauthentication flood is detected or finished. + * Logs data to a text file: deauth_flood_data.logfile. + * + * Arguments: + * + * Returns: + * + */ +void DSLog(Packet *p, u_int32_t wst_addr) +{ + char timestamp[TIMEBUF_SIZE]; + + if(p){ + ts_print((struct timeval *) &p->pkth->ts, timestamp); + fprintf(deauth_flood_data.logfile, "\n%s Deauth flood reported\n", timestamp); + PrintWifiHeader(deauth_flood_data.logfile, p); + } + else{ + ts_print((struct timeval *) (wst_addr + deauth_flood_data.offset_time), timestamp); + fprintf(deauth_flood_data.logfile, "\n%s End Deauth flood :" + " -> Addr dst: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x,\n" + "%u deauth frame reported.\n", + timestamp, + *((u_int8_t *)(wst_addr)), *((u_int8_t *)(wst_addr + 1)), *((u_int8_t *)(wst_addr + 2)), + *((u_int8_t *)(wst_addr + 3)), *((u_int8_t *)(wst_addr + 4)), *((u_int8_t *)(wst_addr + 5)), + *((u_int16_t *)(wst_addr + deauth_flood_data.offset_nbr))); + } + fflush(deauth_flood_data.logfile); + return; +} + + +/* + * Function: void DeauthCleanExitFunction(int, void *) + * + * Purpose: + * + * Arguments: + * + * Returns: + */ +void DeauthFloodCleanExitFunction(int signal, void *arg) +{ + DeauthFloodData *dfd_ptr = (DeauthFloodData *) arg; + + DEBUG_WRAP(DebugMessage(DEBUG_DEAUTHFLOOD, "DeauthFloodCleanExitFunction\n");); + + if(fclose(dfd_ptr->logfile)){ + LogMessage("%s: fclose function failed while snort exiting: %s\n", + MODNAME, strerror(errno)); + } + return; +} + + + +/* + * Function: void DeauthFloodCleanRestartFunction(int, void *) + * + * Purpose: + * + * Arguments: + * + * Returns: + */ +void DeauthFloodRestartFunction(int signal, void *arg) +{ + DeauthFloodData *dfd_ptr = (DeauthFloodData *) arg; + + DEBUG_WRAP(DebugMessage(DEBUG_DEAUTHFLOOD, "DeauthFloodRestartFunction\n");); + + if(fclose(dfd_ptr->logfile)){ + LogMessage("%s: fclose function failed while snort restarting: %s\n", + MODNAME, strerror(errno)); + } + return; +} Index: snort/src/preprocessors/spp_deauth_flood.h diff -u /dev/null snort/src/preprocessors/spp_deauth_flood.h:1.3 --- /dev/null Sat Nov 5 19:10:45 2005 +++ snort/src/preprocessors/spp_deauth_flood.h Fri Jun 24 18:33:20 2005 @@ -0,0 +1,98 @@ +/* +** Copyright (C) 2004 sebastien Gracia +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Copyright disclaimers: +** The Directeur Central de la sécurité des systèmes d'information hereby +** disclaims all copyright interest in the changes and enhancements +** made by sebastien Gracia. +** 5th Fev 2004. +*/ + + +#ifndef __SPP_DEAUTH_FLOOD_H__ +#define __SPP_DEAUTH_FLOOD_H__ + + +/* I N C L U D E S +*******************************************************************************/ +#include "snort.h" + + +/* D E F I N E S +*******************************************************************************/ + +#define DEAUTH_OPT_threshold "deauth-threshold" +#define DEAUTH_OPT_EXPIRE_TIMEOUT "expire_timeout" +#define DEAUTH_OPT_TARGET_LIMIT "target_limit" +#define DEAUTH_OPT_PRUNE_PERIOD "prune_period" + + +#define DEAUTH_FLOOD_THRESHOLD 20 +#define DEAUTH_FLOOD_EXPIRE_TIMEOUT 60 +#define DEAUTH_FLOOD_TARGET_LIMIT 100 +#define DEAUTH_FLOOD_PRUNE_PERIOD 30 + +typedef struct _DeauthFloodData +{ + ubi_trRoot Deauthstations; + ubi_trRootPtr DeauthstationsPtr; + + MemPool DeauthstationPool; + + u_int16_t offset_alert_flag; + u_int16_t offset_nbr; + u_int16_t offset_time; + + u_int32_t deauth_threshold; + u_int32_t expire_timeout; + u_int32_t target_limit; + u_int32_t prune_period; + + struct timeval prune_time; + + /** Global Program Data **/ + FILE *logfile; +} DeauthFloodData; + +/* this represent the deauthenticated station */ +typedef struct _DeauthStation +{ + ubi_trNode Node; /* for the splay tree */ + MemBucket *bucket; + + u_int32_t wst_addr; + u_int8_t addr[6]; +} Deauthstation; + + +/* P R O T O T Y P E S +*******************************************************************************/ + +void SetupDeauthFlood(); +void DeauthFloodInit(u_char *); +void DeauthFloodParseArgs(char *); +void DeauthFloodDetect(Packet *); +int deauthstationCompareFunc(ubi_trItemPtr, ubi_trNodePtr); +void AddDeauthStation(u_int32_t); +u_int32_t PruneDeauthstations(u_int32_t); +void DeleteDeauthstation(Deauthstation *); +void DSLog(Packet *, u_int32_t); +void DeauthFloodRestartFunction(int, void *); +void DeauthFloodCleanExitFunction(int, void *); + + +#endif /* __SPP_DESFLOOD_H__ */ Index: snort/src/preprocessors/spp_macspoof.c diff -u /dev/null snort/src/preprocessors/spp_macspoof.c:1.2 --- /dev/null Sat Nov 5 19:10:45 2005 +++ snort/src/preprocessors/spp_macspoof.c Fri Jun 24 17:22:16 2005 @@ -0,0 +1,983 @@ +/* +** Copyright (C) 2004 Sebastien Gracia +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Copyright disclaimers: +** The Directeur Central de la sécurité des systèmes d'information hereby +** disclaims all copyright interest in the changes and enhancements +** made by sebastien Gracia. +** 5th Fev 2004. +*/ + + +/* spp_macspoof + * + * Purpose: Detects wireless MAC addresses involved in some MAC spoofed traffic. + * + * => list of MAC addresses excluded from wireless MAC spoofing + * detection process + * + * tolerate_gap => tolerate missing frames betweeen two consecutive frames issued + * from same MAC address + * + * threshold => number of abnormal sequence number gaps during time delta + * to trigger an alert + * + * expire_timeout => time period used to keep count of abnormal sequence number gap + * + * spoofed_addr_limit => maximum number of MAC addresses inserted inside MAC spoofed + * addresses mempool + * + * prune_period => number of seconds to wait for looking after some decayed + * MAC addresses inside mempool + * + * Effect: + * + * Sends an alert whenever MAC spoofing activity is detected. + * + * Comments: + * - Because of some particuliar firmware or some electro_magnetic conditions, this + * preprocessors won't fit to all wireless features inside network. + * Those would generate too much false positive alert. + * Therefore, I suggest macspoof preprocessos users to run snort a first time + * in order to identify those particuliar features and thereafter to insert + * them inside MaskedMACaddrlist. + * + * - Whenever an alert si raised, it doesn't mean anytime that concerned MAC address + * is spoofed. Furthermore, It means that this MAC adress is involved in some MAC + * spoofed traffic (either MAC spoofed or MAC spoofing address). + * + * - whenever "end abnormal sequence number gap" is logged, it doesn't exactly mean that + * MAC spoofing ended. For example, it would occured if a spoofer succeed to divert + * a user from network while keeping using his MAC address. In such a case, neither + * abnormal sequence number gap would be detected nor alert would be sended + * while MAC spoofing still occur. + * + * Any comments? + * + */ + + +#include + +#include "plugbase.h" +#include "mstring.h" +#include "debug.h" +#include "log.h" +#include "wifi_statetable.h" +#include "generators.h" +#include "ubi_BinTree.h" +#include "mempool.h" +#include "detect.h" +#include "util.h" + +#ifndef __SPP_MACSPOOF_C__ +#define __SPP_MACSPOOF_C__ +#include "spp_macspoof.h" +#endif + +#define MODNAME "spp_macspoof" + +MACSpoofData MACspoof_data; +char logpath[STD_BUF]; + +/* external globals from rules.c */ + +extern char *file_name; +extern int file_line; + + +/* + * Function: SetupMACSpoof() + * + * Purpose: Registers the preprocessor keyword and initialization + * function into the preprocessor list. This is the function that + * gets called from InitPreprocessors() in plugbase.c. + * + * Arguments: None. + * + * Returns: void function + * + */ +void SetupMACSpoof() +{ + /* link the preprocessor keyword to the init function in + the preproc list */ + + RegisterPreprocessor("macspoof", MACSpoofInit); + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Preprocessor: macspoof is setup...\n");); + return; +} + + +/* + * Function: MACSpoofInit(u_char *) + * + * Purpose: Calls the argument parsing function, performs final setup on data + * structs, links the preproc function into the function list. + * + * Arguments: args => ptr to argument string + * + * Returns: void function + * + */ +void MACSpoofInit(u_char *args) +{ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Preprocessor: macspoof Initialized\n");); + + memset(&MACspoof_data, 0, sizeof(MACSpoofData)); + + /* parse the argument list from the rules file */ + + MACSpoofParseArgs(args); + + MACspoof_data.spoofed_MACaddrsPtr = &MACspoof_data.spoofed_MACaddrs; + + /* set up the MAC spoofed address tree */ + + ubi_trInitTree(MACspoof_data.spoofed_MACaddrsPtr, MACSpoofedAddrCompareFunc, 0); + + /* set up the node pools */ + + if(mempool_init(&MACspoof_data.spoofed_MACaddrPool, + MACspoof_data.spoofed_addr_limit, + sizeof(Spoofed_MACaddr))){ + FatalError("ERROR: Can't initialize mempool for MACSpoofed addresses\n"); + } + + /* setup logpath */ + + strncpy(logpath, pv.log_dir, STD_BUF); + strncat(logpath, "/MACspoof.log", STD_BUF); + + MACspoof_data.logfile = fopen(logpath, "a+"); + if(MACspoof_data.logfile == NULL){ + FatalError("Can't open logfile: %s", logpath); + } + + MACspoof_data.offset_alert_flag = WSTInit(sizeof(u_int8_t)); + MACspoof_data.offset_seq_number = WSTInit(sizeof(u_int16_t)); + MACspoof_data.offset_gap_number = WSTInit(sizeof(u_int16_t)); + MACspoof_data.offset_time = WSTInit(sizeof(struct timeval)); + + /* Set the preprocessor function into the function list */ + + AddFuncToPreprocList(MACSpoofDetect); + + AddFuncToCleanExitList(MACSpoofCleanExitFunction, &MACspoof_data); + AddFuncToRestartList(MACSpoofRestartFunction, &MACspoof_data); + return; +} + + +/* + * Function: MACSpoofParseArgs(char *) + * + * Purpose: Process the preprocessor arguments from the rules file and + * initialize the preprocessor's data struct. This function doesn't + * have to exist if it makes sense to parse the args in the init + * function. + * + * Arguments: args => argument list + * + * Returns: void function + * + */ +void MACSpoofParseArgs(char *args) +{ + int i, n, n_args, n_arg_args; + char **arg_toks = NULL, **arg_args = NULL; + MACADDR *MAC_addr_ptr; + + DEBUG_WRAP(DebugMessage(DEBUG_MACSPOOF, + "Parsing macspoof preprocessor arguments\n");); + + /* init preproc data with defaults */ + + MACspoof_data.tolerate_gap = MACSPOOF_TOLERATE_GAP; + MACspoof_data.threshold = MACSPOOF_THRESHOLD; + MACspoof_data.expire_timeout = MACSPOOF_EXPIRE_TIMEOUT; + MACspoof_data.spoofed_addr_limit = MACSPOOF_SPOOFED_ADDR_LIMIT; + MACspoof_data.prune_period = MACSPOOF_PRUNE_PERIOD; + + if(args == NULL) { + LogMessage("macspoof initialized with defaults:\n"); + LogMessage(" %s: none\n", MACSPOOF_OPT_MASKED_MAC_ADDR); + LogMessage(" %s: %u\n", MACSPOOF_OPT_TOLERATE_GAP, MACspoof_data.tolerate_gap); + LogMessage(" %s: %u\n", MACSPOOF_OPT_THRESHOLD, MACspoof_data.threshold); + LogMessage(" %s: %u\n", MACSPOOF_OPT_EXPIRE_TIMEOUT, MACspoof_data.expire_timeout); + LogMessage(" %s: %u\n", MACSPOOF_OPT_SPOOFED_ADDR_LIMIT, MACspoof_data.spoofed_addr_limit); + LogMessage(" %s: %u\n", MACSPOOF_OPT_PRUNE_PERIOD, MACspoof_data.prune_period); + + /* Update wifi_statetable timeout */ + + WSTUpdateTimeout(MACspoof_data.expire_timeout); + return; + } + + /* Build masked MAC address list */ + + MACspoof_data.masked_MACaddrlist = BuildMaskedMACaddrlist(&args); + + if(MACspoof_data.masked_MACaddrlist == NULL){ + args += 4; + } + else{ + MACspoof_data.MaskedMACaddrlist_flag = 1; + } + + /* finally process tolerate_gap, threshold, expire_timeout,spoofed_addr_limit and + prune_period arguments */ + + arg_toks = mSplit(args, ",", 5, &n_args, 0); + if(n_args != 5){ + FatalError("%s: %s (%d) => macspoof configuration format:" + " tolerate_gap , threshold , expire_timeout ,\n" + "spoofed_addr_limit , prune_period \n", + MODNAME, file_name, file_line); + } + + for(i = 0; i < n_args; i++) { + arg_args = mSplit(arg_toks[i], " ", 2, &n_arg_args, 0); + if(n_arg_args != 2){ + FatalError("%s: %s (%d) => macspoof configuration format:" + " tolerate_gap , threshold , expire_timeout ,\n" + "spoofed_addr_limit , prune_period \n", + MODNAME, file_name, file_line); + } + + if(strcmp(arg_args[0], "tolerate_gap") == 0){ + n = strtol(arg_args[1], NULL, 10); + if(n <= 0){ + FatalError("%s: %s (%d) => \"tolerate_gap\" must be greater than 0\n" + , MODNAME, file_name, file_line); + } + MACspoof_data.tolerate_gap = n; + } + else if(strcmp(arg_args[0], "threshold") == 0){ + n = strtol(arg_args[1], NULL, 10); + if(n <= 1){ + FatalError("%s: %s (%d) => \"threshold\" must be greater than 1\n" + , MODNAME, file_name, file_line); + } + MACspoof_data.threshold = n; + } + else if(strcmp(arg_args[0], "expire_timeout") == 0){ + n = strtol(arg_args[1], NULL, 10); + if(n <= 0){ + FatalError("%s: %s (%d) => \"expire_timeout\" must be greater than 0\n", + MODNAME, file_name, file_line); + } + MACspoof_data.expire_timeout = n; + } + else if(strcmp(arg_args[0], "spoofed_addr_limit") == 0){ + n = strtol(arg_args[1], NULL, 10); + if(n <= 0){ + FatalError("%s: %s (%d) => \"spoofed_addr_limit\" must be greater than 0\n", + MODNAME, file_name, file_line); + } + MACspoof_data.spoofed_addr_limit = n; + } + else if(strcmp(arg_args[0], "prune_period") == 0){ + n = strtol(arg_args[1], NULL, 10); + if(n <= 0){ + FatalError("%s: %s (%d) => \"prune_period\" must be greater than 0\n", + MODNAME, file_name, file_line); + } + MACspoof_data.prune_period = n; + } + else{ + FatalError("%s: %s (%d) => Invalid argument \"%s %s\"\n", + MODNAME, file_name, file_line, arg_args[0], arg_args[1]); + } + } + + if(MACspoof_data.expire_timeout <= MACspoof_data.prune_period){ + FatalError("%s: %s (%d) => \"expire_timeout\" must be greater than prune_period\n", + MODNAME, file_name, file_line); + } + + LogMessage("macspoof arguments:\n"); + if(MACspoof_data.MaskedMACaddrlist_flag){ + MAC_addr_ptr = MACspoof_data.masked_MACaddrlist->head; + LogMessage(" %s: ", MACSPOOF_OPT_MASKED_MAC_ADDR); + LogMessage("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", + MAC_addr_ptr->MAC_addr[0], MAC_addr_ptr->MAC_addr[1], MAC_addr_ptr->MAC_addr[2], + MAC_addr_ptr->MAC_addr[3], MAC_addr_ptr->MAC_addr[4], MAC_addr_ptr->MAC_addr[5]); + MAC_addr_ptr = MAC_addr_ptr->next; + while(MAC_addr_ptr){ + LogMessage(" %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", + MAC_addr_ptr->MAC_addr[0], MAC_addr_ptr->MAC_addr[1], MAC_addr_ptr->MAC_addr[2], + MAC_addr_ptr->MAC_addr[3], MAC_addr_ptr->MAC_addr[4], MAC_addr_ptr->MAC_addr[5]); + MAC_addr_ptr = MAC_addr_ptr->next; + } + } + else{ + LogMessage(" %s: none\n", MACSPOOF_OPT_MASKED_MAC_ADDR); + } + LogMessage(" %s: %u\n", MACSPOOF_OPT_TOLERATE_GAP, MACspoof_data.tolerate_gap); + LogMessage(" %s: %u\n", MACSPOOF_OPT_THRESHOLD, MACspoof_data.threshold); + LogMessage(" %s: %u\n", MACSPOOF_OPT_EXPIRE_TIMEOUT, MACspoof_data.expire_timeout); + LogMessage(" %s: %u\n", MACSPOOF_OPT_SPOOFED_ADDR_LIMIT, MACspoof_data.spoofed_addr_limit); + LogMessage(" %s: %u\n", MACSPOOF_OPT_PRUNE_PERIOD, MACspoof_data.prune_period); + + /* Update wifi_statetable timeout */ + + WSTUpdateTimeout(MACspoof_data.expire_timeout); + return; +} + + +/* + * Function: MACSpoofDetect(Packet *) + * + * Purpose: Detect wireless frames with spoofed source address excluding ones specified + * by the MACSPOOF_MASKEDC_ADDR variable in snort.conf + * + * Arguments: p => pointer to the current packet data struct + * + * Returns: void function + * + */ +void MACSpoofDetect(Packet *p) +{ + wst_flag_type flag_addr; + u_int32_t pruned; + u_int16_t *gap_number_ptr, *seq_number_ptr, gap; + u_int8_t *alert_flag_ptr; + int8_t src_offset; + struct timeval wst_tv, tv_diff; + Event event; + char outstring[255]; + MACADDR *MAC_addr_ptr; + + /* Cull any expired MAC spoofed addresses out */ + + if(p->pkth->ts.tv_sec >= (MACspoof_data.prune_time.tv_sec + MACspoof_data.prune_period)){ + DEBUG_WRAP(DebugMessage(DEBUG_MACSPOOF, + "Pruning out MACSpoofed addr due to expired prune_period\n");); + MACspoof_data.prune_time.tv_sec = p->pkth->ts.tv_sec; + pruned=PruneMACSpoofedAddrs(p->pkth->ts.tv_sec); + DEBUG_WRAP(DebugMessage(DEBUG_MACSPOOF, + "%u addr removed from MACSpoofed addr memory pool\n", pruned);); + } + + DEBUG_WRAP(DebugMessage(DEBUG_MACSPOOF, + "MACSPoofed addr count: %u\n", + ubi_trCount(MACspoof_data.spoofed_MACaddrsPtr));); + + if(p->wifih == NULL){ + return; + } + + flag_addr = WST_FLAG_SRCADDR; + + if(MACspoof_data.MaskedMACaddrlist_flag){ + src_offset = WSTDetermineMACAddrOffset(p, flag_addr); + MAC_addr_ptr = MACspoof_data.masked_MACaddrlist->head; + do{ + if(!memcmp(MAC_addr_ptr->MAC_addr, (u_int8_t *) p->wifih + src_offset, 6)){ + DEBUG_WRAP(DebugMessage(DEBUG_MACSPOOF, + "Packet ignored due to src MAC addr: %2x:%.2x:%.2x:%.2x:%.2x:%.2x " + "included inside masked MAC addr list\n", + *((u_int8_t *) p->wifih + src_offset), + *((u_int8_t *) p->wifih + src_offset + 1), + *((u_int8_t *) p->wifih + src_offset + 2), + *((u_int8_t *) p->wifih + src_offset + 3), + *((u_int8_t *) p->wifih + src_offset + 4), + *((u_int8_t *) p->wifih + src_offset + 5));); + return; + } + MAC_addr_ptr = MAC_addr_ptr->next; + } while(MAC_addr_ptr); + } + + /* Calls WSTMain to fill up p->wstidx.cache_addr[flag_addr] with memory address corresponding + * with the place where source MAC address is recorded inside WST. */ + + WSTMain(p, flag_addr); + + if( p->wstidx.cache_addr[flag_addr] == WST_FAILED) { + return; + } + + /* seq_number_ptr points to the last wireless frame sequence number issued from + source MAC address */ + + seq_number_ptr = (u_int16_t *) ((u_int8_t *) (p->wstidx.cache_addr[flag_addr] + + MACspoof_data.offset_seq_number)); + + /* gap represent the difference between packet's sequence number and corresponding sequence + number recorded inside WST minus one. Furthermore, it should be considered as the total + missing frames refered to 802.11 protocol. + This means that two consecutive frames with same sequence number issued from same MAC addr + will generate a gab equal to 4095. */ + + gap = (4095 + p->wifih->seqnum - (*seq_number_ptr)) %4096; + + /* Check whether or not gap should be considered as normal refered to preprocessor's argument + tolerate_gap */ + + if( gap <= MACspoof_data.tolerate_gap){ + + /* packet sequence number fill up 802.11 protocol according to preprocessor arguments */ + + *seq_number_ptr = p->wifih->seqnum; + return; + } + + /* From now, Packet is considered as abnormal */ + + DEBUG_WRAP(DebugMessage(DEBUG_MACSPOOF, + "Missing frame abnormal count issued from MAC addr: " + "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", + "received frame seq nbr: %u, recorded seq nbr: %u\n\n", + *((u_int8_t *) p->wstidx.cache_addr[flag_addr]), + *((u_int8_t *) (p->wstidx.cache_addr[flag_addr] + 1)), + *((u_int8_t *) (p->wstidx.cache_addr[flag_addr] + 2)), + *((u_int8_t *) (p->wstidx.cache_addr[flag_addr] + 3)), + *((u_int8_t *) (p->wstidx.cache_addr[flag_addr] + 4)), + *((u_int8_t *) (p->wstidx.cache_addr[flag_addr] + 5)), + p->wifih->seqnum, *seq_number_ptr);); + + /* check wheter or not an alert is already reported */ + + alert_flag_ptr = (u_int8_t *) ((u_int8_t *) (p->wstidx.cache_addr[flag_addr] + + MACspoof_data.offset_alert_flag)); + + if(*alert_flag_ptr){ + + /* Alert has already been sent. Purpose is now to update WST time data in order + to avoid concerned spoofed MAC address to be removed from MAC spoofed address + memory pool throught PruneMACSpoofedAddrs function */ + + *seq_number_ptr = p->wifih->seqnum; + memcpy((u_int8_t *) (p->wstidx.cache_addr[flag_addr] + MACspoof_data.offset_time), + &p->pkth->ts, sizeof(struct timeval)); + return; + } + + /* gap_number_ptr points to the number of abnormal gap associated with source MAC addr + inside WST */ + + gap_number_ptr = (u_int16_t *) ((u_int8_t *) (p->wstidx.cache_addr[flag_addr] + + MACspoof_data.offset_gap_number)); + + /* Check whether or not data recorded inside WST should be considered as decayed for + this preprocessor */ + + memcpy(&wst_tv, ((u_int8_t *) (p->wstidx.cache_addr[flag_addr] + MACspoof_data.offset_time)), + sizeof(struct timeval)); + tv_diff = WSTTimevalSubtract(p->pkth->ts, wst_tv); + + if( tv_diff.tv_sec > MACspoof_data.expire_timeout ){ + + /* data recorded inside WST are considered as decayed for this preprocessor. + Uptade them. */ + + *gap_number_ptr = 1; + *seq_number_ptr = p->wifih->seqnum; + memcpy((u_int8_t *) (p->wstidx.cache_addr[flag_addr] + MACspoof_data.offset_time), + &p->pkth->ts, sizeof(struct timeval)); + return; + } + + (*gap_number_ptr)++; + *seq_number_ptr = p->wifih->seqnum; + + /* checks if alert condition are reached */ + + if((*gap_number_ptr) == MACspoof_data.threshold){ + + /* alert condition are reached */ + + memcpy((u_int8_t *) (p->wstidx.cache_addr[flag_addr] + MACspoof_data.offset_time), + &p->pkth->ts, sizeof(struct timeval)); + (*alert_flag_ptr) = 1; + + snprintf(outstring, 255, MACSPOOF_PREFIX_STR "\nabnormal seq number gap " + "occurs on addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x", + *((u_int8_t *) p->wstidx.cache_addr[flag_addr]), + *((u_int8_t *) (p->wstidx.cache_addr[flag_addr] + 1)), + *((u_int8_t *) (p->wstidx.cache_addr[flag_addr] + 2)), + *((u_int8_t *) (p->wstidx.cache_addr[flag_addr] + 3)), + *((u_int8_t *) (p->wstidx.cache_addr[flag_addr] + 4)), + *((u_int8_t *) (p->wstidx.cache_addr[flag_addr] + 5))); + DEBUG_WRAP(DebugMessage(DEBUG_MACSPOOF, "%s\n", outstring);); + + /* send alert & log data */ + + SetEvent(&event, GENERATOR_SPP_MACSPOOF, MACSPOOF_DETECTED, 1, 0, 0, 0); + CallAlertFuncs(p, outstring, NULL, &event); + MACSpoofLog(p, p->wstidx.cache_addr[flag_addr]); + + /* insert station inside deauthstation mempool */ + + AddMACSpoofedAddr(p->wstidx.cache_addr[flag_addr]); + } + return; +} + + +/* + * Function: MaskedMACaddrlist *BuildMaskedMACaddrlist(char **args_ptr) + * + * Purpose: Parses MAC address argument from the preprocessor's arguments string into a + * MaskedMACaddrlist and points it to the end of the MAC address argument + * + * Arguments: args_ptr => pointer to a string containing the preprocessor's arguments + * + * Returns: a MaskedMACaddrlist of MAC addresses to exclude from alerts + * + */ +MaskedMACaddrlist *BuildMaskedMACaddrlist(char **args_ptr) +{ + char *end_ptr; + char *args = *args_ptr; + MaskedMACaddrlist *masked_MACaddrlist = NULL; + u_int8_t MAC_addr[6]; + + while(*args && isspace(*args)) + args++; + + /* checks if MAC address argument is none which means that no MAC address + will be exclude from alerts */ + + if(memcmp(args, "none", 4) == 0){ + return NULL; + } + + masked_MACaddrlist = AllocMaskedMACaddrlist(); + + /* parse the MAC addr or list of MAC addrs */ + + if(args[0] == '['){ + for(end_ptr = ++args; *end_ptr && *end_ptr != ']'; end_ptr++){ + if(*end_ptr == ','){ + *end_ptr = '\0'; + if(ParseMACAddr(MAC_addr, args) < 0){ + FatalError("%s: %s (%d) => Error parsing MAC addr \"%s\"\n", + MODNAME, file_name, file_line, args); + } + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "%s: Adding %.2X:%.2X:%.2X:%.2X:%.2X:%.2X to masked MAC list\n", + MODNAME, MAC_addr[0], MAC_addr[1], MAC_addr[2], + MAC_addr[3], MAC_addr[4], MAC_addr[5]);); + + InsertMaskedMACaddr(MAC_addr, masked_MACaddrlist); + args = end_ptr + 1; + } + } + + *end_ptr = '\0'; + if(ParseMACAddr(MAC_addr, args) < 0){ + FatalError("%s: %s (%d) => error parsing masked MAC addresses \"%s\"\n", + MODNAME, file_name, file_line, args); + } + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "%s: Adding %.2X:%.2X:%.2X:%.2X:%.2X:%.2X to masked MAC list\n", + MODNAME, MAC_addr[0], MAC_addr[1], MAC_addr[2], + MAC_addr[3], MAC_addr[4], MAC_addr[5]);); + + InsertMaskedMACaddr(MAC_addr, masked_MACaddrlist); + args = end_ptr + 1; + while(*args && *args != ','){ + args++; + } + if(*args){ + args++; + } + } + else{ + for(end_ptr = args; *end_ptr && *end_ptr != ','; end_ptr++); + + *end_ptr ='\0'; + if(ParseMACAddr(MAC_addr, args) < 0){ + FatalError("%s: %s (%d) => error parsing masked MAC addresses \"%s\"\n", + MODNAME, file_name, file_line, args); + } + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "%s: Adding %.2X:%.2X:%.2X:%.2X:%.2X:%.2X to masked MAC list\n", + MODNAME, MAC_addr[0], MAC_addr[1], MAC_addr[2], + MAC_addr[3], MAC_addr[4], MAC_addr[5]);); + + InsertMaskedMACaddr(MAC_addr, masked_MACaddrlist); + args = end_ptr + 1; + } + + *args_ptr = args; + + return masked_MACaddrlist; +} + + +/* + * Function: MaskedMACaddrlist *AllocMaskedMACaddrlist(void) + * + * Purpose: Allocates a MaskedMACaddrlist + * + * Arguments: None + * + * Returns: A pointer to the newly allocated MaskedMACaddrlist or NULL or -1 if failed + * + */ +MaskedMACaddrlist *AllocMaskedMACaddrlist(void) +{ + return (MaskedMACaddrlist *)calloc(1, sizeof(MaskedMACaddrlist)); +} + + +int ParseMACAddr(u_int8_t *MACaddr, char *MAC_str) +{ + int i = 0; + char *next = MAC_str; + + while(*next){ + MACaddr[i] = strtol(MAC_str, &next, 16); + + if(MAC_str != next && i < 6){ + MAC_str = next + 1; + i++; + } + else{ + return -1; + } + } + return 0; +} + + +/* + * Function: MACADDR *InsertMaskedMACaddr(u_int8_t *MAC_addr, MaskedMACaddrlist *list) + * + * Purpose: Creates a MACADDR node from a byte array and inserts it into the + * specified MaskedMACaddrlist + * + * Arguments: MAC_addr => byte array containing a MAC address + * list => MaskedMACaddrlist to insert new node in + * + * Returns: A pointer to newly inserted MACADDR node or NULL if MAC_addr or + * list is NULL + */ +MACADDR *InsertMaskedMACaddr(u_int8_t *MAC_addr, MaskedMACaddrlist *list) +{ + MACADDR *MACAddr_ptr = NULL; + + if(list == NULL || MAC_addr == NULL) + return NULL; + + /* allocate new MACaddr node */ + + MACAddr_ptr = (MACADDR *)malloc(sizeof(MACADDR)); + memcpy(MACAddr_ptr->MAC_addr, MAC_addr, 6); + MACAddr_ptr->next = NULL; + MACAddr_ptr->prev =NULL; + + if(list->head == NULL && list->tail == NULL){ + list->head = MACAddr_ptr; + list->tail = MACAddr_ptr; + } + else{ + MACAddr_ptr->prev = list->tail; + list->tail->next = MACAddr_ptr; + list->tail = MACAddr_ptr; + } + return MACAddr_ptr; +} + + +/* + * Function: int MACSpoofAddrCompareFunc(ubi_trItemPtrItemPtr, + * ubi_trNodePtr NodePtr) + * + * Purpose: Callback function used by splay trees to sort deauthstation node + * + * Arguments: + * + * Returns: + * + */ +int MACSpoofedAddrCompareFunc(ubi_trItemPtr ItemPtr, ubi_trNodePtr NodePtr) +{ + Spoofed_MACaddr *A = (Spoofed_MACaddr *) NodePtr; + Spoofed_MACaddr *B = (Spoofed_MACaddr *) ItemPtr; + int32_t memcmp_result; + + memcmp_result = memcmp(&A->addr[0], &B->addr[0], 6); + if(memcmp_result < 0){ + return 1; + } + else if(memcmp_result > 0){ + return -1; + } + return 0; +} + + +/* + * Function: void AddMACSpoofedAddr(u_int32_t wst_addr) + * + * Purpose: Adds a new spoofed addr into the spoofed MAC addr tree + * + * Arguments: wst_addr => memory address where MAC address is recorded inside wst. + * + * Returns: none + * + */ +void AddMACSpoofedAddr(u_int32_t wst_addr) +{ + Spoofed_MACaddr *ms = NULL; + MemBucket *mb = NULL; + + /* borrow a MAC address node from the MAC addresses node pool */ + + mb = mempool_alloc(&MACspoof_data.spoofed_MACaddrPool); + + if(mb == NULL){ + DEBUG_WRAP(DebugMessage(DEBUG_MACSPOOF, "out of MACSpoofed addr Nodes\n");); + return; + } + + ms = (Spoofed_MACaddr *) mb->data; + ms->bucket = mb; + + /* fill in the Spoofed_MACaddr struct */ + + ms->wst_addr = wst_addr; + memcpy(&ms->addr[0], (u_int8_t *) wst_addr, 6); + DEBUG_WRAP(DebugMessage(DEBUG_MACSPOOF, + "Assigning a MACSpoofed addr of" + " %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", + ms->addr[0],ms->addr[1],ms->addr[2],ms->addr[3],ms->addr[4],ms->addr[5]);); + + /* add this spoofed MAC address to the spoofed MAC addresses tree */ + + if(ubi_sptInsert(MACspoof_data.spoofed_MACaddrsPtr, + (ubi_btNodePtr)ms, + (ubi_btNodePtr)ms, NULL) == ubi_trFALSE){ + DEBUG_WRAP(DebugMessage(DEBUG_MACSPOOF, + "Insert into MACSpoofed addr tree failed\n");); + } + else{ + DEBUG_WRAP(DebugMessage(DEBUG_MACSPOOF, + "Insert into MACSpoofed addr tree successful\n");); + } + return; +} + + +/* + * Function: u_int32_t PruneMACSPoofedAddrs(u_int32_t now) + * + * Purpose: Checks whether or not MAC addresses inserted inside spoofed + * MAC addresses tree are still spoofed or not. + * If not, removes concerned addresses from spoofed MAC addresses tree and + * calls MACSpoofLogs function. + * + * Arguments: now => packet's capture time in sec + * + * Returns: number of MAC addresses removed from spoofed MAC addresses memory + * pool. + * + */ +u_int32_t PruneMACSpoofedAddrs(u_int32_t now) +{ + Spoofed_MACaddr *idx; + u_int32_t pruned = 0; + u_int32_t ms_sec; + u_int8_t *alert_flag_ptr; + + DEBUG_WRAP(DebugMessage(DEBUG_MACSPOOF, + "Prune MACSpoofed addr called now: " + " %u , count: %u\n", + now, ubi_trCount(MACspoof_data.spoofed_MACaddrsPtr));); + + if(ubi_trCount(MACspoof_data.spoofed_MACaddrsPtr) < 1){ + DEBUG_WRAP(DebugMessage(DEBUG_MACSPOOF, + "exit PruneMACSpoofedAddrs function since MACSpoofed addr tree is free\n");); + return(0); + } + + /* number of thing that need to be deleted */ + + idx = (Spoofed_MACaddr *) ubi_btFirst((ubi_btNodePtr)MACspoof_data.spoofed_MACaddrsPtr->root); + + if(idx == NULL){ + return(0); + } + + + do{ + ms_sec = *((u_int32_t *) (idx->wst_addr + MACspoof_data.offset_time)); + + if((ms_sec + MACspoof_data.expire_timeout) < now){ + + /* MAC addresses shouldn't much more be considered as a spoofed one. + Removes it from spoofed MAC adresses pool */ + + alert_flag_ptr = (u_int8_t *) (idx->wst_addr + MACspoof_data.offset_alert_flag); + *alert_flag_ptr = 0; + + MACSpoofLog(NULL, idx->wst_addr); + Spoofed_MACaddr *savidx = idx; + if(ubi_trCount(MACspoof_data.spoofed_MACaddrsPtr) > 1){ + idx = (Spoofed_MACaddr *) ubi_btNext((ubi_btNodePtr)idx); + DEBUG_WRAP(DebugMessage(DEBUG_MACSPOOF, + "pruning stale MACSpoofed addr\n");); + DeleteMACSpoofedAddr(savidx); + pruned++; + } + else{ + DeleteMACSpoofedAddr(savidx); + pruned++; + return(pruned); + } + } + else{ + if(idx != NULL && ubi_trCount(MACspoof_data.spoofed_MACaddrsPtr)){ + idx = (Spoofed_MACaddr *) ubi_btNext((ubi_btNodePtr)idx); + } + else{ + return pruned; + } + } + } while(idx != NULL); + return pruned; +} + + +/* + * Function: void DeleteMACSpoofedAddr(Spoofed_MACaddr *ms) + * + * Purpose: removed MAC address from spoofed MAC addresses mempool + * + * Arguments: ms => points to concerned MAC address + * + * Returns: none + * + */ +void DeleteMACSpoofedAddr(Spoofed_MACaddr *ms) +{ + Spoofed_MACaddr *oldms; + oldms = (Spoofed_MACaddr *) ubi_sptRemove(MACspoof_data.spoofed_MACaddrsPtr, + (ubi_btNodePtr) ms); + mempool_free(&MACspoof_data.spoofed_MACaddrPool, ms->bucket); +} + + +/* + * Function: void MACSpoofLog(Packet *p, u_int32_t wst_addr) + * + * Purpose: Called either when MAC spoofing is detected or finished. + * Logs data to a text file: MACspoof_data.logfile. + * + * Arguments: p => pointer to current packet + * wst_addr => memory address where MAC address is recorded inside wst. + * + * Returns: none + * + */ +void MACSpoofLog(Packet *p, u_int32_t wst_addr) +{ + char timestamp[TIMEBUF_SIZE]; + + if(p){ + ts_print((struct timeval *) (wst_addr + MACspoof_data.offset_time), timestamp); + fprintf(MACspoof_data.logfile, "\n%s\nabnormal sequence number gap reported on addr :" + " %.2x:%.2x:%.2x:%.2x:%.2x:%.2x, sed number: %u\n", + timestamp, + *((u_int8_t *)(wst_addr)), *((u_int8_t *)(wst_addr + 1)), *((u_int8_t *)(wst_addr + 2)), + *((u_int8_t *)(wst_addr + 3)), *((u_int8_t *)(wst_addr + 4)), *((u_int8_t *)(wst_addr + 5)), + p->wifih->seqnum); + + PrintWifiHeader(MACspoof_data.logfile, p); + + if(p->iph != NULL){ + PrintIPHeader(MACspoof_data.logfile, p); + + switch(p->iph->ip_proto) + { + case IPPROTO_TCP: + PrintTCPHeader(MACspoof_data.logfile, p); + break; + + case IPPROTO_UDP: + PrintUDPHeader(MACspoof_data.logfile, p); + break; + + case IPPROTO_ICMP: + PrintICMPHeader(MACspoof_data.logfile, p); + break; + + default: + break; + } + } + } + else{ + ts_print((struct timeval *) (wst_addr + MACspoof_data.offset_time), timestamp); + fprintf(MACspoof_data.logfile, "\n%s End abnormal sequence number gap reported on addr: " + "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", + timestamp, + *((u_int8_t *)(wst_addr)), *((u_int8_t *)(wst_addr + 1)), *((u_int8_t *)(wst_addr + 2)), + *((u_int8_t *)(wst_addr + 3)), *((u_int8_t *)(wst_addr + 4)), *((u_int8_t *)(wst_addr + 5))); + } + + fflush(MACspoof_data.logfile); + return; +} + + +/* + * Function: void MACSpoofCleanExitFunction(int, void *) + * + * Purpose: + * + * Arguments: + * + * Returns: + */ +void MACSpoofCleanExitFunction(int signal, void *arg) +{ + MACSpoofData *MACsd_ptr = (MACSpoofData *) arg; + + DEBUG_WRAP(DebugMessage(DEBUG_MACSPOOF, "MACSpoofCleanExitFunction\n");); + + if(fclose(MACsd_ptr->logfile)) + LogMessage("%s: fclose function failed while snort exiting: %s\n", + MODNAME, strerror(errno)); + return; +} + + +/* + * Function: void MACSpoofCleanRestartFunction(int, void *) + * + * Purpose: + * + * Arguments: + * + * Returns: + */ +void MACSpoofRestartFunction(int signal, void *arg) +{ + MACSpoofData *MACsd_ptr = (MACSpoofData *) arg; + + DEBUG_WRAP(DebugMessage(DEBUG_MACSPOOF, "MACSpoofRestartFunction\n");); + + if(fclose(MACsd_ptr->logfile)) + LogMessage("%s: fclose function failed while snort restarting: %s\n", + MODNAME, strerror(errno)); + return; +} + Index: snort/src/preprocessors/spp_macspoof.h diff -u /dev/null snort/src/preprocessors/spp_macspoof.h:1.2 --- /dev/null Sat Nov 5 19:10:45 2005 +++ snort/src/preprocessors/spp_macspoof.h Fri Jun 24 17:22:16 2005 @@ -0,0 +1,124 @@ +/* +** Copyright (C) 2004 sebastien Gracia +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Copyright disclaimers: +** Direction Centrale des Systèmes de Sécurité de l'Information hereby +** disclaims all copyright interest in the changes and enhancements +** made by sebastien Gracia. +** The Directeur Central de la sécurité des systèmes d'information, +** Henri Serres, 5th fev 2004. +*/ + + +#ifndef __SPP_MACSPOOF_H__ +#define __SPP_MACSPOOF_H__ + + +/* I N C L U D E S +*******************************************************************************/ +#include "snort.h" + + +/* D E F I N E S +*******************************************************************************/ + +#define MACSPOOF_OPT_MASKED_MAC_ADDR "masked_MAC_addr" +#define MACSPOOF_OPT_TOLERATE_GAP "tolerate_gap" +#define MACSPOOF_OPT_THRESHOLD "threshold" +#define MACSPOOF_OPT_EXPIRE_TIMEOUT "expire_timeout" +#define MACSPOOF_OPT_SPOOFED_ADDR_LIMIT "spoofed_addr_limit" +#define MACSPOOF_OPT_PRUNE_PERIOD "prune_period" + +#define MACSPOOF_TOLERATE_GAP 5 +#define MACSPOOF_THRESHOLD 10 +#define MACSPOOF_EXPIRE_TIMEOUT 120 +#define MACSPOOF_SPOOFED_ADDR_LIMIT 100 +#define MACSPOOF_PRUNE_PERIOD 30 + + +typedef struct _MACADDR +{ + u_int8_t MAC_addr[6]; + struct _MACADDR *next, *prev; +} MACADDR; + + +typedef struct _MaskedMACaddrList +{ + struct _MACADDR *head, *tail; +} MaskedMACaddrlist; + + +typedef struct _MACSpoofData +{ + ubi_trRoot spoofed_MACaddrs; + ubi_trRootPtr spoofed_MACaddrsPtr; + + MemPool spoofed_MACaddrPool; + + u_int16_t offset_alert_flag; + u_int16_t offset_seq_number; + u_int16_t offset_gap_number; + u_int16_t offset_time; + + u_int8_t MaskedMACaddrlist_flag; + MaskedMACaddrlist *masked_MACaddrlist; + + u_int32_t tolerate_gap; + u_int32_t threshold; + u_int32_t expire_timeout; + u_int32_t spoofed_addr_limit; + u_int32_t prune_period; + + struct timeval prune_time; + + /** Global Program Data **/ + FILE *logfile; +} MACSpoofData; + +/* this represent the deauthenticated station */ +typedef struct _Spoofed_MACaddr +{ + ubi_trNode Node; /* for the splay tree */ + MemBucket *bucket; + + u_int32_t wst_addr; + u_int8_t addr[6]; +} Spoofed_MACaddr; + + +/* P R O T O T Y P E S +*******************************************************************************/ + +void SetupMACSpoof(); +void MACSpoofInit(u_char *); +void MACSpoofParseArgs(char *); +void MACSpoofDetect(Packet *); +MaskedMACaddrlist *BuildMaskedMACaddrlist(char **); +MaskedMACaddrlist *AllocMaskedMACaddrlist(void); +int ParseMACAddr(u_int8_t *, char *); +MACADDR *InsertMaskedMACaddr(u_int8_t *, MaskedMACaddrlist *); +int MACSpoofedAddrCompareFunc(ubi_trItemPtr, ubi_trNodePtr); +void AddMACSpoofedAddr(u_int32_t); +u_int32_t PruneMACSpoofedAddrs(u_int32_t); +void DeleteMACSpoofedAddr(Spoofed_MACaddr *); +void MACSpoofLog(Packet *, u_int32_t); +void MACSpoofCleanExitFunction(int, void *); +void MACSpoofRestartFunction(int, void *); + + +#endif /* __SPP_MACSPOOF_H__ */ Index: snort/src/preprocessors/spp_rogue_ap.c diff -u /dev/null snort/src/preprocessors/spp_rogue_ap.c:1.2 --- /dev/null Sat Nov 5 19:10:45 2005 +++ snort/src/preprocessors/spp_rogue_ap.c Sat Jun 25 01:46:21 2005 @@ -0,0 +1,646 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: spp_rogue_ap.c,v 1.2 2005/06/25 05:46:21 andrew Exp $ */ + +/* spp_rogue_ap + * + * Purpose: + * + * Detects unauthorized wireless APs and AdHoc networks + * + * Arguments: + * + * , , scan_flag [0 | 1], scan_timeout , expire_timeout + * + * Where: + * + * => a single BSSID or a list specified as [, ...] + * + * => a single channel or a list specified as [, , ...] + * + * scan_flag => enable scanning of multiple channels + * + * scan_timeout => seconds to wait between scanning channels + * + * expire_timeout => expiration timeout for detected access points + * + * + * Effect: + * + * Sends an alert for each rogue network it detects of the form: + * "Rogue AP detected (BSSID XX:XX:XX:XX:XX:XX)" + * + * Comments: + * + * Detection on multiple channels will be implemented later + * + */ + +#include "generators.h" +#include "log.h" +#include "detect.h" +#include "decode.h" +#include "event.h" +#include "plugbase.h" +#include "parser.h" +#include "mstring.h" +#include "debug.h" +#include "util.h" + +#ifndef __SPP_ROGUE_AP_C__ +#define __SPP_ROGUE_AP_C__ +#include "spp_rogue_ap.h" +#endif + + +#define MODNAME "spp_rogue_ap" + +/* external globals from rules.c */ +extern char *file_name; +extern int file_line; + +RogueApData rogue_ap_data; /* preprocessor data */ + +/* + * Function: SetupRogueAp() + * + * Purpose: Registers the preprocessor keyword and initialization + * function into the preprocessor list. This is the function that + * gets called from InitPreprocessors() in plugbase.c. + * + * Arguments: None. + * + * Returns: void function + * + */ +void SetupRogueAp() +{ + /* link the preprocessor keyword to the init function in + the preproc list */ + RegisterPreprocessor("rogue_ap", RogueApInit); + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Preprocessor: RogueAp is setup...\n");); +} + + +/* + * Function: RogueApInit(u_char *) + * + * Purpose: Calls the argument parsing function, performs final setup on data + * structs, links the preproc function into the function list. + * + * Arguments: args => ptr to argument string + * + * Returns: void function + * + */ +void RogueApInit(u_char *args) +{ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Preprocessor: RogueAp Initialized\n");); + + /* parse the argument list from the rules file */ + RogueApParseArgs(args); + + /* Set the preprocessor function into the function list */ + AddFuncToPreprocList(RogueApDetect); +/* AddFuncToCleanExitList(RogueApCleanExit); */ +/* AddFuncToRestartList(RogueApRestart); */ + + + if(rogue_ap_data.scan_flag){ +#warning "Implement channel hopping" + } +} + + + +/* + * Function: RogueApParseArgs(char *) + * + * Purpose: Process the preprocessor arguements from the rules file and + * initialize the preprocessor's data struct. This function doesn't + * have to exist if it makes sense to parse the args in the init + * function. + * + * Arguments: args => argument list + * + * Returns: void function + * + */ + +void RogueApParseArgs(char *args) +{ + char *end_ptr; + char **arg_toks = NULL, **arg_args = NULL; + int i, n, n_args, n_arg_args; + BSSIDList *bssid_list; + u_int8_t bssid[6] = { 0 }; + + + memset(&rogue_ap_data, 0x00, sizeof(rogue_ap_data)); + rogue_ap_data.scan_timeout = ROGUE_AP_SCAN_TIMEOUT; /* default scan_timeout */ + rogue_ap_data.expire_timeout = ROGUE_AP_EXPIRE_TIMEOUT; /* default expire_timeout */ + + if(args == NULL) + return; + + rogue_ap_data.pass_list = BuildApList(&args); + rogue_ap_data.rogue_list = AllocBSSIDList(); + rogue_ap_data.channel_mask = BuildChannelMask(&args); + + if(*args){ + arg_toks = mSplit(args, ",", 3, &n_args, 0); + + if(n_args != 3){ + FatalError("%s: %s (%d) => rogue_ap configuration format: , ," + " scan_flag [ 0 | 1 ], scan_timeout , expire_timeout \n", MODNAME, file_name, file_line); + } + + for(i = 0; i < n_args; i++){ + arg_args = mSplit(arg_toks[i], " ", 2, &n_arg_args, 0); + if(n_arg_args != 2){ + FatalError("%s: %s (%d) => rogue_ap configuration format: , ," + " scan_flag [ 0 | 1 ], scan_timeout , expire_timeout \n", MODNAME, file_name, file_line); + } + + if(strcmp(arg_args[0], "scan_flag") == 0){ + n = strtol(arg_args[1], NULL, 10); + if(n != 0 && n != 1){ + FatalError("%s: %s (%d) => \"scan_flag\" must either be 0 or 1\n", MODNAME, file_name, file_line); + } + rogue_ap_data.scan_flag = n; + } + else if(strcmp(arg_args[0], "scan_timeout") == 0){ + n = strtol(arg_args[1], NULL, 10); + if(n <= 0){ + FatalError("%s: %s (%d) => \"scan_timeout\" must be non-negative\n", MODNAME, file_name, file_line); + } + rogue_ap_data.scan_timeout = n; + } + else if(strcmp(arg_args[0], "expire_timeout") == 0){ + n = strtol(arg_args[1], NULL, 10); + if(n <= 0){ + FatalError("%s: %s (%d) => \"expire_timeout\" must be non-negative\n", MODNAME, file_name, file_line); + } + rogue_ap_data.expire_timeout = n; + } + else{ + FatalError("%s: %s (%d) => Invalid argument \"%s %s\"\n", MODNAME, file_name, file_line, arg_args[0], arg_args[1]); + } + } + } + +} + + + +/* + * Function: RogueApDetect(Packet *) + * + * Purpose: Detect APs and AdHoc networks excluding ones specified + * by the ACCESS_POINTS variable in snort.conf + * + * Arguments: p => pointer to the current packet data struct + * + * Returns: void function + * + */ + +void RogueApDetect(Packet *p) +{ + Event event; + char log_message[128]; + BSSID *bssid_ptr; + u_int8_t *bssid; + time_t time_curr; + + if(!p->wifih) + return; + + time_curr = time(NULL); + + switch(p->wifih->type){ /* point bssid to the correct field in the frame */ + + case TYPE_MANAGEMENT: + bssid = p->wifih->addr3; + break; + + case TYPE_CONTROL: + + if(p->wifih->stype == STYPE_RTS || p->wifih->stype == STYPE_CTS || p->wifih->stype == STYPE_ACK){ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "%s: Received Control frame subtype that does not contain BSSID\n", MODNAME);); + return; + } + else if(p->wifih->stype == STYPE_PS) + bssid = p->wifih->addr1; + else if(p->wifih->stype == STYPE_CFEND) + bssid = p->wifih->addr2; + else if(p->wifih->stype == STYPE_CFEND_CFACK) + bssid = p->wifih->addr2; + else{ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "%s: Received Control frame with unknown/invalid subtype\n", MODNAME);); + return; + } + + break; + + case TYPE_DATA: + if(p->wifih->to_ds){ + if(p->wifih->from_ds){ /* to_ds == 1 && from_ds == 1 */ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "%s: Received Data frame subtype that does not contain BSSID\n", MODNAME);); + return; + } + else /* to_ds == 1 && from_ds == 0 */ + bssid = p->wifih->addr1; + } + else{ + if(p->wifih->from_ds) /* to_ds == 0 && from_ds == 1 */ + bssid = p->wifih->addr2; + else /* to_ds == 0 && from_ds == 0 */ + bssid = p->wifih->addr3; + } + + break; + + default: + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "%s: Received frame with unknown/invalid type\n", MODNAME);); + return; + } + + + /* iterate through rogue AP list */ + bssid_ptr = rogue_ap_data.rogue_list->head; + while(bssid_ptr){ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "%s: Checking %.2X:%.2X:%.2X:%.2X:%.2X:%.2X against rogue " + "(BSSID %.2X:%.2X:%.2X:%.2X:%.2X:%.2X)\n", MODNAME, + bssid[0], bssid[1], bssid[2], + bssid[3], bssid[4], bssid[5], + bssid_ptr->bssid[0], bssid_ptr->bssid[1], bssid_ptr->bssid[2], + bssid_ptr->bssid[3], bssid_ptr->bssid[4], bssid_ptr->bssid[5]);); + + if(time_curr - bssid_ptr->timestamp >= rogue_ap_data.expire_timeout){ + + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "%s: Removing expired AP from rogue AP list (BSSID %.2X:%.2X:%.2X:%.2X:%.2X:%.2X)\n", + MODNAME, bssid_ptr->bssid[0], bssid_ptr->bssid[1], bssid_ptr->bssid[2], + bssid_ptr->bssid[3], bssid_ptr->bssid[4], bssid_ptr->bssid[5]);); + + bssid_ptr = RemoveBSSID(bssid_ptr, rogue_ap_data.rogue_list); /* remove BSSIDs that have expired */ + continue; + } + + if(memcmp(bssid, bssid_ptr->bssid, 6) == 0){ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "%s: BSSID already on rogue AP list (BSSID %.2X:%.2X:%.2X:%.2X:%.2X:%.2X)\n", + MODNAME, bssid_ptr->bssid[0], bssid_ptr->bssid[1], bssid_ptr->bssid[2], + bssid_ptr->bssid[3], bssid_ptr->bssid[4], bssid_ptr->bssid[5]);); + return; /* return if BSSID is already on the list */ + } + + bssid_ptr = bssid_ptr->next; + } + + /* iterate through legitimate AP list */ + for(bssid_ptr = rogue_ap_data.pass_list->head; bssid_ptr != NULL; bssid_ptr = bssid_ptr->next) + if(memcmp(bssid_ptr->bssid, bssid, 6) == 0){ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "%s: BSSID on good AP list (BSSID %.2X:%.2X:%.2X:%.2X:%.2X:%.2X)\n", + MODNAME, bssid_ptr->bssid[0], bssid_ptr->bssid[1], bssid_ptr->bssid[2], + bssid_ptr->bssid[3], bssid_ptr->bssid[4], bssid_ptr->bssid[5]);); + return; /* return if the AP is legit */ + } + /* construct alert message */ + snprintf(log_message, 128, "Rogue AP detected (BSSID %.2X:%.2X:%.2X:%.2X:%.2X:%.2X)", + bssid[0], bssid[1], bssid[2], + bssid[3], bssid[4], bssid[5]); + + SetEvent(&event, GENERATOR_SPP_ROGUE_AP, ROGUE_AP_DETECTED, 1, 4, 2, 0); +/* if(p->iph == NULL) */ /* horrible hack to get this to show up in ACID */ +/* p->iph = (IPHdr *)calloc(1, sizeof(IPHdr)); */ + + CallAlertFuncs(p, log_message, NULL, &event); /* send alert */ + + InsertBSSID(bssid, rogue_ap_data.rogue_list); /* insert BSSID into rogue AP list */ + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "%s: Adding %.2X:%.2X:%.2X:%.2X:%.2X:%.2X to rogue AP list\n", MODNAME, + bssid[0], bssid[1], bssid[2], + bssid[3], bssid[4], bssid[5]);); +} + + + +void RogueApCleanExitFunction(int signal) +{ +#warning "Implement RogueApCleanExitFunction()" + /* clean exit code goes here */ +} + + + +void RogueApRestartFunction(int signal) +{ +#warning "Implement RogueApRestartFunction()" + /* restart code goes here */ +} + + + +/* + * Function: BuildApList(char **) + * + * Purpose: Parses bssid argument from the preprocessor's arguments string into a + * BSSIDList and points it to the end of the bssid argument + * + * Arguments: args_ptr => pointer to a string containing the preprocessor's arguments + * + * Returns: a BSSIDList of BSSIDs to exclude from alerts + * + */ + +BSSIDList *BuildApList(char **args_ptr){ + char *end_ptr; + char *args = *args_ptr; + BSSIDList *bssid_list = NULL; + u_int8_t bssid[6]; + + if(args == NULL || *args == '\0') + FatalError("%s: %s (%d) => rogue_ap configuration format: , ," + " scan_flag [ 0 | 1 ], scan_timeout , expire_timeout \n", MODNAME, file_name, file_line); + + + while(*args && isspace(*args)) /* eat up initial whitespace */ + args++; + + bssid_list = AllocBSSIDList(); + + memset(bssid, 0xff, 6); + InsertBSSID(bssid, bssid_list); + + /* parse the bssid or list of bssids */ + if(args[0] == '['){ + + for(end_ptr = ++args; *end_ptr && *end_ptr != ']'; end_ptr++) + if(*end_ptr == ','){ + *end_ptr = '\0'; + if(ParseBSSID(bssid, args) < 0) + FatalError("%s: %s (%d) => Error parsing BSSID \"%s\"\n", + MODNAME, file_name, file_line, args); + + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "%s: Adding %.2X:%.2X:%.2X:%.2X:%.2X:%.2X to good AP list\n", + MODNAME, bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);); + InsertBSSID(bssid, bssid_list); + args = end_ptr + 1; + } + + *end_ptr = '\0'; + if(ParseBSSID(bssid, args) < 0) + FatalError("%s: %s (%d) => Error parsing BSSID \"%s\"\n", + MODNAME, file_name, file_line, args); + + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "%s: Adding %.2X:%.2X:%.2X:%.2X:%.2X:%.2X to good AP list\n", + MODNAME, bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);); + InsertBSSID(bssid, bssid_list); + args = end_ptr + 1; + while(*args && *args != ',') args++; + if(*args) args++; + } + else{ + + for(end_ptr = args; *end_ptr && *end_ptr != ','; end_ptr++); + + *end_ptr = '\0'; + if(ParseBSSID(bssid, args) < 0) + FatalError("%s: %s (%d) => Error parsing BSSID \"%s\"\n", + MODNAME, file_name, file_line, args); + + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "%s: Adding %.2X:%.2X:%.2X:%.2X:%.2X:%.2X to good AP list\n", + MODNAME, bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);); + InsertBSSID(bssid, bssid_list); + args = end_ptr + 1; + } + + *args_ptr = args; + + return bssid_list; +} + + + +/* + * Function: BuildChannelMask(char **) + * + * Purpose: Parses channel argument from the preprocessor's arguments string into a + * bitmask and points it to the end of the channel argument + * + * Arguments: args_ptr => pointer to a string containing the preprocessor's arguments + * + * Returns: a 16 bit mask containing the channels to be monitored + * + */ + +u_int16_t BuildChannelMask(char **args_ptr){ + char *end_ptr; + char *args = *args_ptr; + u_int16_t mask = 0; + int n; + + if(args == NULL || *args == '\0') + FatalError("%s: %s (%d) => rogue_ap configuration format: , ," + " scan_flag [ 0 | 1 ], scan_timeout , expire_timeout \n", MODNAME, file_name, file_line); + + while(*args && isspace(*args)) args++; /* eat initial white space */ + + + if(args[0] == '['){ + for(end_ptr = ++args; *end_ptr && *end_ptr != ']'; end_ptr++) + if(*end_ptr == ','){ + *end_ptr = '\0'; + n = strtol(args, NULL, 10); + if(n < ROGUE_AP_MIN_CHANNEL || n > ROGUE_AP_MAX_CHANNEL) + FatalError("%s: %s (%d) => Channel \"%s\" out of range\n", + MODNAME, file_name, file_line, args); + mask |= 1 << n; + args = end_ptr + 1; + } + + *end_ptr = '\0'; + n = strtol(args, NULL, 10); + if(n < ROGUE_AP_MIN_CHANNEL || n > ROGUE_AP_MAX_CHANNEL) + FatalError("%s: %s (%d) => Channel \"%s\" out of range\n", + MODNAME, file_name, file_line, args); + mask |= 1 << n; + args = end_ptr + 1; + + /* eat up to and including next ',' */ + while(*args && *args != ',') args++; + if(*args) args++; + } + else{ + for(end_ptr = args; *end_ptr && *end_ptr != ','; end_ptr++); + *end_ptr = '\0'; + n = strtol(args, NULL, 10); + if(n < ROGUE_AP_MIN_CHANNEL || n > ROGUE_AP_MAX_CHANNEL) + FatalError("%s: %s (%d) => Channel \"%s\" out of range\n", + MODNAME, file_name, file_line, args); + mask |= 1 << n; + args = end_ptr + 1; + } + + + + *args_ptr = args; + + return mask; +} + + + +/* + * Function: AllocBSSIDList(void) + * + * Purpose: Allocates a BSSIDList + * + * Arguments: None + * + * Returns: A pointer to the newly allocated BSSIDList or + * NULL on error + * + */ + + +BSSIDList *AllocBSSIDList(void){ + return (BSSIDList *)calloc(1, sizeof(BSSIDList)); +} + + + +void DestroyBSSIDList(BSSIDList *list){ +#warning "Implement DestroyBSSIDList()" +} + + + +/* + * Function: InsertBSSID(u_int8_t *, BSSIDList *) + * + * Purpose: Creates a BSSID node from a byte array and inserts + * it into the specified BSSIDList + * + * Arguments: bssid => byte array containing a BSSID + * list => BSSIDList to insert new node in + * + * Returns: pointer to newly inserted BSSID node or NULL + * if bssid or list is NULL + * + */ + +BSSID *InsertBSSID(u_int8_t *bssid, BSSIDList *list){ + BSSID *bssid_ptr = NULL; + + if(list == NULL || bssid == NULL) + return NULL; + + /* allocate new BSSID node */ + bssid_ptr = (BSSID *)malloc(sizeof(BSSID)); + bssid_ptr->not_flag = 0; + memcpy(bssid_ptr->bssid, bssid, 6); + bssid_ptr->timestamp = time(NULL); + bssid_ptr->next = NULL; + bssid_ptr->prev = NULL; + + if(list->head == NULL && list->tail == NULL){ /* if empty list, set head and tail */ + list->head = bssid_ptr; + list->tail = bssid_ptr; + } + else{ /* if already a tail, link new node in */ + bssid_ptr->prev = list->tail; + list->tail->next = bssid_ptr; + list->tail = bssid_ptr; + } + + return bssid_ptr; /* return pointer to new BSSID node */ +} + + + +/* + * Function: RemoveBSSID(BSSID *, BSSIDList *) + * + * Purpose: Removes a BSSID node from a BSSIDList + * + * Arguments: node => pointer to BSSID node to be removed + * list => BSSIDList to remove node from + * + * Returns: next BSSID node in the list or NULL if one + * does not exist + */ + +BSSID *RemoveBSSID(BSSID *node, BSSIDList *list){ + BSSID *bssid_ptr; + + if(list == NULL) + return node; + + if(node == list->head){ + if((list->head = node->next) == NULL) + list->tail = NULL; + else + node->next->prev = NULL; + } + else{ + if((node->next->prev = node->next) == NULL) + list->tail = node->prev; + else + node->next->prev = node->prev; + } + + bssid_ptr = node->next; + free(node); + + return bssid_ptr; +} + + + +/* + * Function: ParseBSSID(u_int8_t *, char *) + * + * Purpose: Parses BSSIDs from a character string and stores them + * in a byte array. + * + * Arguments: bssid => pointer to byte array to store parsed BSSID in + * mac_str => character string containing BSSID + * + * Returns: 0 on success, -1 on error + * + */ + +int ParseBSSID(u_int8_t *bssid, char *mac_str){ + int i = 0; + char *next = mac_str; + + while(*next){ + if((bssid[i] = strtol(mac_str, &next, 16)) > 255){ + return -1; + } + if(mac_str != next && i < 6){ + mac_str = next + 1; + i++; + } + else + return -1; + } + + return 0; +} Index: snort/src/preprocessors/spp_rogue_ap.h diff -u /dev/null snort/src/preprocessors/spp_rogue_ap.h:1.2 --- /dev/null Sat Nov 5 19:10:45 2005 +++ snort/src/preprocessors/spp_rogue_ap.h Sat Jul 26 23:21:44 2003 @@ -0,0 +1,132 @@ +/* +** Copyright (C) 2003 Andrew Lockhart +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: spp_rogue_ap.h,v 1.2 2003/07/27 03:21:44 andrew Exp $ */ +/* Snort Preprocessor Plugin Header File RogueAp */ + +#include "snort.h" + +#ifndef __SPP_ROGUE_AP_H__ +#define __SPP_ROGUE_AP_H__ + +#define ROGUE_AP_NUM_ARGS 2 +#define ROGUE_AP_SCAN_TIMEOUT 60 +#define ROGUE_AP_EXPIRE_TIMEOUT 60 * 60 * 12 /* 12 hours */ +#define ROGUE_AP_MAX_BSSIDS 255 +#define ROGUE_AP_MIN_CHANNEL 1 +#define ROGUE_AP_MAX_CHANNEL 11 + +#ifdef __SPP_ROGUE_AP_C__ + +typedef struct _BSSID { + u_int8_t not_flag; + u_int8_t bssid[6]; + time_t timestamp; + struct _BSSID *next, *prev; +} BSSID; + +typedef struct _BSSIDList { + struct _BSSID *head, *tail; +} BSSIDList; + +typedef struct _RogueApData { + BSSIDList *pass_list; /* list of our BSSIDs -- var ACCESS_POINTS from snort.conf */ + BSSIDList *rogue_list; /* list of gathered rogue BSSIDs */ + u_int16_t channel_mask; /* bitmask for channels 1-11 or 1-14 */ + u_int8_t scan_flag; /* channel scan flag */ + time_t scan_timeout; /* scan_timeout from snort.conf */ + time_t expire_timeout; /* expire_timeout from snort.conf */ + time_t scan_timer; /* timer for channel switching */ +} RogueApData; + +typedef enum { /* 802.11 frame types */ + TYPE_INVALID = -1, + TYPE_MANAGEMENT = 0x00, + TYPE_CONTROL = 0x01, + TYPE_DATA = 0x02 +} wifi_type_t; + +typedef enum { /* 802.11 management frame subtypes */ + STYPE_ASSOCREQ = 0x00, /* Subtypes are already AND'ed with their corresponding Types */ + STYPE_ASSOCRESP = 0x01, /* to prevent false positives and the need for checking the type */ + STYPE_REASSOC_REQ = 0x02, /* independently */ + STYPE_REASSOC_RESP = 0x03, + STYPE_PROBEREQ = 0x04, + STYPE_PROBERESP = 0x05, + STYPE_BEACON = 0x08, + STYPE_ATIM = 0x09, + STYPE_DISASSOC = 0x0a, + STYPE_AUTH = 0x0b, + STYPE_DEAUTH = 0x0c, + + STYPE_INVALID = 0x0d, +/* STYPE_INVALID = 0x0e, */ +/* STYPE_INVALID = 0x0f, */ +/* STYPE_INVALID = 0x10, */ +/* STYPE_INVALID = 0x11, */ +/* STYPE_INVALID = 0x12, */ +/* STYPE_INVALID = 0x13, */ +/* STYPE_INVALID = 0x14, */ +/* STYPE_INVALID = 0x15, */ +/* STYPE_INVALID = 0x16, */ +/* STYPE_INVALID = 0x17, */ +/* STYPE_INVALID = 0x18, */ +/* STYPE_INVALID = 0x19, */ + + +/* 802.11 control frame subtypes */ + STYPE_PS = 0x0a, + STYPE_RTS = 0x0b, + STYPE_CTS = 0x0c, + STYPE_ACK = 0x0d, + STYPE_CFEND = 0x0e, + STYPE_CFEND_CFACK = 0x0f, + +/* 802.11 data frame subtypes */ + STYPE_DATA = 0x00, + STYPE_CFACK = 0x01, + STYPE_CFPOLL = 0x02, + STYPE_CFACK_CFPOLL = 0x03, + STYPE_NULLFUNC = 0x04, + STYPE_CFACK_NULLFUNC = 0x05, + STYPE_CFPOLL_NULLFUNC = 0x06, + STYPE_CFACK_CFPOLL_NULLFUNC = 0x07 +} wifi_stype_t; + + +BSSIDList *BuildApList(char **); +u_int16_t BuildChannelMask(char **); +BSSIDList *AllocBSSIDList(void); +void DestroyBSSIDList(BSSIDList *); +BSSID *InsertBSSID(u_int8_t *, BSSIDList *); +BSSID *RemoveBSSID(BSSID *, BSSIDList *); +int ParseBSSID(u_int8_t *, char *); + +#endif /* __SPP_ROGUE_AP_C__ */ + + +void SetupRogueAp(); +void RogueApInit(u_char *); +void RogueApParseArgs(char *); +void RogueApDetect(Packet *); +void RogueApRestart(int); +void RogueApCleanExit(int); + + + +#endif /* !__SPP_ROGUE_AP_H__ */ Index: snort/src/win32/WIN32-Prj/Makefile diff -u /dev/null snort/src/win32/WIN32-Prj/Makefile:1.1.1.2 --- /dev/null Sat Nov 5 19:10:49 2005 +++ snort/src/win32/WIN32-Prj/Makefile Wed Apr 21 18:26:57 2004 @@ -0,0 +1,7 @@ +# Microsoft Visual Studio NMAKE File +# +# $Id: Makefile,v 1.2 2003/08/31 23:04:19 chris_reid Exp $ + +!MESSAGE Please use the following command line instead: +!MESSAGE NMAKE /f "snort.mak" CFG="?" +