• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OISF / suricata / 23374838686

21 Mar 2026 07:29AM UTC coverage: 59.341% (-20.0%) from 79.315%
23374838686

Pull #15075

github

web-flow
Merge 90b4e834f into 6587e363a
Pull Request #15075: Stack 8001 v16.4

38 of 70 new or added lines in 10 files covered. (54.29%)

34165 existing lines in 563 files now uncovered.

119621 of 201584 relevant lines covered (59.34%)

650666.92 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

34.09
/src/util-action.c
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: */
40
uint8_t action_order_sigs[4] = {ACTION_PASS, ACTION_DROP, ACTION_REJECT, ACTION_ALERT};
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
{
756,376✔
55
    /* reject_both and reject_dst have the same prio as reject */
56
    if (action & ACTION_REJECT_ANY) {
756,376✔
57
        action = ACTION_REJECT;
150✔
58
    } else if (action & ACTION_DROP) {
756,226✔
59
        action = ACTION_DROP;
9,282✔
60
    } else if (action & ACTION_PASS) {
746,944✔
61
        action = ACTION_PASS;
37,446✔
62
    } else if (action & ACTION_ALERT) {
709,498✔
63
        action = ACTION_ALERT;
703,659✔
64
    } else if (action == 0) {
703,659✔
65
        action = ACTION_ALERT;
5,776✔
66
    }
5,776✔
67

68
    for (uint8_t i = 0; i < 4; i++) {
2,894,515✔
69
        if (action_order_sigs[i] == action) {
2,894,452✔
70
            return i;
756,313✔
71
        }
756,313✔
72
    }
2,894,452✔
73
    /* Unknown action, set just a low prio (high val) */
74
    return 10;
63✔
75
}
756,376✔
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)
UNCOV
85
{
×
UNCOV
86
    if (strcmp(action,"pass") == 0)
×
UNCOV
87
        return ACTION_PASS;
×
UNCOV
88
    if (strcmp(action,"drop") == 0)
×
UNCOV
89
        return ACTION_DROP;
×
UNCOV
90
    if (strcmp(action,"reject") == 0)
×
UNCOV
91
        return ACTION_REJECT;
×
UNCOV
92
    if (strcmp(action,"alert") == 0)
×
UNCOV
93
        return ACTION_ALERT;
×
94

UNCOV
95
    return 0;
×
UNCOV
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
 */
105
int ActionInitConfig(void)
106
{
35,469✔
107
    uint8_t actions_used = 0;
35,469✔
108
    uint8_t action_flag = 0;
35,469✔
109
    uint8_t actions_config[4] = {0, 0, 0, 0};
35,469✔
110
    int order = 0;
35,469✔
111

112
    SCConfNode *action_order;
35,469✔
113
    SCConfNode *action = NULL;
35,469✔
114

115
    /* Let's load the order of actions from the general config */
116
    action_order = SCConfGetNode("action-order");
35,469✔
117
    if (action_order == NULL) {
35,469✔
118
        /* No configuration, use defaults. */
119
        return 0;
35,469✔
120
    }
35,469✔
UNCOV
121
    else {
×
UNCOV
122
        TAILQ_FOREACH(action, &action_order->head, next) {
×
UNCOV
123
            SCLogDebug("Loading action order : %s", action->val);
×
UNCOV
124
            action_flag = ActionAsciiToFlag(action->val);
×
UNCOV
125
            if (action_flag == 0) {
×
UNCOV
126
                SCLogError("action-order, invalid action: \"%s\". Please, use"
×
UNCOV
127
                           " \"pass\",\"drop\",\"alert\",\"reject\". You have"
×
UNCOV
128
                           " to specify all of them, without quotes and without"
×
UNCOV
129
                           " capital letters",
×
UNCOV
130
                        action->val);
×
UNCOV
131
                goto error;
×
UNCOV
132
            }
×
133

UNCOV
134
            if (actions_used & action_flag) {
×
UNCOV
135
                SCLogError("action-order, action already set: \"%s\". Please,"
×
UNCOV
136
                           " use \"pass\",\"drop\",\"alert\",\"reject\". You"
×
UNCOV
137
                           " have to specify all of them, without quotes and"
×
UNCOV
138
                           " without capital letters",
×
UNCOV
139
                        action->val);
×
UNCOV
140
                goto error;
×
UNCOV
141
            }
×
142

UNCOV
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
            }
×
UNCOV
152
            actions_used |= action_flag;
×
UNCOV
153
            actions_config[order++] = action_flag;
×
UNCOV
154
        }
×
UNCOV
155
    }
×
UNCOV
156
    if (order < 4) {
×
UNCOV
157
        SCLogError("action-order, the config didn't specify all of the "
×
UNCOV
158
                   "actions. Please, use \"pass\",\"drop\",\"alert\","
×
UNCOV
159
                   "\"reject\". You have to specify all of them, without"
×
UNCOV
160
                   " quotes and without capital letters");
×
UNCOV
161
        goto error;
×
UNCOV
162
    }
×
163

164
    /* Now, it's a valid config. Override the default preset */
UNCOV
165
    for (order = 0; order < 4; order++) {
×
UNCOV
166
        action_order_sigs[order] = actions_config[order];
×
UNCOV
167
    }
×
168

UNCOV
169
    return 0;
×
170

UNCOV
171
 error:
×
UNCOV
172
    return -1;
×
UNCOV
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

192
    SCConfCreateContextBackup();
193
    SCConfInit();
194
    SCConfYamlLoadString(config, strlen(config));
195

196
    ActionInitConfig();
197
    FAIL_IF_NOT(action_order_sigs[0] == ACTION_PASS);
198
    FAIL_IF_NOT(action_order_sigs[1] == ACTION_DROP);
199
    FAIL_IF_NOT(action_order_sigs[2] == ACTION_REJECT);
200
    FAIL_IF_NOT(action_order_sigs[3] == ACTION_ALERT);
201

202
    SCConfDeInit();
203
    SCConfRestoreContextBackup();
204

205
    /* Restore default values */
206
    action_order_sigs[0] = ACTION_PASS;
207
    action_order_sigs[1] = ACTION_DROP;
208
    action_order_sigs[2] = ACTION_REJECT;
209
    action_order_sigs[3] = ACTION_ALERT;
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

228
    SCConfCreateContextBackup();
229
    SCConfInit();
230
    SCConfYamlLoadString(config, strlen(config));
231

232
    ActionInitConfig();
233
    FAIL_IF_NOT(action_order_sigs[0] == ACTION_PASS);
234
    FAIL_IF_NOT(action_order_sigs[1] == ACTION_DROP);
235
    FAIL_IF_NOT(action_order_sigs[2] == ACTION_REJECT);
236
    FAIL_IF_NOT(action_order_sigs[3] == ACTION_ALERT);
237
    SCConfDeInit();
238
    SCConfRestoreContextBackup();
239

240
    /* Restore default values */
241
    action_order_sigs[0] = ACTION_PASS;
242
    action_order_sigs[1] = ACTION_DROP;
243
    action_order_sigs[2] = ACTION_REJECT;
244
    action_order_sigs[3] = ACTION_ALERT;
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

262
    SCConfCreateContextBackup();
263
    SCConfInit();
264
    SCConfYamlLoadString(config, strlen(config));
265

266
    ActionInitConfig();
267
    FAIL_IF_NOT(action_order_sigs[0] == ACTION_PASS);
268
    FAIL_IF_NOT(action_order_sigs[1] == ACTION_DROP);
269
    FAIL_IF_NOT(action_order_sigs[2] == ACTION_REJECT);
270
    FAIL_IF_NOT(action_order_sigs[3] == ACTION_ALERT);
271
    SCConfDeInit();
272
    SCConfRestoreContextBackup();
273

274
    /* Restore default values */
275
    action_order_sigs[0] = ACTION_PASS;
276
    action_order_sigs[1] = ACTION_DROP;
277
    action_order_sigs[2] = ACTION_REJECT;
278
    action_order_sigs[3] = ACTION_ALERT;
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

293
    SCConfCreateContextBackup();
294
    SCConfInit();
295
    SCConfYamlLoadString(config, strlen(config));
296

297
    ActionInitConfig();
298
    FAIL_IF_NOT(action_order_sigs[0] == ACTION_PASS);
299
    FAIL_IF_NOT(action_order_sigs[1] == ACTION_DROP);
300
    FAIL_IF_NOT(action_order_sigs[2] == ACTION_REJECT);
301
    FAIL_IF_NOT(action_order_sigs[3] == ACTION_ALERT);
302
    SCConfDeInit();
303
    SCConfRestoreContextBackup();
304

305
    /* Restore default values */
306
    action_order_sigs[0] = ACTION_PASS;
307
    action_order_sigs[1] = ACTION_DROP;
308
    action_order_sigs[2] = ACTION_REJECT;
309
    action_order_sigs[3] = ACTION_ALERT;
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

330
    SCConfCreateContextBackup();
331
    SCConfInit();
332
    SCConfYamlLoadString(config, strlen(config));
333

334
    ActionInitConfig();
335
    FAIL_IF_NOT(action_order_sigs[0] == ACTION_PASS);
336
    FAIL_IF_NOT(action_order_sigs[1] == ACTION_DROP);
337
    FAIL_IF_NOT(action_order_sigs[2] == ACTION_REJECT);
338
    FAIL_IF_NOT(action_order_sigs[3] == ACTION_ALERT);
339
    SCConfDeInit();
340
    SCConfRestoreContextBackup();
341

342
    /* Restore default values */
343
    action_order_sigs[0] = ACTION_PASS;
344
    action_order_sigs[1] = ACTION_DROP;
345
    action_order_sigs[2] = ACTION_REJECT;
346
    action_order_sigs[3] = ACTION_ALERT;
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

364
    SCConfCreateContextBackup();
365
    SCConfInit();
366
    SCConfYamlLoadString(config, strlen(config));
367

368
    ActionInitConfig();
369
    FAIL_IF_NOT(action_order_sigs[0] == ACTION_ALERT);
370
    FAIL_IF_NOT(action_order_sigs[1] == ACTION_DROP);
371
    FAIL_IF_NOT(action_order_sigs[2] == ACTION_REJECT);
372
    FAIL_IF_NOT(action_order_sigs[3] == ACTION_PASS);
373
    SCConfDeInit();
374
    SCConfRestoreContextBackup();
375

376
    /* Restore default values */
377
    action_order_sigs[0] = ACTION_PASS;
378
    action_order_sigs[1] = ACTION_DROP;
379
    action_order_sigs[2] = ACTION_REJECT;
380
    action_order_sigs[3] = ACTION_ALERT;
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

398
    SCConfCreateContextBackup();
399
    SCConfInit();
400
    SCConfYamlLoadString(config, strlen(config));
401

402
    ActionInitConfig();
403
    FAIL_IF_NOT(action_order_sigs[0] == ACTION_PASS);
404
    FAIL_IF_NOT(action_order_sigs[1] == ACTION_ALERT);
405
    FAIL_IF_NOT(action_order_sigs[2] == ACTION_DROP);
406
    FAIL_IF_NOT(action_order_sigs[3] == ACTION_REJECT);
407
    SCConfDeInit();
408
    SCConfRestoreContextBackup();
409

410
    /* Restore default values */
411
    action_order_sigs[0] = ACTION_PASS;
412
    action_order_sigs[1] = ACTION_DROP;
413
    action_order_sigs[2] = ACTION_REJECT;
414
    action_order_sigs[3] = ACTION_ALERT;
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

427
    SCConfCreateContextBackup();
428
    SCConfInit();
429
    SCConfYamlLoadString(config, strlen(config));
430

431
    FAIL_IF_NOT(ActionInitConfig() == 0);
432
    FAIL_IF_NOT(action_order_sigs[0] == ACTION_PASS);
433
    FAIL_IF_NOT(action_order_sigs[1] == ACTION_DROP);
434
    FAIL_IF_NOT(action_order_sigs[2] == ACTION_REJECT);
435
    FAIL_IF_NOT(action_order_sigs[3] == ACTION_ALERT);
436

437
    SCConfDeInit();
438
    SCConfRestoreContextBackup();
439
    PASS;
440
}
441

442
/* Register unittests */
443
void UtilActionRegisterTests(void)
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
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc