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_ANY) {
57  action = ACTION_REJECT;
58  } else if (action & ACTION_DROP) {
59  action = ACTION_DROP;
60  } else if (action & ACTION_PASS) {
61  action = ACTION_PASS;
62  } else if (action & ACTION_ALERT) {
63  action = ACTION_ALERT;
64  } else if (action == 0) {
65  action = ACTION_ALERT;
66  }
67 
68  for (uint8_t i = 0; i < 4; i++) {
69  if (action_order_sigs[i] == action) {
70  return i;
71  }
72  }
73  /* Unknown action, set just a low prio (high val) */
74  return 10;
75 }
76 
77 /**
78  * \brief Return the ACTION_* bit from their ascii value
79  * \param action can be one of "pass", "drop",
80  * "reject" or "alert"
81  * \retval uint8_t can be one of ACTION_PASS, ACTION_DROP,
82  * ACTION_REJECT or ACTION_ALERT
83  */
84 static uint8_t ActionAsciiToFlag(const char *action)
85 {
86  if (strcmp(action,"pass") == 0)
87  return ACTION_PASS;
88  if (strcmp(action,"drop") == 0)
89  return ACTION_DROP;
90  if (strcmp(action,"reject") == 0)
91  return ACTION_REJECT;
92  if (strcmp(action,"alert") == 0)
93  return ACTION_ALERT;
94 
95  return 0;
96 }
97 
98 /**
99  * \brief Load the action order from config. If none is provided,
100  * it will be default to ACTION_PASS, ACTION_DROP,
101  * ACTION_REJECT, ACTION_ALERT (pass has the highest prio)
102  *
103  * \retval 0 on success; -1 on fatal error;
104  */
106 {
107  uint8_t actions_used = 0;
108  uint8_t action_flag = 0;
109  uint8_t actions_config[4] = {0, 0, 0, 0};
110  int order = 0;
111 
112  SCConfNode *action_order;
113  SCConfNode *action = NULL;
114 
115  /* Let's load the order of actions from the general config */
116  action_order = SCConfGetNode("action-order");
117  if (action_order == NULL) {
118  /* No configuration, use defaults. */
119  return 0;
120  }
121  else {
122  TAILQ_FOREACH(action, &action_order->head, next) {
123  SCLogDebug("Loading action order : %s", action->val);
124  action_flag = ActionAsciiToFlag(action->val);
125  if (action_flag == 0) {
126  SCLogError("action-order, invalid action: \"%s\". Please, use"
127  " \"pass\",\"drop\",\"alert\",\"reject\". You have"
128  " to specify all of them, without quotes and without"
129  " capital letters",
130  action->val);
131  goto error;
132  }
133 
134  if (actions_used & action_flag) {
135  SCLogError("action-order, action already set: \"%s\". Please,"
136  " use \"pass\",\"drop\",\"alert\",\"reject\". You"
137  " have to specify all of them, without quotes and"
138  " without capital letters",
139  action->val);
140  goto error;
141  }
142 
143  if (order >= 4) {
144  SCLogError("action-order, you have already specified all the "
145  "possible actions plus \"%s\". Please, use \"pass\","
146  "\"drop\",\"alert\",\"reject\". You have to specify"
147  " all of them, without quotes and without capital"
148  " letters",
149  action->val);
150  goto error;
151  }
152  actions_used |= action_flag;
153  actions_config[order++] = action_flag;
154  }
155  }
156  if (order < 4) {
157  SCLogError("action-order, the config didn't specify all of the "
158  "actions. Please, use \"pass\",\"drop\",\"alert\","
159  "\"reject\". You have to specify all of them, without"
160  " quotes and without capital letters");
161  goto error;
162  }
163 
164  /* Now, it's a valid config. Override the default preset */
165  for (order = 0; order < 4; order++) {
166  action_order_sigs[order] = actions_config[order];
167  }
168 
169  return 0;
170 
171  error:
172  return -1;
173 }
174 
175 #ifdef UNITTESTS
176 
177 /**
178  * \test Check that we invalidate duplicated actions
179  * (It should default to pass, drop, reject, alert)
180  */
181 static int UtilActionTest01(void)
182 {
183  char config[] = "\
184 %YAML 1.1\n\
185 ---\n\
186 action-order:\n\
187  - alert\n\
188  - drop\n\
189  - reject\n\
190  - alert\n";
191 
193  SCConfInit();
194  SCConfYamlLoadString(config, strlen(config));
195 
201 
202  SCConfDeInit();
204 
205  /* Restore default values */
210  PASS;
211 }
212 
213 /**
214  * \test Check that we invalidate with unknown keywords
215  * (It should default to pass, drop, reject, alert)
216  */
217 static int UtilActionTest02(void)
218 {
219  char config[] = "\
220 %YAML 1.1\n\
221 ---\n\
222 action-order:\n\
223  - alert\n\
224  - drop\n\
225  - reject\n\
226  - ftw\n";
227 
229  SCConfInit();
230  SCConfYamlLoadString(config, strlen(config));
231 
237  SCConfDeInit();
239 
240  /* Restore default values */
245  PASS;
246 }
247 
248 /**
249  * \test Check that we invalidate if any action is missing
250  * (It should default to pass, drop, reject, alert)
251  */
252 static int UtilActionTest03(void)
253 {
254  char config[] = "\
255 %YAML 1.1\n\
256 ---\n\
257 action-order:\n\
258  - alert\n\
259  - drop\n\
260  - reject\n";
261 
263  SCConfInit();
264  SCConfYamlLoadString(config, strlen(config));
265 
271  SCConfDeInit();
273 
274  /* Restore default values */
279  PASS;
280 }
281 
282 /**
283  * \test Check that we invalidate if any action is missing
284  * (It should default to pass, drop, reject, alert)
285  */
286 static int UtilActionTest04(void)
287 {
288  char config[] = "\
289 %YAML 1.1\n\
290 ---\n\
291 action-order:\n";
292 
294  SCConfInit();
295  SCConfYamlLoadString(config, strlen(config));
296 
302  SCConfDeInit();
304 
305  /* Restore default values */
310  PASS;
311 }
312 
313 /**
314  * \test Check that we invalidate with unknown keywords
315  * and/or more than the expected
316  * (It should default to pass, drop, reject, alert)
317  */
318 static int UtilActionTest05(void)
319 {
320  char config[] = "\
321 %YAML 1.1\n\
322 ---\n\
323 action-order:\n\
324  - alert\n\
325  - drop\n\
326  - reject\n\
327  - pass\n\
328  - whatever\n";
329 
331  SCConfInit();
332  SCConfYamlLoadString(config, strlen(config));
333 
339  SCConfDeInit();
341 
342  /* Restore default values */
347  PASS;
348 }
349 
350 /**
351  * \test Check that we load a valid config
352  */
353 static int UtilActionTest06(void)
354 {
355  char config[] = "\
356 %YAML 1.1\n\
357 ---\n\
358 action-order:\n\
359  - alert\n\
360  - drop\n\
361  - reject\n\
362  - pass\n";
363 
365  SCConfInit();
366  SCConfYamlLoadString(config, strlen(config));
367 
373  SCConfDeInit();
375 
376  /* Restore default values */
381  PASS;
382 }
383 
384 /**
385  * \test Check that we load a valid config
386  */
387 static int UtilActionTest07(void)
388 {
389  char config[] = "\
390 %YAML 1.1\n\
391 ---\n\
392 action-order:\n\
393  - pass\n\
394  - alert\n\
395  - drop\n\
396  - reject\n";
397 
399  SCConfInit();
400  SCConfYamlLoadString(config, strlen(config));
401 
407  SCConfDeInit();
409 
410  /* Restore default values */
415  PASS;
416 }
417 
418 /**
419  * \test Check that the expected defaults are loaded if the
420  * action-order configuration is not present.
421  */
422 static int UtilActionTest08(void)
423 {
424  char config[] = "%YAML 1.1\n"
425  "---\n";
426 
428  SCConfInit();
429  SCConfYamlLoadString(config, strlen(config));
430 
436 
437  SCConfDeInit();
439  PASS;
440 }
441 
442 /* Register unittests */
444 {
445  /* Generic tests */
446  UtRegisterTest("UtilActionTest01", UtilActionTest01);
447  UtRegisterTest("UtilActionTest02", UtilActionTest02);
448  UtRegisterTest("UtilActionTest02", UtilActionTest02);
449  UtRegisterTest("UtilActionTest03", UtilActionTest03);
450  UtRegisterTest("UtilActionTest04", UtilActionTest04);
451  UtRegisterTest("UtilActionTest05", UtilActionTest05);
452  UtRegisterTest("UtilActionTest06", UtilActionTest06);
453  UtRegisterTest("UtilActionTest07", UtilActionTest07);
454  UtRegisterTest("UtilActionTest08", UtilActionTest08);
455 }
456 #endif
SCConfYamlLoadString
int SCConfYamlLoadString(const char *string, size_t len)
Load configuration from a YAML string.
Definition: conf-yaml-loader.c:523
detect-engine.h
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:105
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:279
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
action-globals.h
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_REJECT_ANY
#define ACTION_REJECT_ANY
Definition: action-globals.h:38
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
SCConfInit
void SCConfInit(void)
Initialize the configuration system.
Definition: conf.c:120
util-debug.h
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
detect.h
ACTION_ALERT
#define ACTION_ALERT
Definition: action-globals.h:29
conf-yaml-loader.h
conf.h
SCConfCreateContextBackup
void SCConfCreateContextBackup(void)
Creates a backup of the conf_hash hash_table used by the conf API.
Definition: conf.c:684
util-action.h
suricata-common.h
ACTION_DROP
#define ACTION_DROP
Definition: action-globals.h:30
SCConfDeInit
void SCConfDeInit(void)
De-initializes the configuration system.
Definition: conf.c:703
detect-engine-sigorder.h
SCConfGetNode
SCConfNode * SCConfGetNode(const char *name)
Get a SCConfNode by name.
Definition: conf.c:181
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:271
SCConfRestoreContextBackup
void SCConfRestoreContextBackup(void)
Restores the backup of the hash_table present in backup_conf_hash back to conf_hash.
Definition: conf.c:694
UtilActionRegisterTests
void UtilActionRegisterTests(void)
Definition: util-action.c:443
SCConfNode_
Definition: conf.h:37
SCConfNode_::val
char * val
Definition: conf.h:39