suricata
util-action.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-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  * \author Pablo Rincon <pablo.rincon.crespo@gmail.com>
22  */
23 
24 #include "suricata-common.h"
25 
26 #include "action-globals.h"
27 #include "conf.h"
28 #include "conf-yaml-loader.h"
29 
30 #include "detect.h"
31 #include "detect-engine.h"
32 #include "detect-engine-sigorder.h"
33 
34 #include "util-unittest.h"
35 #include "util-action.h"
36 #include "util-unittest-helper.h"
37 #include "util-debug.h"
38 
39 /* Default order: */
41 /* This order can be changed from config */
42 
43 /**
44  * \brief Return the priority associated to an action (to order sigs
45  * as specified at config)
46  * action_order_sigs has this priority by index val
47  * so action_order_sigs[0] has to be inspected first.
48  * This function is called from detect-engine-sigorder
49  * \param action can be one of ACTION_PASS, ACTION_DROP,
50  * ACTION_REJECT or ACTION_ALERT
51  * \retval uint8_t the priority (order of this actions)
52  */
53 uint8_t ActionOrderVal(uint8_t action)
54 {
55  /* reject_both and reject_dst have the same prio as reject */
56  if( (action & ACTION_REJECT) ||
57  (action & ACTION_REJECT_BOTH) ||
58  (action & ACTION_REJECT_DST)) {
59  action = ACTION_REJECT;
60  }
61  uint8_t i = 0;
62  for (; i < 4; i++) {
63  if (action_order_sigs[i] == action)
64  return i;
65  }
66  /* Unknown action, set just a low prio (high val) */
67  return 10;
68 }
69 
70 /**
71  * \brief Return the ACTION_* bit from their ascii value
72  * \param action can be one of "pass", "drop",
73  * "reject" or "alert"
74  * \retval uint8_t can be one of ACTION_PASS, ACTION_DROP,
75  * ACTION_REJECT or ACTION_ALERT
76  */
77 static uint8_t ActionAsciiToFlag(const char *action)
78 {
79  if (strcmp(action,"pass") == 0)
80  return ACTION_PASS;
81  if (strcmp(action,"drop") == 0)
82  return ACTION_DROP;
83  if (strcmp(action,"reject") == 0)
84  return ACTION_REJECT;
85  if (strcmp(action,"alert") == 0)
86  return ACTION_ALERT;
87 
88  return 0;
89 }
90 
91 /**
92  * \brief Load the action order from config. If none is provided,
93  * it will be default to ACTION_PASS, ACTION_DROP,
94  * ACTION_REJECT, ACTION_ALERT (pass has the highest prio)
95  *
96  * \retval 0 on success; -1 on fatal error;
97  */
99 {
100  uint8_t actions_used = 0;
101  uint8_t action_flag = 0;
102  uint8_t actions_config[4] = {0, 0, 0, 0};
103  int order = 0;
104 
105  ConfNode *action_order;
106  ConfNode *action = NULL;
107 
108  /* Let's load the order of actions from the general config */
109  action_order = ConfGetNode("action-order");
110  if (action_order == NULL) {
111  /* No configuration, use defaults. */
112  return 0;
113  }
114  else {
115  TAILQ_FOREACH(action, &action_order->head, next) {
116  SCLogDebug("Loading action order : %s", action->val);
117  action_flag = ActionAsciiToFlag(action->val);
118  if (action_flag == 0) {
119  SCLogError("action-order, invalid action: \"%s\". Please, use"
120  " \"pass\",\"drop\",\"alert\",\"reject\". You have"
121  " to specify all of them, without quotes and without"
122  " capital letters",
123  action->val);
124  goto error;
125  }
126 
127  if (actions_used & action_flag) {
128  SCLogError("action-order, action already set: \"%s\". Please,"
129  " use \"pass\",\"drop\",\"alert\",\"reject\". You"
130  " have to specify all of them, without quotes and"
131  " without capital letters",
132  action->val);
133  goto error;
134  }
135 
136  if (order >= 4) {
137  SCLogError("action-order, you have already specified all the "
138  "possible actions plus \"%s\". Please, use \"pass\","
139  "\"drop\",\"alert\",\"reject\". You have to specify"
140  " all of them, without quotes and without capital"
141  " letters",
142  action->val);
143  goto error;
144  }
145  actions_used |= action_flag;
146  actions_config[order++] = action_flag;
147  }
148  }
149  if (order < 4) {
150  SCLogError("action-order, the config didn't specify all of the "
151  "actions. Please, use \"pass\",\"drop\",\"alert\","
152  "\"reject\". You have to specify all of them, without"
153  " quotes and without capital letters");
154  goto error;
155  }
156 
157  /* Now, it's a valid config. Override the default preset */
158  for (order = 0; order < 4; order++) {
159  action_order_sigs[order] = actions_config[order];
160  }
161 
162  return 0;
163 
164  error:
165  return -1;
166 }
167 
168 #ifdef UNITTESTS
169 
170 /**
171  * \test Check that we invalidate duplicated actions
172  * (It should default to pass, drop, reject, alert)
173  */
174 static int UtilActionTest01(void)
175 {
176  char config[] = "\
177 %YAML 1.1\n\
178 ---\n\
179 action-order:\n\
180  - alert\n\
181  - drop\n\
182  - reject\n\
183  - alert\n";
184 
186  ConfInit();
187  ConfYamlLoadString(config, strlen(config));
188 
195 
196  /* Restore default values */
201  PASS;
202 }
203 
204 /**
205  * \test Check that we invalidate with unknown keywords
206  * (It should default to pass, drop, reject, alert)
207  */
208 static int UtilActionTest02(void)
209 {
210  char config[] = "\
211 %YAML 1.1\n\
212 ---\n\
213 action-order:\n\
214  - alert\n\
215  - drop\n\
216  - reject\n\
217  - ftw\n";
218 
220  ConfInit();
221  ConfYamlLoadString(config, strlen(config));
222 
229 
230  /* Restore default values */
235  PASS;
236 }
237 
238 /**
239  * \test Check that we invalidate if any action is missing
240  * (It should default to pass, drop, reject, alert)
241  */
242 static int UtilActionTest03(void)
243 {
244  char config[] = "\
245 %YAML 1.1\n\
246 ---\n\
247 action-order:\n\
248  - alert\n\
249  - drop\n\
250  - reject\n";
251 
253  ConfInit();
254  ConfYamlLoadString(config, strlen(config));
255 
262 
263  /* Restore default values */
268  PASS;
269 }
270 
271 /**
272  * \test Check that we invalidate if any action is missing
273  * (It should default to pass, drop, reject, alert)
274  */
275 static int UtilActionTest04(void)
276 {
277  char config[] = "\
278 %YAML 1.1\n\
279 ---\n\
280 action-order:\n";
281 
283  ConfInit();
284  ConfYamlLoadString(config, strlen(config));
285 
292 
293  /* Restore default values */
298  PASS;
299 }
300 
301 /**
302  * \test Check that we invalidate with unknown keywords
303  * and/or more than the expected
304  * (It should default to pass, drop, reject, alert)
305  */
306 static int UtilActionTest05(void)
307 {
308  char config[] = "\
309 %YAML 1.1\n\
310 ---\n\
311 action-order:\n\
312  - alert\n\
313  - drop\n\
314  - reject\n\
315  - pass\n\
316  - whatever\n";
317 
319  ConfInit();
320  ConfYamlLoadString(config, strlen(config));
321 
328 
329  /* Restore default values */
334  PASS;
335 }
336 
337 /**
338  * \test Check that we load a valid config
339  */
340 static int UtilActionTest06(void)
341 {
342  char config[] = "\
343 %YAML 1.1\n\
344 ---\n\
345 action-order:\n\
346  - alert\n\
347  - drop\n\
348  - reject\n\
349  - pass\n";
350 
352  ConfInit();
353  ConfYamlLoadString(config, strlen(config));
354 
361 
362  /* Restore default values */
367  PASS;
368 }
369 
370 /**
371  * \test Check that we load a valid config
372  */
373 static int UtilActionTest07(void)
374 {
375  char config[] = "\
376 %YAML 1.1\n\
377 ---\n\
378 action-order:\n\
379  - pass\n\
380  - alert\n\
381  - drop\n\
382  - reject\n";
383 
385  ConfInit();
386  ConfYamlLoadString(config, strlen(config));
387 
394 
395  /* Restore default values */
400  PASS;
401 }
402 
403 /**
404  * \test Check that the expected defaults are loaded if the
405  * action-order configuration is not present.
406  */
407 static int UtilActionTest08(void)
408 {
409  char config[] = "%YAML 1.1\n"
410  "---\n";
411 
413  ConfInit();
414  ConfYamlLoadString(config, strlen(config));
415 
421 
423  PASS;
424 }
425 
426 /* Register unittests */
428 {
429  /* Generic tests */
430  UtRegisterTest("UtilActionTest01", UtilActionTest01);
431  UtRegisterTest("UtilActionTest02", UtilActionTest02);
432  UtRegisterTest("UtilActionTest02", UtilActionTest02);
433  UtRegisterTest("UtilActionTest03", UtilActionTest03);
434  UtRegisterTest("UtilActionTest04", UtilActionTest04);
435  UtRegisterTest("UtilActionTest05", UtilActionTest05);
436  UtRegisterTest("UtilActionTest06", UtilActionTest06);
437  UtRegisterTest("UtilActionTest07", UtilActionTest07);
438  UtRegisterTest("UtilActionTest08", UtilActionTest08);
439 }
440 #endif
detect-engine.h
ConfNode_::val
char * val
Definition: conf.h:34
ACTION_PASS
#define ACTION_PASS
Definition: action-globals.h:34
ACTION_REJECT
#define ACTION_REJECT
Definition: action-globals.h:31
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
ActionInitConfig
int ActionInitConfig(void)
Load the action order from config. If none is provided, it will be default to ACTION_PASS,...
Definition: util-action.c:98
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
action-globals.h
ConfGetNode
ConfNode * ConfGetNode(const char *name)
Get a ConfNode by name.
Definition: conf.c:181
ActionOrderVal
uint8_t ActionOrderVal(uint8_t action)
Return the priority associated to an action (to order sigs as specified at config) action_order_sigs ...
Definition: util-action.c:53
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:252
action_order_sigs
uint8_t action_order_sigs[4]
Definition: util-action.c:40
util-unittest.h
util-unittest-helper.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
ACTION_REJECT_DST
#define ACTION_REJECT_DST
Definition: action-globals.h:32
util-debug.h
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
detect.h
ConfYamlLoadString
int ConfYamlLoadString(const char *string, size_t len)
Load configuration from a YAML string.
Definition: conf-yaml-loader.c:491
ACTION_ALERT
#define ACTION_ALERT
Definition: action-globals.h:29
conf-yaml-loader.h
conf.h
ConfCreateContextBackup
void ConfCreateContextBackup(void)
Creates a backup of the conf_hash hash_table used by the conf API.
Definition: conf.c:664
util-action.h
ACTION_REJECT_BOTH
#define ACTION_REJECT_BOTH
Definition: action-globals.h:33
suricata-common.h
ACTION_DROP
#define ACTION_DROP
Definition: action-globals.h:30
ConfRestoreContextBackup
void ConfRestoreContextBackup(void)
Restores the backup of the hash_table present in backup_conf_hash back to conf_hash.
Definition: conf.c:676
detect-engine-sigorder.h
ConfInit
void ConfInit(void)
Initialize the configuration system.
Definition: conf.c:120
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
ConfNode_
Definition: conf.h:32
UtilActionRegisterTests
void UtilActionRegisterTests(void)
Definition: util-action.c:427