suricata
util-exception-policy.c
Go to the documentation of this file.
1 /* Copyright (C) 2022 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  */
21 
22 #include "suricata-common.h"
23 #include "suricata.h"
24 #include "packet.h"
25 #include "util-exception-policy.h"
26 #include "util-misc.h"
27 #include "stream-tcp-reassemble.h"
28 #include "action-globals.h"
29 
31 /** true if exception policy was defined in config */
32 static bool g_eps_have_exception_policy = false;
33 
34 static const char *ExceptionPolicyEnumToString(enum ExceptionPolicy policy)
35 {
36  switch (policy) {
38  return "ignore";
40  return "reject";
42  return "bypass";
44  return "drop-flow";
46  return "drop-packet";
48  return "pass-packet";
50  return "pass-flow";
51  }
52  // TODO we shouldn't reach this, but if we do, better not to leave this as simply null...
53  return "not set";
54 }
55 
57 {
58  g_eps_master_switch = ExceptionPolicyParse("exception-policy", true);
59 }
60 
61 static enum ExceptionPolicy GetMasterExceptionPolicy(const char *option)
62 {
63  return g_eps_master_switch;
64 }
65 
66 void ExceptionPolicyApply(Packet *p, enum ExceptionPolicy policy, enum PacketDropReason drop_reason)
67 {
68  SCLogDebug("start: pcap_cnt %" PRIu64 ", policy %u", p->pcap_cnt, policy);
69  switch (policy) {
71  break;
73  SCLogDebug("EXCEPTION_POLICY_REJECT");
74  PacketDrop(p, ACTION_REJECT, drop_reason);
75  /* fall through */
77  SCLogDebug("EXCEPTION_POLICY_DROP_FLOW");
78  if (p->flow) {
80  FlowSetNoPayloadInspectionFlag(p->flow);
81  FlowSetNoPacketInspectionFlag(p->flow);
83  }
84  /* fall through */
86  SCLogDebug("EXCEPTION_POLICY_DROP_PACKET");
87  DecodeSetNoPayloadInspectionFlag(p);
88  DecodeSetNoPacketInspectionFlag(p);
89  PacketDrop(p, ACTION_DROP, drop_reason);
90  break;
93  /* fall through */
95  SCLogDebug("EXCEPTION_POLICY_PASS_FLOW");
96  if (p->flow) {
98  FlowSetNoPacketInspectionFlag(p->flow); // TODO util func
99  }
100  /* fall through */
102  SCLogDebug("EXCEPTION_POLICY_PASS_PACKET");
103  DecodeSetNoPayloadInspectionFlag(p);
104  DecodeSetNoPacketInspectionFlag(p);
105  break;
106  }
107  SCLogDebug("end");
108 }
109 
110 static enum ExceptionPolicy SetIPSOption(
111  const char *option, const char *value_str, enum ExceptionPolicy p)
112 {
113  if (!EngineModeIsIPS()) {
114  SCLogConfig("%s: %s not a valid config in IDS mode. Ignoring it.", option, value_str);
116  }
117  return p;
118 }
119 
120 static enum ExceptionPolicy PickPacketAction(const char *option, enum ExceptionPolicy p)
121 {
122  switch (p) {
124  SCLogWarning(
125  "flow actions not supported for %s, defaulting to \"drop-packet\"", option);
128  SCLogWarning(
129  "flow actions not supported for %s, defaulting to \"pass-packet\"", option);
132  SCLogWarning("flow actions not supported for %s, defaulting to \"ignore\"", option);
134  /* add all cases, to make sure new cases not handle will raise
135  * errors */
137  break;
139  break;
141  break;
143  break;
144  }
145  return p;
146 }
147 
148 enum ExceptionPolicy ExceptionPolicyParse(const char *option, const bool support_flow)
149 {
151  const char *value_str = NULL;
152  if ((ConfGet(option, &value_str)) == 1 && value_str != NULL) {
153  if (strcmp(value_str, "drop-flow") == 0) {
154  policy = SetIPSOption(option, value_str, EXCEPTION_POLICY_DROP_FLOW);
155  } else if (strcmp(value_str, "pass-flow") == 0) {
157  } else if (strcmp(value_str, "bypass") == 0) {
159  } else if (strcmp(value_str, "drop-packet") == 0) {
160  policy = SetIPSOption(option, value_str, EXCEPTION_POLICY_DROP_PACKET);
161  } else if (strcmp(value_str, "pass-packet") == 0) {
163  } else if (strcmp(value_str, "reject") == 0) {
164  policy = EXCEPTION_POLICY_REJECT;
165  } else if (strcmp(value_str, "ignore") == 0) { // TODO name?
166  policy = EXCEPTION_POLICY_NOT_SET;
167  } else if (strcmp(value_str, "auto") == 0) {
168  if (!EngineModeIsIPS()) {
169  policy = EXCEPTION_POLICY_NOT_SET;
170  } else {
172  }
173  } else {
175  "\"%s\" is not a valid exception policy value. Valid options are drop-flow, "
176  "pass-flow, bypass, drop-packet, pass-packet or ignore.",
177  value_str);
178  }
179 
180  if (!support_flow) {
181  policy = PickPacketAction(option, policy);
182  }
183 
184  if (strcmp(option, "exception-policy") == 0) {
185  g_eps_have_exception_policy = true;
186 
187  if (strcmp(value_str, "auto") == 0) {
188  SCLogConfig("%s: %s (because of 'auto' setting in %s-mode)", option,
189  ExceptionPolicyEnumToString(policy), EngineModeIsIPS() ? "IPS" : "IDS");
190  } else {
191  SCLogConfig("%s: %s", option, ExceptionPolicyEnumToString(policy));
192  }
193  } else {
194  SCLogConfig("%s: %s", option, ExceptionPolicyEnumToString(policy));
195  }
196 
197  } else if (strcmp(option, "exception-policy") == 0) {
198  /* not enabled, we won't change the master exception policy,
199  for now */
200  if (!EngineModeIsIPS()) {
201  policy = EXCEPTION_POLICY_NOT_SET;
202  } else {
204  }
205  SCLogConfig("%s: %s (%s-mode)", option, ExceptionPolicyEnumToString(policy),
206  EngineModeIsIPS() ? "IPS" : "IDS");
207 
208  } else {
209  /* Exception Policy was not defined individually */
210  policy = GetMasterExceptionPolicy(option);
211  if (g_eps_have_exception_policy) {
212  SCLogConfig("%s: %s (defined via 'exception-policy' master switch)", option,
213  ExceptionPolicyEnumToString(policy));
214  } else {
215  SCLogConfig("%s: %s (defined via 'built-in default' for %s-mode)", option,
216  ExceptionPolicyEnumToString(policy), EngineModeIsIPS() ? "IPS" : "IDS");
217  }
218  }
219 
220  return policy;
221 }
222 
223 #ifndef DEBUG
224 
225 int ExceptionSimulationCommandlineParser(const char *name, const char *arg)
226 {
227  return 0;
228 }
229 
230 #else
231 
232 /* exception policy simulation (eps) handling */
233 
234 uint64_t g_eps_applayer_error_offset_ts = UINT64_MAX;
235 uint64_t g_eps_applayer_error_offset_tc = UINT64_MAX;
236 uint64_t g_eps_pcap_packet_loss = UINT64_MAX;
237 uint64_t g_eps_stream_ssn_memcap = UINT64_MAX;
238 uint64_t g_eps_stream_reassembly_memcap = UINT64_MAX;
239 uint64_t g_eps_flow_memcap = UINT64_MAX;
240 uint64_t g_eps_defrag_memcap = UINT64_MAX;
241 bool g_eps_is_alert_queue_fail_mode = false;
242 
243 /* 1: parsed, 0: not for us, -1: error */
244 int ExceptionSimulationCommandlineParser(const char *name, const char *arg)
245 {
246  if (strcmp(name, "simulate-applayer-error-at-offset-ts") == 0) {
247  BUG_ON(arg == NULL);
248  uint64_t offset = 0;
249  if (ParseSizeStringU64(arg, &offset) < 0) {
250  return -1;
251  }
252  g_eps_applayer_error_offset_ts = offset;
253  } else if (strcmp(name, "simulate-applayer-error-at-offset-tc") == 0) {
254  BUG_ON(arg == NULL);
255  uint64_t offset = 0;
256  if (ParseSizeStringU64(arg, &offset) < 0) {
257  return TM_ECODE_FAILED;
258  }
259  g_eps_applayer_error_offset_tc = offset;
260  } else if (strcmp(name, "simulate-packet-loss") == 0) {
261  BUG_ON(arg == NULL);
262  uint64_t pkt_num = 0;
263  if (ParseSizeStringU64(arg, &pkt_num) < 0) {
264  return TM_ECODE_FAILED;
265  }
266  g_eps_pcap_packet_loss = pkt_num;
267  } else if (strcmp(name, "simulate-packet-tcp-reassembly-memcap") == 0) {
268  BUG_ON(arg == NULL);
269  uint64_t pkt_num = 0;
270  if (ParseSizeStringU64(arg, &pkt_num) < 0) {
271  return TM_ECODE_FAILED;
272  }
273  g_eps_stream_reassembly_memcap = pkt_num;
274  } else if (strcmp(name, "simulate-packet-tcp-ssn-memcap") == 0) {
275  BUG_ON(arg == NULL);
276  uint64_t pkt_num = 0;
277  if (ParseSizeStringU64(arg, &pkt_num) < 0) {
278  return TM_ECODE_FAILED;
279  }
280  g_eps_stream_ssn_memcap = pkt_num;
281  } else if (strcmp(name, "simulate-packet-flow-memcap") == 0) {
282  BUG_ON(arg == NULL);
283  uint64_t pkt_num = 0;
284  if (ParseSizeStringU64(arg, &pkt_num) < 0) {
285  return TM_ECODE_FAILED;
286  }
287  g_eps_flow_memcap = pkt_num;
288  } else if (strcmp(name, "simulate-packet-defrag-memcap") == 0) {
289  BUG_ON(arg == NULL);
290  uint64_t pkt_num = 0;
291  if (ParseSizeStringU64(arg, &pkt_num) < 0) {
292  return TM_ECODE_FAILED;
293  }
294  g_eps_defrag_memcap = pkt_num;
295  } else if (strcmp(name, "simulate-alert-queue-realloc-failure") == 0) {
296  g_eps_is_alert_queue_fail_mode = true;
297  } else {
298  // not for us
299  return 0;
300  }
301  return 1;
302 }
303 #endif
ExceptionPolicyApply
void ExceptionPolicyApply(Packet *p, enum ExceptionPolicy policy, enum PacketDropReason drop_reason)
Definition: util-exception-policy.c:66
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
PacketBypassCallback
void PacketBypassCallback(Packet *p)
Definition: decode.c:444
g_eps_master_switch
enum ExceptionPolicy g_eps_master_switch
Definition: util-exception-policy.c:30
ACTION_REJECT
#define ACTION_REJECT
Definition: action-globals.h:31
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
Packet_::pcap_cnt
uint64_t pcap_cnt
Definition: decode.h:594
ParseSizeStringU64
int ParseSizeStringU64(const char *size, uint64_t *res)
Definition: util-misc.c:198
action-globals.h
EXCEPTION_POLICY_DROP_PACKET
@ EXCEPTION_POLICY_DROP_PACKET
Definition: util-exception-policy.h:32
stream-tcp-reassemble.h
FLOW_ACTION_DROP
#define FLOW_ACTION_DROP
Definition: flow.h:67
ExceptionSimulationCommandlineParser
int ExceptionSimulationCommandlineParser(const char *name, const char *arg)
Definition: util-exception-policy.c:225
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:85
PacketDropReason
PacketDropReason
Definition: decode.h:390
ConfGet
int ConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:335
FLOW_ACTION_PASS
#define FLOW_ACTION_PASS
Definition: flow.h:114
util-exception-policy.h
EXCEPTION_POLICY_REJECT
@ EXCEPTION_POLICY_REJECT
Definition: util-exception-policy.h:34
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:249
EXCEPTION_POLICY_PASS_PACKET
@ EXCEPTION_POLICY_PASS_PACKET
Definition: util-exception-policy.h:29
EXCEPTION_POLICY_DROP_FLOW
@ EXCEPTION_POLICY_DROP_FLOW
Definition: util-exception-policy.h:33
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:289
ExceptionPolicy
ExceptionPolicy
Definition: util-exception-policy.h:27
Packet_
Definition: decode.h:428
Packet_::flow
struct Flow_ * flow
Definition: decode.h:465
ExceptionPolicyParse
enum ExceptionPolicy ExceptionPolicyParse(const char *option, const bool support_flow)
Definition: util-exception-policy.c:148
StreamTcpDisableAppLayer
void StreamTcpDisableAppLayer(Flow *f)
Definition: stream-tcp-reassemble.c:445
suricata-common.h
FatalErrorOnInit
#define FatalErrorOnInit(...)
Fatal error IF we're starting up, and configured to consider errors to be fatal errors.
Definition: util-debug.h:511
packet.h
ACTION_DROP
#define ACTION_DROP
Definition: action-globals.h:30
EXCEPTION_POLICY_BYPASS_FLOW
@ EXCEPTION_POLICY_BYPASS_FLOW
Definition: util-exception-policy.h:31
SCLogConfig
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
EXCEPTION_POLICY_PASS_FLOW
@ EXCEPTION_POLICY_PASS_FLOW
Definition: util-exception-policy.h:30
Flow_::flags
uint32_t flags
Definition: flow.h:427
PacketDrop
void PacketDrop(Packet *p, const uint8_t action, enum PacketDropReason r)
issue drop action
Definition: packet.c:32
EngineModeIsIPS
int EngineModeIsIPS(void)
Definition: suricata.c:211
suricata.h
SetMasterExceptionPolicy
void SetMasterExceptionPolicy(void)
Definition: util-exception-policy.c:56
util-misc.h
EXCEPTION_POLICY_NOT_SET
@ EXCEPTION_POLICY_NOT_SET
Definition: util-exception-policy.h:28