Skip to content

Commit

Permalink
requires: pre-scan option for requires statements
Browse files Browse the repository at this point in the history
Pre-scan the rule options looking for requires. This eliminates the
need for requires to come before any options that may depend on
requiring a specific version or feature.
  • Loading branch information
jasonish committed Nov 29, 2023
1 parent bd9295f commit faad6e3
Showing 1 changed file with 38 additions and 3 deletions.
41 changes: 38 additions & 3 deletions src/detect-parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -847,7 +847,8 @@ int SigMatchListSMBelongsTo(const Signature *s, const SigMatch *key_sm)
return -1;
}

static int SigParseOptions(DetectEngineCtx *de_ctx, Signature *s, char *optstr, char *output, size_t output_size)
static int SigParseOptions(DetectEngineCtx *de_ctx, Signature *s, char *optstr, char *output,
size_t output_size, bool requires)
{
SigTableElmt *st = NULL;
char *optname = NULL;
Expand Down Expand Up @@ -901,6 +902,12 @@ static int SigParseOptions(DetectEngineCtx *de_ctx, Signature *s, char *optstr,
}
optname = optstr;

if (requires) {
if (strcmp(optname, "requires")) {
goto finish;
}
}

/* Call option parsing */
st = SigTableGet(optname);
if (st == NULL || st->Setup == NULL) {
Expand Down Expand Up @@ -1040,6 +1047,7 @@ static int SigParseOptions(DetectEngineCtx *de_ctx, Signature *s, char *optstr,
}
s->init_data->negated = false;

finish:
if (strlen(optend) > 0) {
strlcpy(output, optend, output_size);
return 1;
Expand Down Expand Up @@ -1463,7 +1471,7 @@ static int SigParse(DetectEngineCtx *de_ctx, Signature *s,
SCReturnInt(-1);
}

/* we can have no options, so make sure we have them */
/* First we will scan the options for requires. */
if (strlen(parser->opts) > 0) {
size_t buffer_size = strlen(parser->opts) + 1;
char input[buffer_size];
Expand All @@ -1476,14 +1484,41 @@ static int SigParse(DetectEngineCtx *de_ctx, Signature *s,
* output variable. */
do {
memset(output, 0x00, buffer_size);
ret = SigParseOptions(de_ctx, s, input, output, buffer_size);
ret = SigParseOptions(de_ctx, s, input, output, buffer_size, true);
if (ret == 1) {
memcpy(input, output, buffer_size);
}

} while (ret == 1);

if (ret < 0) {
/* Suricata didn't meet the rule requirements, skip. */
goto end;
}
}

/* we can have no options, so make sure we have them */
if (strlen(parser->opts) > 0) {
size_t buffer_size = strlen(parser->opts) + 1;
char input[buffer_size];
char output[buffer_size];
memset(input, 0x00, buffer_size);
memcpy(input, parser->opts, strlen(parser->opts) + 1);

/* loop the option parsing. Each run processes one option
* and returns the rest of the option string through the
* output variable. */
do {
memset(output, 0x00, buffer_size);
ret = SigParseOptions(de_ctx, s, input, output, buffer_size, false);
if (ret == 1) {
memcpy(input, output, buffer_size);
}

} while (ret == 1);
}

end:
DetectIPProtoRemoveAllSMs(de_ctx, s);

SCReturnInt(ret);
Expand Down

0 comments on commit faad6e3

Please sign in to comment.