1 /* $Id$ */
2 /*
3 ** Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
4 ** Copyright (C) 2004-2013 Sourcefire, Inc.
5 ** Copyright (C) 2001-2004 Jeff Nathan <jeff@snort.org>
6 **
7 ** This program is free software; you can redistribute it and/or modify
8 ** it under the terms of the GNU General Public License Version 2 as
9 ** published by the Free Software Foundation. You may not use, modify or
10 ** distribute this program under any other version of the GNU General
11 ** Public License.
12 **
13 ** This program is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ** GNU General Public License for more details.
17 **
18 ** You should have received a copy of the GNU General Public License
19 ** along with this program; if not, write to the Free Software
20 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 */
22
23 /* Snort ARPspoof Preprocessor Plugin
24 * by Jeff Nathan <jeff@snort.org>
25 * Version 0.1.4
26 *
27 * Purpose:
28 *
29 * This preprocessor looks for anomalies in ARP traffic and attempts to
30 * maliciously overwrite ARP cache information on hosts.
31 *
32 * Arguments:
33 *
34 * To check for unicast ARP requests use:
35 * arpspoof: -unicast
36 *
37 * WARNING: this can generate false positives as Linux systems send unicast
38 * ARP requests repetatively for entries in their cache.
39 *
40 * This plugin also takes a list of IP addresses and MAC address in the form:
41 * arpspoof_detect_host: 10.10.10.10 29:a2:9a:29:a2:9a
42 * arpspoof_detect_host: 192.168.40.1 f0:0f:00:f0:0f:00
43 * and so forth...
44 *
45 * Effect:
46 * By comparing information in the Ethernet header to the ARP frame, obvious
47 * anomalies are detected. Also, utilizing a user supplied list of IP
48 * addresses and MAC addresses, ARP traffic appearing to have originated from
49 * any IP in that list is carefully examined by comparing the source hardware
50 * address to the user supplied hardware address. If there is a mismatch, an
51 * alert is generated as either an ARP request or REPLY can be used to
52 * overwrite cache information on a remote host. This should only be used for
53 * hosts/devices on the **same layer 2 segment** !!
54 *
55 * Bugs:
56 * This is a proof of concept ONLY. It is clearly not complete. Also, the
57 * lookup function LookupIPMacEntryByIP is in need of optimization. The
58 * arpspoof_detect_host functionality may false alarm in redundant environments. * Also, see the comment above pertaining to Linux systems.
59 *
60 * Thanks:
61 *
62 * First and foremost Patrick Mullen who sat beside me and helped every step of
63 * the way. Andrew Baker for graciously supplying the tougher parts of this
64 * code. W. Richard Stevens for readable documentation and finally
65 * Marty for being a badass. All your packets are belong to Marty.
66 *
67 */
68
69 /* I N C L U D E S ************************************************/
70 #include <assert.h>
71 #include <sys/types.h>
72 #include <stdlib.h>
73 #include <string.h>
74 #include <stdio.h>
75
76 #ifndef WIN32
77 # include <sys/time.h>
78 # include <sys/socket.h>
79 # include <netinet/in.h>
80 # include <arpa/inet.h>
81 #else
82 # include <time.h>
83 #endif
84
85 #ifdef HAVE_CONFIG_H
86 #include "config.h"
87 #endif
88
89 #include "generators.h"
90 #include "log.h"
91 #include "detect.h"
92 #include "decode.h"
93 #include "event.h"
94 #include "plugbase.h"
95 #include "parser.h"
96 #include "mstring.h"
97 #include "snort_debug.h"
98 #include "util.h"
99 #include "event_queue.h"
100
101 #include "snort.h"
102 #include "profiler.h"
103 #include "sfPolicy.h"
104 #include "session_api.h"
105
106 /* D E F I N E S **************************************************/
107 #define MODNAME "spp_arpspoof"
108 #define WITHUNICAST "-unicast"
109
110
111 /* D A T A S T R U C T U R E S **********************************/
112 typedef struct _IPMacEntry
113 {
114 uint32_t ipv4_addr;
115 uint8_t mac_addr[6];
116 uint8_t pad[2];
117 } IPMacEntry;
118
119 typedef struct _IPMacEntryListNode
120 {
121 IPMacEntry *ip_mac_entry;
122 struct _IPMacEntryListNode *next;
123 } IPMacEntryListNode;
124
125 typedef struct _IPMacEntryList
126 {
127 int size;
128 IPMacEntryListNode *head;
129 IPMacEntryListNode *tail;
130 } IPMacEntryList;
131
132 typedef struct _ArpSpoofConfig
133 {
134 int check_unicast_arp;
135 int check_overwrite;
136 IPMacEntryList *ipmel;
137
138 } ArpSpoofConfig;
139
140
141 /* G L O B A L S **************************************************/
142 static tSfPolicyUserContextId arp_spoof_config = NULL;
143
144 static const uint8_t bcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
145
146 #ifdef PERF_PROFILING
147 PreprocStats arpPerfStats;
148 #endif
149
150
151 /* P R O T O T Y P E S ********************************************/
152 static void ARPspoofInit(struct _SnortConfig *, char *args);
153 static void ARPspoofHostInit(struct _SnortConfig *, char *args);
154 static void ParseARPspoofArgs(ArpSpoofConfig *, char *);
155 static void ParseARPspoofHostArgs(IPMacEntryList *, char *);
156 static void DetectARPattacks(Packet *p, void *context);
157 static void ARPspoofCleanExit(int signal, void *unused);
158 static void FreeIPMacEntryList(IPMacEntryList *ip_mac_entry_list);
159 static int AddIPMacEntryToList(IPMacEntryList *ip_mac_entry_list,
160 IPMacEntry *ip_mac_entry);
161 static IPMacEntry *LookupIPMacEntryByIP(IPMacEntryList *ip_mac_entry_list,
162 uint32_t ipv4_addr);
163 static void ArpSpoofFreeConfig(tSfPolicyUserContextId config);
164
165 #ifdef DEBUG
166 static void PrintIPMacEntryList(IPMacEntryList *ip_mac_entry_list);
167 #endif
168
169 #ifdef SNORT_RELOAD
170 static void ARPspoofReload(struct _SnortConfig *, char *, void **);
171 static void ARPspoofReloadHost(struct _SnortConfig *, char *, void **);
172 static void * ARPspoofReloadSwap(struct _SnortConfig *, void *);
173 static void ARPspoofReloadSwapFree(void *);
174 #endif
175
176
SetupARPspoof(void)177 void SetupARPspoof(void)
178 {
179 #ifndef SNORT_RELOAD
180 RegisterPreprocessor("arpspoof", ARPspoofInit);
181 RegisterPreprocessor("arpspoof_detect_host", ARPspoofHostInit);
182 #else
183 RegisterPreprocessor("arpspoof", ARPspoofInit, ARPspoofReload, NULL,
184 ARPspoofReloadSwap, ARPspoofReloadSwapFree);
185 RegisterPreprocessor("arpspoof_detect_host", ARPspoofHostInit,
186 ARPspoofReloadHost, NULL, NULL, NULL);
187 #endif
188
189 DEBUG_WRAP(DebugMessage(DEBUG_INIT,
190 "Preprocessor: ARPspoof is setup...\n"););
191 }
192
193
ARPspoofInit(struct _SnortConfig * sc,char * args)194 static void ARPspoofInit(struct _SnortConfig *sc, char *args)
195 {
196 int policy_id = (int)getParserPolicy(sc);
197 ArpSpoofConfig *pDefaultPolicyConfig = NULL;
198 ArpSpoofConfig *pCurrentPolicyConfig = NULL;
199
200 DEBUG_WRAP(DebugMessage(DEBUG_INIT,
201 "Preprocessor: ARPspoof Initialized\n"););
202
203 if (arp_spoof_config == NULL)
204 {
205 arp_spoof_config = sfPolicyConfigCreate();
206
207 #ifdef PERF_PROFILING
208 RegisterPreprocessorProfile("arpspoof", &arpPerfStats, 0, &totalPerfStats, NULL);
209 #endif
210
211 AddFuncToPreprocCleanExitList(ARPspoofCleanExit, NULL, PRIORITY_LAST, PP_ARPSPOOF);
212 }
213
214 sfPolicyUserPolicySet (arp_spoof_config, policy_id);
215 pDefaultPolicyConfig = (ArpSpoofConfig *)sfPolicyUserDataGetDefault(arp_spoof_config);
216 pCurrentPolicyConfig = (ArpSpoofConfig *)sfPolicyUserDataGetCurrent(arp_spoof_config);
217
218 if ((policy_id != 0) && (pDefaultPolicyConfig == NULL))
219 {
220 ParseError("Arpspoof configuration: Must configure default policy "
221 "if other policies are to be configured.");
222 }
223
224 if (pCurrentPolicyConfig)
225 {
226 ParseError("Arpspoof can only be configured once.\n");
227 }
228
229 pCurrentPolicyConfig = (ArpSpoofConfig *)SnortAlloc(sizeof(ArpSpoofConfig));
230 if (!pCurrentPolicyConfig)
231 {
232 ParseError("Arpspoof preprocessor: memory allocate failed.\n");
233 }
234
235 sfPolicyUserDataSetCurrent(arp_spoof_config, pCurrentPolicyConfig);
236 /* Add arpspoof to the preprocessor function list */
237 AddFuncToPreprocList(sc, DetectARPattacks, PRIORITY_NETWORK, PP_ARPSPOOF, PROTO_BIT__ARP);
238 session_api->enable_preproc_all_ports( sc, PP_ARPSPOOF, PROTO_BIT__ARP );
239
240 //policy independent configuration. First policy defines actual values.
241 if (policy_id != 0)
242 {
243 pCurrentPolicyConfig->check_unicast_arp =
244 ((ArpSpoofConfig *)sfPolicyUserDataGetDefault(arp_spoof_config))->check_unicast_arp;
245 return;
246 }
247
248 /* Parse the arpspoof arguments from snort.conf */
249 ParseARPspoofArgs(pCurrentPolicyConfig, args);
250 }
251
252
253 /**
254 * Parse arguments passed to the arpspoof keyword.
255 *
256 * @param args preprocessor argument string
257 *
258 * @return void function
259 */
ParseARPspoofArgs(ArpSpoofConfig * config,char * args)260 static void ParseARPspoofArgs(ArpSpoofConfig *config, char *args)
261 {
262 if ((config == NULL) || (args == NULL))
263 return;
264
265 if (strcasecmp(WITHUNICAST, args) == 0)
266 config->check_unicast_arp = 1;
267 else
268 ParseError("Invalid option to arpspoof configuration");
269 }
270
271
ARPspoofHostInit(struct _SnortConfig * sc,char * args)272 static void ARPspoofHostInit(struct _SnortConfig *sc, char *args)
273 {
274 tSfPolicyId policy_id = getParserPolicy(sc);
275 ArpSpoofConfig *pPolicyConfig = NULL;
276
277 if (arp_spoof_config == NULL)
278 {
279 ParseError("Please activate arpspoof before trying to "
280 "use arpspoof_detect_host.");
281 }
282
283 sfPolicyUserPolicySet(arp_spoof_config, policy_id);
284 pPolicyConfig = (ArpSpoofConfig *)sfPolicyUserDataGetCurrent(arp_spoof_config);
285
286 if (pPolicyConfig == NULL)
287 {
288 ParseError("Please activate arpspoof before trying to "
289 "use arpspoof_detect_host.");
290 }
291
292 DEBUG_WRAP(DebugMessage(DEBUG_INIT,
293 "Preprocessor: ARPspoof (overwrite list) Initialized\n"););
294
295 if (pPolicyConfig->ipmel == NULL)
296 {
297 pPolicyConfig->ipmel = (IPMacEntryList *)SnortAlloc(sizeof(IPMacEntryList));
298 }
299
300 /* Add MAC/IP pairs to ipmel */
301 ParseARPspoofHostArgs(pPolicyConfig->ipmel, args);
302
303 if (pPolicyConfig->check_overwrite == 0)
304 pPolicyConfig->check_overwrite = 1;
305 }
306
307
308 /**
309 * Parse arguments passed to the arpspoof_detect_host keyword.
310 *
311 * @param args preprocessor argument string
312 *
313 * @return void function
314 */
ParseARPspoofHostArgs(IPMacEntryList * ipmel,char * args)315 static void ParseARPspoofHostArgs(IPMacEntryList *ipmel, char *args)
316 {
317 char **toks;
318 char **macbytes;
319 int num_toks, num_macbytes;
320 int i;
321 struct in_addr IP_struct;
322 IPMacEntry *ipme = NULL;
323
324 if (ipmel == NULL)
325 return;
326
327 toks = mSplit(args, " ", 0, &num_toks, '\\');
328
329 if (num_toks != 2)
330 ParseError("Invalid arguments to arpspoof_detect_host.");
331
332 /* Add entries */
333 ipme = (IPMacEntry *)SnortAlloc(sizeof(IPMacEntry));
334
335 if ((IP_struct.s_addr = inet_addr(toks[0])) == INADDR_NONE)
336 {
337 ParseError("Invalid IP address as first argument of "
338 "IP/MAC pair to arpspoof_detect_host.");
339 }
340
341 ipme->ipv4_addr = (uint32_t)IP_struct.s_addr;
342
343 macbytes = mSplit(toks[1], ":", 6, &num_macbytes, '\\');
344
345 if (num_macbytes < 6)
346 {
347 ParseError("Invalid MAC address as second argument of IP/MAC "
348 "pair to arpspoof_detect_host.");
349 }
350 else
351 {
352 for (i = 0; i < 6; i++)
353 ipme->mac_addr[i] = (uint8_t) strtoul(macbytes[i], NULL, 16);
354 }
355
356 AddIPMacEntryToList(ipmel, ipme);
357
358 mSplitFree(&toks, num_toks);
359 mSplitFree(&macbytes, num_macbytes);
360
361 #if defined(DEBUG)
362 PrintIPMacEntryList(ipmel);
363 #endif
364 }
365
366
367 /**
368 * Detect ARP anomalies and overwrite attacks.
369 *
370 * @param p packet to detect anomalies and overwrite attacks on
371 * @param context unused
372 *
373 * @return void function
374 */
DetectARPattacks(Packet * p,void * context)375 static void DetectARPattacks(Packet *p, void *context)
376 {
377 IPMacEntry *ipme;
378 ArpSpoofConfig *aconfig = NULL;
379 const uint8_t *dst_mac_addr = NULL, *src_mac_addr = NULL;
380 PROFILE_VARS;
381 sfPolicyUserPolicySet (arp_spoof_config, getNapRuntimePolicy());
382 aconfig = (ArpSpoofConfig *)sfPolicyUserDataGetCurrent(arp_spoof_config);
383 uint32_t *arp_spa;
384
385 /* is the packet valid? */
386 if ( aconfig == NULL || p->ah == NULL)
387 return;
388
389 // preconditions - what we registered for
390 if( p->eh != NULL)
391 {
392 src_mac_addr = p->eh->ether_src;
393 dst_mac_addr = p->eh->ether_dst;
394 }
395 #ifndef NO_NON_ETHER_DECODER
396 else if( p->wifih != NULL )
397 {
398 if ((p->wifih->frame_control & WLAN_FLAG_TODS) &&
399 (p->wifih->frame_control & WLAN_FLAG_FROMDS))
400 {
401 dst_mac_addr = p->wifih->addr3;
402 src_mac_addr = p->wifih->addr4;
403 }
404 else if (p->wifih->frame_control & WLAN_FLAG_TODS)
405 {
406 src_mac_addr = p->wifih->addr2;
407 dst_mac_addr = p->wifih->addr3;
408 }
409 else if (p->wifih->frame_control & WLAN_FLAG_FROMDS)
410 {
411 dst_mac_addr = p->wifih->addr1;
412 src_mac_addr = p->wifih->addr3;
413 }
414 else
415 {
416 dst_mac_addr = p->wifih->addr1;
417 src_mac_addr = p->wifih->addr2;
418 }
419 }
420 #endif
421 else
422 {
423 return;
424 }
425
426 /* is the ARP protocol type IP and the ARP hardware type Ethernet? */
427 if ((ntohs(p->ah->ea_hdr.ar_hrd) != 0x0001) ||
428 (ntohs(p->ah->ea_hdr.ar_pro) != ETHERNET_TYPE_IP))
429 return;
430
431 PREPROC_PROFILE_START(arpPerfStats);
432
433 switch(ntohs(p->ah->ea_hdr.ar_op))
434 {
435 case ARPOP_REQUEST:
436 if (aconfig->check_unicast_arp)
437 {
438 if (memcmp((u_char *)dst_mac_addr, (u_char *)bcast, 6) != 0)
439 {
440 SnortEventqAdd(GENERATOR_SPP_ARPSPOOF,
441 ARPSPOOF_UNICAST_ARP_REQUEST, 1, 0, 3,
442 ARPSPOOF_UNICAST_ARP_REQUEST_STR, 0);
443
444 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,
445 "MODNAME: Unicast request\n"););
446 }
447 }
448 else if (memcmp((u_char *)src_mac_addr,
449 (u_char *)p->ah->arp_sha, 6) != 0)
450 {
451 SnortEventqAdd(GENERATOR_SPP_ARPSPOOF,
452 ARPSPOOF_ETHERFRAME_ARP_MISMATCH_SRC, 1, 0, 3,
453 ARPSPOOF_ETHERFRAME_ARP_MISMATCH_SRC_STR, 0);
454
455 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,
456 "MODNAME: Ethernet/ARP mismatch request\n"););
457 }
458 break;
459 case ARPOP_REPLY:
460 if (memcmp((u_char *)src_mac_addr,
461 (u_char *)p->ah->arp_sha, 6) != 0)
462 {
463 SnortEventqAdd(GENERATOR_SPP_ARPSPOOF,
464 ARPSPOOF_ETHERFRAME_ARP_MISMATCH_SRC, 1, 0, 3,
465 ARPSPOOF_ETHERFRAME_ARP_MISMATCH_SRC_STR, 0);
466
467 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,
468 "MODNAME: Ethernet/ARP mismatch reply src\n"););
469 }
470 else if (memcmp((u_char *)dst_mac_addr,
471 (u_char *)p->ah->arp_tha, 6) != 0)
472 {
473 SnortEventqAdd(GENERATOR_SPP_ARPSPOOF,
474 ARPSPOOF_ETHERFRAME_ARP_MISMATCH_DST, 1, 0, 3,
475 ARPSPOOF_ETHERFRAME_ARP_MISMATCH_DST_STR, 0);
476
477 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,
478 "MODNAME: Ethernet/ARP mismatch reply dst\n"););
479 }
480 break;
481 }
482 PREPROC_PROFILE_END(arpPerfStats);
483
484 /* return if the overwrite list hasn't been initialized */
485 if (!aconfig->check_overwrite)
486 return;
487
488 /* LookupIPMacEntryByIP() is too slow, will be fixed later */
489 arp_spa = (uint32_t *)&p->ah->arp_spa[0];
490 if ((ipme = LookupIPMacEntryByIP(aconfig->ipmel,
491 *arp_spa)) == NULL)
492 {
493 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,
494 "MODNAME: LookupIPMacEntryByIp returned NULL\n"););
495 return;
496 }
497 else
498 {
499 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,
500 "MODNAME: LookupIPMacEntryByIP returned %p\n", ipme););
501
502 /* If the Ethernet source address or the ARP source hardware address
503 * in p doesn't match the MAC address in ipme, then generate an alert
504 */
505 if ((memcmp((uint8_t *)src_mac_addr,
506 (uint8_t *)ipme->mac_addr, 6)) ||
507 (memcmp((uint8_t *)p->ah->arp_sha,
508 (uint8_t *)ipme->mac_addr, 6)))
509 {
510 SnortEventqAdd(GENERATOR_SPP_ARPSPOOF,
511 ARPSPOOF_ARP_CACHE_OVERWRITE_ATTACK, 1, 0, 3,
512 ARPSPOOF_ARP_CACHE_OVERWRITE_ATTACK_STR, 0);
513
514 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,
515 "MODNAME: Attempted ARP cache overwrite attack\n"););
516
517 return;
518 }
519 }
520 }
521
522
523 /**
524 * Add IP/MAC pair to a linked list.
525 *
526 * @param ip_mac_entry_list pointer to the list structure
527 * @param ip_mac_entry linked list structure node
528 *
529 * @return 0 if the node is added successfully, 1 otherwise
530 */
AddIPMacEntryToList(IPMacEntryList * ip_mac_entry_list,IPMacEntry * ip_mac_entry)531 static int AddIPMacEntryToList(IPMacEntryList *ip_mac_entry_list,
532 IPMacEntry *ip_mac_entry)
533 {
534 IPMacEntryListNode *newNode;
535
536 if (ip_mac_entry == NULL || ip_mac_entry_list == NULL)
537 return 1;
538
539 newNode = (IPMacEntryListNode *)SnortAlloc(sizeof(IPMacEntryListNode));
540 newNode->ip_mac_entry = ip_mac_entry;
541 newNode->next = NULL;
542
543 if (ip_mac_entry_list->head == NULL)
544 {
545 ip_mac_entry_list->head = newNode;
546 ip_mac_entry_list->size = 1;
547 }
548 else
549 {
550 ip_mac_entry_list->tail->next = newNode;
551 ip_mac_entry_list->size += 1;
552 }
553 ip_mac_entry_list->tail = newNode;
554 return 0;
555 }
556
557
558 /**
559 * Locate a linked list structure node by an IP address.
560 *
561 * @param ip_mac_entry_list pointer to the list structure
562 * @param ipv4_addr IPv4 address as an unsigned 32-bit integer
563 *
564 * @return pointer to a structure node if a match is found, NULL otherwise
565 */
LookupIPMacEntryByIP(IPMacEntryList * ip_mac_entry_list,uint32_t ipv4_addr)566 static IPMacEntry *LookupIPMacEntryByIP(IPMacEntryList *ip_mac_entry_list,
567 uint32_t ipv4_addr)
568 {
569 IPMacEntryListNode *current;
570 #if defined(DEBUG)
571 char *cha, *chb;
572 sfaddr_t ina, inb;
573 #endif
574
575 if (ip_mac_entry_list == NULL)
576 return NULL;
577
578 for (current = ip_mac_entry_list->head; current != NULL;
579 current = current->next)
580 {
581 #if defined(DEBUG)
582 sfip_set_raw(&ina, &ipv4_addr, AF_INET);
583 sfip_set_raw(&inb, ¤t->ip_mac_entry->ipv4_addr, AF_INET);
584 cha = strdup(inet_ntoa(IP_ARG(ina)));
585 chb = strdup(inet_ntoa(IP_ARG(inb)));
586
587 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,
588 "MODNAME: LookupIPMacEntryByIP() comparing %s to %s\n", cha, chb););
589 free(cha);
590 free(chb);
591 #endif
592 if (current->ip_mac_entry->ipv4_addr == ipv4_addr)
593 {
594 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,
595 "MODNAME: LookupIPMecEntryByIP() match!"););
596
597 return current->ip_mac_entry;
598 }
599 }
600 return NULL;
601 }
602
603
604 /**
605 * Free the linked list of IP/MAC address pairs
606 *
607 * @param ip_mac_entry_list pointer to the list structure
608 *
609 * @return void function
610 */
FreeIPMacEntryList(IPMacEntryList * ip_mac_entry_list)611 static void FreeIPMacEntryList(IPMacEntryList *ip_mac_entry_list)
612 {
613 IPMacEntryListNode *prev;
614 IPMacEntryListNode *current;
615
616 if (ip_mac_entry_list == NULL)
617 return;
618
619 current = ip_mac_entry_list->head;
620 while (current != NULL)
621 {
622 if (current->ip_mac_entry != NULL)
623 free(current->ip_mac_entry);
624
625 prev = current;
626 current = current->next;
627 free(prev);
628 }
629 ip_mac_entry_list->head = NULL;
630 ip_mac_entry_list->size = 0;
631
632 return;
633 }
634
635
ARPspoofCleanExit(int signal,void * unused)636 static void ARPspoofCleanExit(int signal, void *unused)
637 {
638 ArpSpoofFreeConfig(arp_spoof_config);
639 arp_spoof_config = NULL;
640 }
641
ArpSpoofFreeConfigPolicy(tSfPolicyUserContextId config,tSfPolicyId policyId,void * pData)642 static int ArpSpoofFreeConfigPolicy(tSfPolicyUserContextId config,tSfPolicyId policyId, void* pData )
643 {
644 ArpSpoofConfig *pPolicyConfig = (ArpSpoofConfig *)pData;
645 if(pPolicyConfig->ipmel != NULL)
646 {
647 FreeIPMacEntryList(pPolicyConfig->ipmel);
648 free(pPolicyConfig->ipmel);
649 }
650 sfPolicyUserDataClear (config, policyId);
651 free(pPolicyConfig);
652 return 0;
653 }
654
ArpSpoofFreeConfig(tSfPolicyUserContextId config)655 static void ArpSpoofFreeConfig(tSfPolicyUserContextId config)
656 {
657
658 if (config == NULL)
659 return;
660
661 sfPolicyUserDataFreeIterate (config, ArpSpoofFreeConfigPolicy);
662 sfPolicyConfigDelete(config);
663
664 }
665
666
667 #ifdef DEBUG
668 /**
669 * Print the overwrite list for debugging purposes
670 *
671 * @param ip_mac_entry_list pointer to the list structure
672 *
673 * @return void function
674 */
PrintIPMacEntryList(IPMacEntryList * ip_mac_entry_list)675 static void PrintIPMacEntryList(IPMacEntryList *ip_mac_entry_list)
676 {
677 IPMacEntryListNode *current;
678 int i;
679 sfaddr_t in;
680
681 if (ip_mac_entry_list == NULL)
682 return;
683
684 current = ip_mac_entry_list->head;
685 printf("Arpspoof IPMacEntry List");
686 printf(" Size: %i\n", ip_mac_entry_list->size);
687 while (current != NULL)
688 {
689 sfip_set_raw(&in, ¤t->ip_mac_entry->ipv4_addr, AF_INET);
690 printf("%s -> ", inet_ntoa(IP_ARG(in)));
691 for (i = 0; i < 6; i++)
692 {
693 printf("%02x", current->ip_mac_entry->mac_addr[i]);
694 if (i != 5)
695 printf(":");
696 }
697 printf("\n");
698 current = current->next;
699 }
700 return;
701 }
702 #endif
703
704 #ifdef SNORT_RELOAD
ARPspoofReload(struct _SnortConfig * sc,char * args,void ** new_config)705 static void ARPspoofReload(struct _SnortConfig *sc, char *args, void **new_config)
706 {
707 tSfPolicyUserContextId arp_spoof_swap_config = (tSfPolicyUserContextId)*new_config;
708 int policy_id = (int)getParserPolicy(sc);
709 ArpSpoofConfig *pPolicyConfig;
710
711 if (!arp_spoof_swap_config)
712 {
713 arp_spoof_swap_config = sfPolicyConfigCreate();
714 *new_config = (void *)arp_spoof_swap_config;
715 }
716
717 sfPolicyUserPolicySet (arp_spoof_swap_config, policy_id);
718
719 pPolicyConfig = (ArpSpoofConfig *)sfPolicyUserDataGetCurrent(arp_spoof_swap_config);
720 if (pPolicyConfig)
721 {
722 FatalError("Arpspoof can only be configured once.\n");
723 }
724
725 pPolicyConfig = (ArpSpoofConfig *)SnortAlloc(sizeof(ArpSpoofConfig));
726 if (!pPolicyConfig)
727 {
728 ParseError("ARPSPOOF preprocessor: memory allocate failed.\n");
729 }
730 sfPolicyUserDataSetCurrent(arp_spoof_swap_config, pPolicyConfig);
731
732
733 /* Add arpspoof to the preprocessor function list */
734 AddFuncToPreprocList(sc, DetectARPattacks, PRIORITY_NETWORK, PP_ARPSPOOF, PROTO_BIT__ARP);
735
736 //policy independent configuration. First policy defines actual values.
737 if (policy_id != 0)
738 {
739 pPolicyConfig->check_unicast_arp = ((ArpSpoofConfig *)sfPolicyUserDataGetDefault(arp_spoof_swap_config))->check_unicast_arp;
740 return;
741 }
742
743 /* Parse the arpspoof arguments from snort.conf */
744 ParseARPspoofArgs(pPolicyConfig, args);
745
746 }
747
ARPspoofReloadHost(struct _SnortConfig * sc,char * args,void ** new_config)748 static void ARPspoofReloadHost(struct _SnortConfig *sc, char *args, void **new_config)
749 {
750 int policy_id = (int)getParserPolicy(sc);
751 ArpSpoofConfig *pPolicyConfig = NULL;
752 tSfPolicyUserContextId arp_spoof_swap_config;
753
754 arp_spoof_swap_config = (tSfPolicyUserContextId)GetRelatedReloadData(sc, "arpspoof");
755
756 if ((arp_spoof_swap_config == NULL) ||
757 (pPolicyConfig == NULL))
758 {
759 ParseError("Please activate arpspoof before trying to "
760 "use arpspoof_detect_host.");
761 }
762
763 sfPolicyUserPolicySet(arp_spoof_swap_config, policy_id);
764 pPolicyConfig = (ArpSpoofConfig *)sfPolicyUserDataGetCurrent(arp_spoof_swap_config);
765
766 DEBUG_WRAP(DebugMessage(DEBUG_INIT,
767 "Preprocessor: ARPspoof (overwrite list) Initialized\n"););
768
769 if (pPolicyConfig->ipmel == NULL)
770 {
771 pPolicyConfig->ipmel =
772 (IPMacEntryList *)SnortAlloc(sizeof(IPMacEntryList));
773 }
774
775 /* Add MAC/IP pairs to ipmel */
776 ParseARPspoofHostArgs(pPolicyConfig->ipmel, args);
777
778 if (pPolicyConfig->check_overwrite == 0)
779 pPolicyConfig->check_overwrite = 1;
780 }
781
ARPspoofReloadSwap(struct _SnortConfig * sc,void * swap_config)782 static void * ARPspoofReloadSwap(struct _SnortConfig *sc, void *swap_config)
783 {
784 tSfPolicyUserContextId arp_spoof_swap_config = (tSfPolicyUserContextId)swap_config;
785 tSfPolicyUserContextId old_config = arp_spoof_config;
786
787 if (arp_spoof_swap_config == NULL)
788 return NULL;
789
790 arp_spoof_config = arp_spoof_swap_config;
791 arp_spoof_swap_config = NULL;
792
793 return (void *)old_config;
794 }
795
ARPspoofReloadSwapFree(void * data)796 static void ARPspoofReloadSwapFree(void *data)
797 {
798 if (data == NULL)
799 return;
800
801 ArpSpoofFreeConfig((tSfPolicyUserContextId)data);
802 }
803 #endif
804