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(SC_ERR_ACTION_ORDER, "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", action->val);
123  goto error;
124  }
125 
126  if (actions_used & action_flag) {
127  SCLogError(SC_ERR_ACTION_ORDER, "action-order, action already set: \"%s\". Please,"
128  " use \"pass\",\"drop\",\"alert\",\"reject\". You"
129  " have to specify all of them, without quotes and"
130  " without capital letters", action->val);
131  goto error;
132  }
133 
134  if (order >= 4) {
135  SCLogError(SC_ERR_ACTION_ORDER, "action-order, you have already specified all the "
136  "possible actions plus \"%s\". Please, use \"pass\","
137  "\"drop\",\"alert\",\"reject\". You have to specify"
138  " all of them, without quotes and without capital"
139  " letters", action->val);
140  goto error;
141  }
142  actions_used |= action_flag;
143  actions_config[order++] = action_flag;
144  }
145  }
146  if (order < 4) {
147  SCLogError(SC_ERR_ACTION_ORDER, "action-order, the config didn't specify all of the "
148  "actions. Please, use \"pass\",\"drop\",\"alert\","
149  "\"reject\". You have to specify all of them, without"
150  " quotes and without capital letters");
151  goto error;
152  }
153 
154  /* Now, it's a valid config. Override the default preset */
155  for (order = 0; order < 4; order++) {
156  action_order_sigs[order] = actions_config[order];
157  }
158 
159  return 0;
160 
161  error:
162  return -1;
163 }
164 
165 #ifdef UNITTESTS
166 
167 /**
168  * \test Check that we invalidate duplicated actions
169  * (It should default to pass, drop, reject, alert)
170  */
171 static int UtilActionTest01(void)
172 {
173  char config[] = "\
174 %YAML 1.1\n\
175 ---\n\
176 action-order:\n\
177  - alert\n\
178  - drop\n\
179  - reject\n\
180  - alert\n";
181 
183  ConfInit();
184  ConfYamlLoadString(config, strlen(config));
185 
192 
193  /* Restore default values */
198  PASS;
199 }
200 
201 /**
202  * \test Check that we invalidate with unknown keywords
203  * (It should default to pass, drop, reject, alert)
204  */
205 static int UtilActionTest02(void)
206 {
207  char config[] = "\
208 %YAML 1.1\n\
209 ---\n\
210 action-order:\n\
211  - alert\n\
212  - drop\n\
213  - reject\n\
214  - ftw\n";
215 
217  ConfInit();
218  ConfYamlLoadString(config, strlen(config));
219 
226 
227  /* Restore default values */
232  PASS;
233 }
234 
235 /**
236  * \test Check that we invalidate if any action is missing
237  * (It should default to pass, drop, reject, alert)
238  */
239 static int UtilActionTest03(void)
240 {
241  char config[] = "\
242 %YAML 1.1\n\
243 ---\n\
244 action-order:\n\
245  - alert\n\
246  - drop\n\
247  - reject\n";
248 
250  ConfInit();
251  ConfYamlLoadString(config, strlen(config));
252 
259 
260  /* Restore default values */
265  PASS;
266 }
267 
268 /**
269  * \test Check that we invalidate if any action is missing
270  * (It should default to pass, drop, reject, alert)
271  */
272 static int UtilActionTest04(void)
273 {
274  char config[] = "\
275 %YAML 1.1\n\
276 ---\n\
277 action-order:\n";
278 
280  ConfInit();
281  ConfYamlLoadString(config, strlen(config));
282 
289 
290  /* Restore default values */
295  PASS;
296 }
297 
298 /**
299  * \test Check that we invalidate with unknown keywords
300  * and/or more than the expected
301  * (It should default to pass, drop, reject, alert)
302  */
303 static int UtilActionTest05(void)
304 {
305  char config[] = "\
306 %YAML 1.1\n\
307 ---\n\
308 action-order:\n\
309  - alert\n\
310  - drop\n\
311  - reject\n\
312  - pass\n\
313  - whatever\n";
314 
316  ConfInit();
317  ConfYamlLoadString(config, strlen(config));
318 
325 
326  /* Restore default values */
331  PASS;
332 }
333 
334 /**
335  * \test Check that we load a valid config
336  */
337 static int UtilActionTest06(void)
338 {
339  char config[] = "\
340 %YAML 1.1\n\
341 ---\n\
342 action-order:\n\
343  - alert\n\
344  - drop\n\
345  - reject\n\
346  - pass\n";
347 
349  ConfInit();
350  ConfYamlLoadString(config, strlen(config));
351 
358 
359  /* Restore default values */
364  PASS;
365 }
366 
367 /**
368  * \test Check that we load a valid config
369  */
370 static int UtilActionTest07(void)
371 {
372  char config[] = "\
373 %YAML 1.1\n\
374 ---\n\
375 action-order:\n\
376  - pass\n\
377  - alert\n\
378  - drop\n\
379  - reject\n";
380 
382  ConfInit();
383  ConfYamlLoadString(config, strlen(config));
384 
391 
392  /* Restore default values */
397  PASS;
398 }
399 
400 /**
401  * \test Check that the expected defaults are loaded if the
402  * action-order configuration is not present.
403  */
404 static int UtilActionTest08(void)
405 {
406  char config[] = "%YAML 1.1\n"
407  "---\n";
408 
410  ConfInit();
411  ConfYamlLoadString(config, strlen(config));
412 
418 
420  PASS;
421 }
422 
423 /* Register unittests */
425 {
426  /* Generic tests */
427  UtRegisterTest("UtilActionTest01", UtilActionTest01);
428  UtRegisterTest("UtilActionTest02", UtilActionTest02);
429  UtRegisterTest("UtilActionTest02", UtilActionTest02);
430  UtRegisterTest("UtilActionTest03", UtilActionTest03);
431  UtRegisterTest("UtilActionTest04", UtilActionTest04);
432  UtRegisterTest("UtilActionTest05", UtilActionTest05);
433  UtRegisterTest("UtilActionTest06", UtilActionTest06);
434  UtRegisterTest("UtilActionTest07", UtilActionTest07);
435  UtRegisterTest("UtilActionTest08", UtilActionTest08);
436 }
437 #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
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:296
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:175
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:487
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:654
util-action.h
ACTION_REJECT_BOTH
#define ACTION_REJECT_BOTH
Definition: action-globals.h:33
SC_ERR_ACTION_ORDER
@ SC_ERR_ACTION_ORDER
Definition: util-error.h:33
suricata-common.h
ACTION_DROP
#define ACTION_DROP
Definition: action-globals.h:30
SCLogError
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:255
ConfRestoreContextBackup
void ConfRestoreContextBackup(void)
Restores the backup of the hash_table present in backup_conf_hash back to conf_hash.
Definition: conf.c:666
detect-engine-sigorder.h
ConfInit
void ConfInit(void)
Initialize the configuration system.
Definition: conf.c:113
ConfNode_
Definition: conf.h:32
ActionInitConfig
int ActionInitConfig()
Load the action order from config. If none is provided, it will be default to ACTION_PASS,...
Definition: util-action.c:98
UtilActionRegisterTests
void UtilActionRegisterTests(void)
Definition: util-action.c:424