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 // data_bus.h author Russ Combs <rucombs@cisco.com>
19 
20 #ifndef DATA_BUS_H
21 #define DATA_BUS_H
22 
23 // DataEvents are the product of inspection, not detection.  They can be
24 // used to implement flexible processing w/o hardcoding the logic to call
25 // specific functions under specific conditions.  By using DataEvents with
26 // a publish-subscribe mechanism, it is possible to add custom processing
27 // at arbitrary points, eg when service is identified, or when a URI is
28 // available, or when a flow clears.
29 
30 #include <string>
31 #include <unordered_map>
32 #include <unordered_set>
33 #include <vector>
34 
35 #include "main/snort_types.h"
36 
37 namespace snort
38 {
39 class Flow;
40 struct Packet;
41 
42 class DataEvent
43 {
44 public:
45     virtual ~DataEvent() = default;
46 
get_packet()47     virtual const Packet* get_packet()
48     { return nullptr; }
49 
get_data()50     virtual const uint8_t* get_data()
51     { return nullptr; }
52 
get_data(unsigned & len)53     virtual const uint8_t* get_data(unsigned& len)
54     { len = 0; return nullptr; }
55 
get_normalized_data(unsigned & len)56     virtual const uint8_t* get_normalized_data(unsigned& len)
57     { return get_data(len); }
58 
59 protected:
60     DataEvent() = default;
61 };
62 
63 class BareDataEvent final : public DataEvent
64 {
65 public:
66     BareDataEvent() = default;
67     ~BareDataEvent() override = default;
68 };
69 
70 class DataHandler
71 {
72 public:
73     virtual ~DataHandler() = default;
74 
handle(DataEvent &,Flow *)75     virtual void handle(DataEvent&, Flow*) { }
76     const char* module_name;
77     bool cloned;
78 
79     // order is desired position in the call sequence of handlers: 1 = first, 0 = last
80     // the sequence among subscribers with the same order is not specified
81     unsigned order = 0;
82 
83 protected:
84     DataHandler(std::nullptr_t) = delete;
DataHandler(const char * mod_name)85     DataHandler(const char* mod_name) : module_name(mod_name), cloned(false) { }
86 };
87 
88 // FIXIT-P evaluate perf; focus is on correctness
89 typedef std::vector<DataHandler*> DataList;
90 typedef std::unordered_map<std::string, DataList> DataMap;
91 
92 class SO_PUBLIC DataBus
93 {
94 public:
95     DataBus();
96     ~DataBus();
97 
98     // configure time methods - main thread only
99     void clone(DataBus& from, const char* exclude_name = nullptr);
100 
101     // FIXIT-L ideally these would not be static or would take an inspection policy*
102     static void subscribe(const char* key, DataHandler*);
103     static void subscribe_network(const char* key, DataHandler*);
104 
105     // FIXIT-L these should be called during cleanup
106     static void unsubscribe(const char* key, DataHandler*);
107     static void unsubscribe_network(const char* key, DataHandler*);
108 
109     // runtime methods
110     static void publish(const char* key, DataEvent&, Flow* = nullptr);
111 
112     // convenience methods
113     static void publish(const char* key, const uint8_t*, unsigned, Flow* = nullptr);
114     static void publish(const char* key, Packet*, Flow* = nullptr);
115 
116 private:
117     void _subscribe(const char* key, DataHandler*);
118     void _unsubscribe(const char* key, DataHandler*);
119     void _publish(const char* key, DataEvent&, Flow*);
120 
121 private:
122     DataMap map;
123 };
124 }
125 
126 //
127 // Common core functionality data events
128 //
129 
130 #define PACKET_EVENT "detection.packet"
131 #define FLOW_STATE_EVENT "flow.state_change"
132 #define THREAD_IDLE_EVENT "thread.idle"
133 #define THREAD_ROTATE_EVENT "thread.rotate"
134 
135 // A packet is being detained.
136 #define DETAINED_PACKET_EVENT "analyzer.detained.packet"
137 
138 // A flow changed its service
139 #define FLOW_SERVICE_CHANGE_EVENT "flow.service_change_event"
140 // A flow has found the service inspector
141 #define SERVICE_INSPECTOR_CHANGE_EVENT "flow.service_inspector.changed"
142 // No service has been found for the flow
143 #define FLOW_NO_SERVICE_EVENT "flow.no_service_event"
144 // search of SSL is abandoned on this flow
145 #define SSL_SEARCH_ABANDONED "flow.ssl_search_abandoned"
146 
147 // A flow has entered the setup state
148 #define FLOW_STATE_SETUP_EVENT "flow.state_setup"
149 
150 // A new flow is created on this packet
151 #define STREAM_ICMP_NEW_FLOW_EVENT "stream.icmp_new_flow"
152 #define STREAM_IP_NEW_FLOW_EVENT "stream.ip_new_flow"
153 #define STREAM_UDP_NEW_FLOW_EVENT "stream.udp_new_flow"
154 
155 // A flow has been determined to be bidirectional
156 #define STREAM_ICMP_BIDIRECTIONAL_EVENT "stream.icmp_bidirectional"
157 #define STREAM_IP_BIDIRECTIONAL_EVENT "stream.ip.bidirectional"
158 #define STREAM_UDP_BIDIRECTIONAL_EVENT "stream.udp.bidirectional"
159 
160 // A TCP flow has the flag; a midstream flow may not publish other events
161 #define STREAM_TCP_SYN_EVENT "stream.tcp_syn"
162 #define STREAM_TCP_SYN_ACK_EVENT "stream.tcp_syn_ack"
163 #define STREAM_TCP_MIDSTREAM_EVENT "stream.tcp_midstream"
164 
165 // A new standby flow was generated by stream high availability
166 #define STREAM_HA_NEW_FLOW_EVENT "stream.ha.new_flow"
167 
168 #endif
169 
170