1 //--------------------------------------------------------------------------
2 // Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
3 //
4 // This program is free software; you can redistribute it and/or modify it
5 // under the terms of the GNU General Public License Version 2 as published
6 // by the Free Software Foundation.  You may not use, modify or distribute
7 // this program under any other version of the GNU General Public License.
8 //
9 // This program is distributed in the hope that it will be useful, but
10 // WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License along
15 // with this program; if not, write to the Free Software Foundation, Inc.,
16 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 //--------------------------------------------------------------------------
18 
19 // arp_module.cc author Russ Combs <rucombs@cisco.com>
20 
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 
25 #include "arp_module.h"
26 
27 using namespace snort;
28 
29 #define ARPSPOOF_UNICAST_ARP_REQUEST_STR \
30     "unicast ARP request"
31 #define ARPSPOOF_ETHERFRAME_ARP_MISMATCH_SRC_STR \
32     "ethernet/ARP mismatch for source hardware address"
33 #define ARPSPOOF_ETHERFRAME_ARP_MISMATCH_DST_STR \
34     "ethernet/ARP mismatch for destination hardware address in reply"
35 #define ARPSPOOF_ARP_CACHE_OVERWRITE_ATTACK_STR \
36     "attempted ARP cache overwrite attack"
37 
38 THREAD_LOCAL SimpleStats asstats;
39 
40 //-------------------------------------------------------------------------
41 // arp_spoof stuff
42 //-------------------------------------------------------------------------
43 
44 static const Parameter arp_spoof_hosts_params[] =
45 {
46     { "ip", Parameter::PT_IP4, nullptr, nullptr,
47       "host ip address" },
48 
49     { "mac", Parameter::PT_MAC, nullptr, nullptr,
50       "host mac address" },
51 
52     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
53 };
54 
55 static const Parameter s_params[] =
56 {
57     { "hosts", Parameter::PT_LIST, arp_spoof_hosts_params, nullptr,
58       "configure ARP cache overwrite attacks" },
59 
60     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
61 };
62 
63 static const RuleMap s_rules[] =
64 {
65     { ARPSPOOF_UNICAST_ARP_REQUEST, ARPSPOOF_UNICAST_ARP_REQUEST_STR },
66     { ARPSPOOF_ETHERFRAME_ARP_MISMATCH_SRC, ARPSPOOF_ETHERFRAME_ARP_MISMATCH_SRC_STR },
67     { ARPSPOOF_ETHERFRAME_ARP_MISMATCH_DST, ARPSPOOF_ETHERFRAME_ARP_MISMATCH_DST_STR },
68     { ARPSPOOF_ARP_CACHE_OVERWRITE_ATTACK, ARPSPOOF_ARP_CACHE_OVERWRITE_ATTACK_STR },
69 
70     { 0, nullptr }
71 };
72 
73 //-------------------------------------------------------------------------
74 // arp_spoof module
75 //-------------------------------------------------------------------------
76 
ArpSpoofModule()77 ArpSpoofModule::ArpSpoofModule() :
78     Module(MOD_NAME, MOD_HELP, s_params)
79 {
80     config = nullptr;
81 }
82 
~ArpSpoofModule()83 ArpSpoofModule::~ArpSpoofModule()
84 {
85     if ( config )
86         delete config;
87 }
88 
get_rules() const89 const RuleMap* ArpSpoofModule::get_rules() const
90 { return s_rules; }
91 
get_profile() const92 ProfileStats* ArpSpoofModule::get_profile() const
93 { return &arpPerfStats; }
94 
set(const char *,Value & v,SnortConfig *)95 bool ArpSpoofModule::set(const char*, Value& v, SnortConfig*)
96 {
97     if ( v.is("ip") )
98         host.ipv4_addr = v.get_ip4();
99 
100     else if ( v.is("mac") )
101         v.get_mac(host.mac_addr);
102 
103     return true;
104 }
105 
get_config()106 ArpSpoofConfig* ArpSpoofModule::get_config()
107 {
108     ArpSpoofConfig* temp = config;
109     config = nullptr;
110     return temp;
111 }
112 
begin(const char *,int,SnortConfig *)113 bool ArpSpoofModule::begin(const char*, int, SnortConfig*)
114 {
115     if ( !config )
116     {
117         config = new ArpSpoofConfig;
118         config->check_overwrite = false;
119     }
120     memset(&host, 0, sizeof(host));
121     return true;
122 }
123 
end(const char *,int idx,SnortConfig *)124 bool ArpSpoofModule::end(const char*, int idx, SnortConfig*)
125 {
126     if ( idx )
127         config->ipmel.emplace_back(host);
128     else
129         config->check_overwrite = !config->ipmel.empty();
130 
131     return true;
132 }
133 
get_pegs() const134 const PegInfo* ArpSpoofModule::get_pegs() const
135 { return simple_pegs; }
136 
get_counts() const137 PegCount* ArpSpoofModule::get_counts() const
138 { return (PegCount*)&asstats; }
139 
140