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-action.h"
35 #include "util-unittest-helper.h"
36 #include "util-debug.h"
37 
38 /* Default order: */
40 /* This order can be changed from config */
41 
42 /**
43  * \brief Return the priority associated to an action (to order sigs
44  * as specified at config)
45  * action_order_sigs has this priority by index val
46  * so action_order_sigs[0] has to be inspected first.
47  * This function is called from detect-engine-sigorder
48  * \param action can be one of ACTION_PASS, ACTION_DROP,
49  * ACTION_REJECT or ACTION_ALERT
50  * \retval uint8_t the priority (order of this actions)
51  */
52 uint8_t ActionOrderVal(uint8_t action)
53 {
54  /* reject_both and reject_dst have the same prio as reject */
55  if (action & ACTION_REJECT_ANY) {
56  action = ACTION_REJECT;
57  } else if (action & ACTION_DROP) {
58  action = ACTION_DROP;
59  } else if (action & ACTION_PASS) {
60  action = ACTION_PASS;
61  } else if (action & ACTION_ALERT) {
62  action = ACTION_ALERT;
63  } else if (action == 0) {
64  action = ACTION_ALERT;
65  }
66 
67  for (uint8_t i = 0; i < 4; i++) {
68  if (action_order_sigs[i] == action) {
69  return i;
70  }
71  }
72  /* Unknown action, set just a low prio (high val) */
73  return 10;
74 }
75 
76 /**
77  * \brief Return the ACTION_* bit from their ascii value
78  * \param action can be one of "pass", "drop",
79  * "reject" or "alert"
80  * \retval uint8_t can be one of ACTION_PASS, ACTION_DROP,
81  * ACTION_REJECT or ACTION_ALERT
82  */
83 static uint8_t ActionAsciiToFlag(const char *action)
84 {
85  if (strcmp(action,"pass") == 0)
86  return ACTION_PASS;
87  if (strcmp(action,"drop") == 0)
88  return ACTION_DROP;
89  if (strcmp(action,"reject") == 0)
90  return ACTION_REJECT;
91  if (strcmp(action,"alert") == 0)
92  return ACTION_ALERT;
93 
94  return 0;
95 }
96 
97 /**
98  * \brief Load the action order from config. If none is provided,
99  * it will be default to ACTION_PASS, ACTION_DROP,
100  * ACTION_REJECT, ACTION_ALERT (pass has the highest prio)
101  *
102  * \retval 0 on success; -1 on fatal error;
103  */
105 {
106  uint8_t actions_used = 0;
107  uint8_t action_flag = 0;
108  uint8_t actions_config[4] = {0, 0, 0, 0};
109  int order = 0;
110 
111  SCConfNode *action_order;
112  SCConfNode *action = NULL;
113 
114  /* Let's load the order of actions from the general config */
115  action_order = SCConfGetNode("action-order");
116  if (action_order == NULL) {
117  /* No configuration, use defaults. */
118  return 0;
119  }
120  else {
121  TAILQ_FOREACH(action, &action_order->head, next) {
122  SCLogDebug("Loading action order : %s", action->val);
123  action_flag = ActionAsciiToFlag(action->val);
124  if (action_flag == 0) {
125  SCLogError("action-order, invalid action: \"%s\". Please, use"
126  " \"pass\",\"drop\",\"alert\",\"reject\". You have"
127  " to specify all of them, without quotes and without"
128  " capital letters",
129  action->val);
130  goto error;
131  }
132 
133  if (actions_used & action_flag) {
134  SCLogError("action-order, action already set: \"%s\". Please,"
135  " use \"pass\",\"drop\",\"alert\",\"reject\". You"
136  " have to specify all of them, without quotes and"
137  " without capital letters",
138  action->val);
139  goto error;
140  }
141 
142  if (order >= 4) {
143  SCLogError("action-order, you have already specified all the "
144  "possible actions plus \"%s\". Please, use \"pass\","
145  "\"drop\",\"alert\",\"reject\". You have to specify"
146  " all of them, without quotes and without capital"
147  " letters",
148  action->val);
149  goto error;
150  }
151  actions_used |= action_flag;
152  actions_config[order++] = action_flag;
153  }
154  }
155  if (order < 4) {
156  SCLogError("action-order, the config didn't specify all of the "
157  "actions. Please, use \"pass\",\"drop\",\"alert\","
158  "\"reject\". You have to specify all of them, without"
159  " quotes and without capital letters");
160  goto error;
161  }
162 
163  /* Now, it's a valid config. Override the default preset */
164  for (order = 0; order < 4; order++) {
165  action_order_sigs[order] = actions_config[order];
166  }
167 
168  return 0;
169 
170  error:
171  return -1;
172 }
173 
174 #ifdef UNITTESTS
175 
176 /**
177  * \test Check that we invalidate duplicated actions
178  * (It should default to pass, drop, reject, alert)
179  */
180 static int UtilActionTest01(void)
181 {
182  char config[] = "\
183 %YAML 1.1\n\
184 ---\n\
185 action-order:\n\
186  - alert\n\
187  - drop\n\
188  - reject\n\
189  - alert\n";
190 
192  SCConfInit();
193  SCConfYamlLoadString(config, strlen(config));
194 
200 
201  SCConfDeInit();
203 
204  /* Restore default values */
209  PASS;
210 }
211 
212 /**
213  * \test Check that we invalidate with unknown keywords
214  * (It should default to pass, drop, reject, alert)
215  */
216 static int UtilActionTest02(void)
217 {
218  char config[] = "\
219 %YAML 1.1\n\
220 ---\n\
221 action-order:\n\
222  - alert\n\
223  - drop\n\
224  - reject\n\
225  - ftw\n";
226 
228  SCConfInit();
229  SCConfYamlLoadString(config, strlen(config));
230 
236  SCConfDeInit();
238 
239  /* Restore default values */
244  PASS;
245 }
246 
247 /**
248  * \test Check that we invalidate if any action is missing
249  * (It should default to pass, drop, reject, alert)
250  */
251 static int UtilActionTest03(void)
252 {
253  char config[] = "\
254 %YAML 1.1\n\
255 ---\n\
256 action-order:\n\
257  - alert\n\
258  - drop\n\
259  - reject\n";
260 
262  SCConfInit();
263  SCConfYamlLoadString(config, strlen(config));
264 
270  SCConfDeInit();
272 
273  /* Restore default values */
278  PASS;
279 }
280 
281 /**
282  * \test Check that we invalidate if any action is missing
283  * (It should default to pass, drop, reject, alert)
284  */
285 static int UtilActionTest04(void)
286 {
287  char config[] = "\
288 %YAML 1.1\n\
289 ---\n\
290 action-order:\n";
291 
293  SCConfInit();
294  SCConfYamlLoadString(config, strlen(config));
295 
301  SCConfDeInit();
303 
304  /* Restore default values */
309  PASS;
310 }
311 
312 /**
313  * \test Check that we invalidate with unknown keywords
314  * and/or more than the expected
315  * (It should default to pass, drop, reject, alert)
316  */
317 static int UtilActionTest05(void)
318 {
319  char config[] = "\
320 %YAML 1.1\n\
321 ---\n\
322 action-order:\n\
323  - alert\n\
324  - drop\n\
325  - reject\n\
326  - pass\n\
327  - whatever\n";
328 
330  SCConfInit();
331  SCConfYamlLoadString(config, strlen(config));
332 
338  SCConfDeInit();
340 
341  /* Restore default values */
346  PASS;
347 }
348 
349 /**
350  * \test Check that we load a valid config
351  */
352 static int UtilActionTest06(void)
353 {
354  char config[] = "\
355 %YAML 1.1\n\
356 ---\n\
357 action-order:\n\
358  - alert\n\
359  - drop\n\
360  - reject\n\
361  - pass\n";
362 
364  SCConfInit();
365  SCConfYamlLoadString(config, strlen(config));
366 
372  SCConfDeInit();
374 
375  /* Restore default values */
380  PASS;
381 }
382 
383 /**
384  * \test Check that we load a valid config
385  */
386 static int UtilActionTest07(void)
387 {
388  char config[] = "\
389 %YAML 1.1\n\
390 ---\n\
391 action-order:\n\
392  - pass\n\
393  - alert\n\
394  - drop\n\
395  - reject\n";
396 
398  SCConfInit();
399  SCConfYamlLoadString(config, strlen(config));
400 
406  SCConfDeInit();
408 
409  /* Restore default values */
414  PASS;
415 }
416 
417 /**
418  * \test Check that the expected defaults are loaded if the
419  * action-order configuration is not present.
420  */
421 static int UtilActionTest08(void)
422 {
423  char config[] = "%YAML 1.1\n"
424  "---\n";
425 
427  SCConfInit();
428  SCConfYamlLoadString(config, strlen(config));
429 
435 
436  SCConfDeInit();
438  PASS;
439 }
440 
441 /* Register unittests */
443 {
444  /* Generic tests */
445  UtRegisterTest("UtilActionTest01", UtilActionTest01);
446  UtRegisterTest("UtilActionTest02", UtilActionTest02);
447  UtRegisterTest("UtilActionTest02", UtilActionTest02);
448  UtRegisterTest("UtilActionTest03", UtilActionTest03);
449  UtRegisterTest("UtilActionTest04", UtilActionTest04);
450  UtRegisterTest("UtilActionTest05", UtilActionTest05);
451  UtRegisterTest("UtilActionTest06", UtilActionTest06);
452  UtRegisterTest("UtilActionTest07", UtilActionTest07);
453  UtRegisterTest("UtilActionTest08", UtilActionTest08);
454 }
455 #endif
SCConfYamlLoadString
int SCConfYamlLoadString(const char *string, size_t len)
Load configuration from a YAML string.
Definition: conf-yaml-loader.c:535
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:101
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:104
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
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:52
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:39
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:740
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:759
detect-engine-sigorder.h
SCConfGetNode
SCConfNode * SCConfGetNode(const char *name)
Get a SCConfNode by name.
Definition: conf.c:183
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:274
SCConfRestoreContextBackup
void SCConfRestoreContextBackup(void)
Restores the backup of the hash_table present in backup_conf_hash back to conf_hash.
Definition: conf.c:750
UtilActionRegisterTests
void UtilActionRegisterTests(void)
Definition: util-action.c:442
SCConfNode_
Definition: conf.h:37
SCConfNode_::val
char * val
Definition: conf.h:39