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  ConfNode *action_order;
113  ConfNode *action = NULL;
114 
115  /* Let's load the order of actions from the general config */
116  action_order = ConfGetNode("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  ConfInit();
194  ConfYamlLoadString(config, strlen(config));
195 
202 
203  /* Restore default values */
208  PASS;
209 }
210 
211 /**
212  * \test Check that we invalidate with unknown keywords
213  * (It should default to pass, drop, reject, alert)
214  */
215 static int UtilActionTest02(void)
216 {
217  char config[] = "\
218 %YAML 1.1\n\
219 ---\n\
220 action-order:\n\
221  - alert\n\
222  - drop\n\
223  - reject\n\
224  - ftw\n";
225 
227  ConfInit();
228  ConfYamlLoadString(config, strlen(config));
229 
236 
237  /* Restore default values */
242  PASS;
243 }
244 
245 /**
246  * \test Check that we invalidate if any action is missing
247  * (It should default to pass, drop, reject, alert)
248  */
249 static int UtilActionTest03(void)
250 {
251  char config[] = "\
252 %YAML 1.1\n\
253 ---\n\
254 action-order:\n\
255  - alert\n\
256  - drop\n\
257  - reject\n";
258 
260  ConfInit();
261  ConfYamlLoadString(config, strlen(config));
262 
269 
270  /* Restore default values */
275  PASS;
276 }
277 
278 /**
279  * \test Check that we invalidate if any action is missing
280  * (It should default to pass, drop, reject, alert)
281  */
282 static int UtilActionTest04(void)
283 {
284  char config[] = "\
285 %YAML 1.1\n\
286 ---\n\
287 action-order:\n";
288 
290  ConfInit();
291  ConfYamlLoadString(config, strlen(config));
292 
299 
300  /* Restore default values */
305  PASS;
306 }
307 
308 /**
309  * \test Check that we invalidate with unknown keywords
310  * and/or more than the expected
311  * (It should default to pass, drop, reject, alert)
312  */
313 static int UtilActionTest05(void)
314 {
315  char config[] = "\
316 %YAML 1.1\n\
317 ---\n\
318 action-order:\n\
319  - alert\n\
320  - drop\n\
321  - reject\n\
322  - pass\n\
323  - whatever\n";
324 
326  ConfInit();
327  ConfYamlLoadString(config, strlen(config));
328 
335 
336  /* Restore default values */
341  PASS;
342 }
343 
344 /**
345  * \test Check that we load a valid config
346  */
347 static int UtilActionTest06(void)
348 {
349  char config[] = "\
350 %YAML 1.1\n\
351 ---\n\
352 action-order:\n\
353  - alert\n\
354  - drop\n\
355  - reject\n\
356  - pass\n";
357 
359  ConfInit();
360  ConfYamlLoadString(config, strlen(config));
361 
368 
369  /* Restore default values */
374  PASS;
375 }
376 
377 /**
378  * \test Check that we load a valid config
379  */
380 static int UtilActionTest07(void)
381 {
382  char config[] = "\
383 %YAML 1.1\n\
384 ---\n\
385 action-order:\n\
386  - pass\n\
387  - alert\n\
388  - drop\n\
389  - reject\n";
390 
392  ConfInit();
393  ConfYamlLoadString(config, strlen(config));
394 
401 
402  /* Restore default values */
407  PASS;
408 }
409 
410 /**
411  * \test Check that the expected defaults are loaded if the
412  * action-order configuration is not present.
413  */
414 static int UtilActionTest08(void)
415 {
416  char config[] = "%YAML 1.1\n"
417  "---\n";
418 
420  ConfInit();
421  ConfYamlLoadString(config, strlen(config));
422 
428 
430  PASS;
431 }
432 
433 /* Register unittests */
435 {
436  /* Generic tests */
437  UtRegisterTest("UtilActionTest01", UtilActionTest01);
438  UtRegisterTest("UtilActionTest02", UtilActionTest02);
439  UtRegisterTest("UtilActionTest02", UtilActionTest02);
440  UtRegisterTest("UtilActionTest03", UtilActionTest03);
441  UtRegisterTest("UtilActionTest04", UtilActionTest04);
442  UtRegisterTest("UtilActionTest05", UtilActionTest05);
443  UtRegisterTest("UtilActionTest06", UtilActionTest06);
444  UtRegisterTest("UtilActionTest07", UtilActionTest07);
445  UtRegisterTest("UtilActionTest08", UtilActionTest08);
446 }
447 #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:105
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_REJECT_ANY
#define ACTION_REJECT_ANY
Definition: action-globals.h:37
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
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:520
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:669
util-action.h
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:679
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:434