detect/flags: cleanup parsing to not alloc temp strings

pull/3534/head
Victor Julien 6 years ago
parent e22a833b94
commit 0a39e06535

@ -1,4 +1,4 @@
/* Copyright (C) 2007-2010 Open Information Security Foundation /* Copyright (C) 2007-2018 Open Information Security Foundation
* *
* You can copy, redistribute or modify this Program under the terms of * You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free * the GNU General Public License version 2 as published by the Free
@ -167,127 +167,57 @@ static DetectFlagsData *DetectFlagsParse (const char *rawstr)
{ {
SCEnter(); SCEnter();
DetectFlagsData *de = NULL;
#define MAX_SUBSTRINGS 30 #define MAX_SUBSTRINGS 30
int ret = 0, found = 0, ignore = 0, res = 0; int ret = 0, found = 0, ignore = 0, res = 0;
int ov[MAX_SUBSTRINGS]; int ov[MAX_SUBSTRINGS];
const char *str_ptr = NULL;
char *args[3] = { NULL, NULL, NULL };
char *ptr; char *ptr;
int i;
char arg1[16] = "";
char arg2[16] = "";
char arg3[16] = "";
ret = pcre_exec(parse_regex, parse_regex_study, rawstr, strlen(rawstr), ret = pcre_exec(parse_regex, parse_regex_study, rawstr, strlen(rawstr),
0, 0, ov, MAX_SUBSTRINGS); 0, 0, ov, MAX_SUBSTRINGS);
if (ret < 1) { SCLogDebug("input '%s', pcre said %d", rawstr, ret);
if (ret < 3) {
SCLogError(SC_ERR_PCRE_MATCH, "pcre match failed"); SCLogError(SC_ERR_PCRE_MATCH, "pcre match failed");
goto error; SCReturnPtr(NULL, "DetectFlagsData");
} }
for (i = 0; i < (ret - 1); i++) { res = pcre_copy_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 1, arg1, sizeof(arg1));
if (res < 0) {
res = pcre_get_substring((char *)rawstr, ov, MAX_SUBSTRINGS,i + 1, SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
&str_ptr); SCReturnPtr(NULL, "DetectFlagsData");
}
if (ret >= 2) {
res = pcre_copy_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 2, arg2, sizeof(arg2));
if (res < 0) { if (res < 0) {
SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
goto error; SCReturnPtr(NULL, "DetectFlagsData");
}
}
if (ret >= 3) {
res = pcre_copy_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 3, arg3, sizeof(arg3));
if (res < 0) {
SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
SCReturnPtr(NULL, "DetectFlagsData");
} }
args[i] = (char *)str_ptr;
} }
SCLogDebug("args '%s', '%s', '%s'", arg1, arg2, arg3);
if(args[1] == NULL) { if (strlen(arg2) == 0) {
SCLogDebug("args[1] == NULL"); SCLogDebug("empty argument");
goto error; SCReturnPtr(NULL, "DetectFlagsData");
} }
de = SCMalloc(sizeof(DetectFlagsData)); DetectFlagsData *de = SCMalloc(sizeof(DetectFlagsData));
if (unlikely(de == NULL)) if (unlikely(de == NULL))
goto error; goto error;
memset(de, 0, sizeof(DetectFlagsData));
memset(de,0,sizeof(DetectFlagsData));
de->ignored_flags = 0xff; de->ignored_flags = 0xff;
/** First parse args[0] */ /** First parse args1 */
ptr = arg1;
if(args[0]) {
ptr = args[0];
while (*ptr != '\0') {
switch (*ptr) {
case 'S':
case 's':
de->flags |= TH_SYN;
found++;
break;
case 'A':
case 'a':
de->flags |= TH_ACK;
found++;
break;
case 'F':
case 'f':
de->flags |= TH_FIN;
found++;
break;
case 'R':
case 'r':
de->flags |= TH_RST;
found++;
break;
case 'P':
case 'p':
de->flags |= TH_PUSH;
found++;
break;
case 'U':
case 'u':
de->flags |= TH_URG;
found++;
break;
case '1':
de->flags |= TH_CWR;
found++;
break;
case '2':
de->flags |= TH_ECN;
found++;
break;
case 'C':
case 'c':
de->flags |= TH_CWR;
found++;
break;
case 'E':
case 'e':
de->flags |= TH_ECN;
found++;
break;
case '0':
de->flags = 0;
found++;
break;
case '!':
de->modifier = MODIFIER_NOT;
break;
case '+':
de->modifier = MODIFIER_PLUS;
break;
case '*':
de->modifier = MODIFIER_ANY;
break;
}
ptr++;
}
}
/** Second parse first set of flags */
ptr = args[1];
while (*ptr != '\0') { while (*ptr != '\0') {
switch (*ptr) { switch (*ptr) {
case 'S': case 'S':
@ -344,46 +274,110 @@ static DetectFlagsData *DetectFlagsParse (const char *rawstr)
break; break;
case '!': case '!':
if (de->modifier != 0) {
SCLogError(SC_ERR_FLAGS_MODIFIER, "\"flags\" supports only"
" one modifier at a time");
goto error;
}
de->modifier = MODIFIER_NOT; de->modifier = MODIFIER_NOT;
SCLogDebug("NOT modifier is set");
break; break;
case '+': case '+':
if (de->modifier != 0) {
SCLogError(SC_ERR_FLAGS_MODIFIER, "\"flags\" supports only"
" one modifier at a time");
goto error;
}
de->modifier = MODIFIER_PLUS; de->modifier = MODIFIER_PLUS;
SCLogDebug("PLUS modifier is set");
break; break;
case '*': case '*':
if (de->modifier != 0) {
SCLogError(SC_ERR_FLAGS_MODIFIER, "\"flags\" supports only"
" one modifier at a time");
goto error;
}
de->modifier = MODIFIER_ANY; de->modifier = MODIFIER_ANY;
SCLogDebug("ANY modifier is set");
break;
default:
break; break;
} }
ptr++; ptr++;
} }
if(found == 0) /** Second parse first set of flags */
goto error; if (strlen(arg2) > 0) {
ptr = arg2;
while (*ptr != '\0') {
switch (*ptr) {
case 'S':
case 's':
de->flags |= TH_SYN;
found++;
break;
case 'A':
case 'a':
de->flags |= TH_ACK;
found++;
break;
case 'F':
case 'f':
de->flags |= TH_FIN;
found++;
break;
case 'R':
case 'r':
de->flags |= TH_RST;
found++;
break;
case 'P':
case 'p':
de->flags |= TH_PUSH;
found++;
break;
case 'U':
case 'u':
de->flags |= TH_URG;
found++;
break;
case '1':
case 'C':
case 'c':
de->flags |= TH_CWR;
found++;
break;
case '2':
case 'E':
case 'e':
de->flags |= TH_ECN;
found++;
break;
case '0':
de->flags = 0;
found++;
break;
/** Finally parse ignored flags */ case '!':
if (de->modifier != 0) {
SCLogError(SC_ERR_FLAGS_MODIFIER, "\"flags\" supports only"
" one modifier at a time");
goto error;
}
de->modifier = MODIFIER_NOT;
SCLogDebug("NOT modifier is set");
break;
case '+':
if (de->modifier != 0) {
SCLogError(SC_ERR_FLAGS_MODIFIER, "\"flags\" supports only"
" one modifier at a time");
goto error;
}
de->modifier = MODIFIER_PLUS;
SCLogDebug("PLUS modifier is set");
break;
case '*':
if (de->modifier != 0) {
SCLogError(SC_ERR_FLAGS_MODIFIER, "\"flags\" supports only"
" one modifier at a time");
goto error;
}
de->modifier = MODIFIER_ANY;
SCLogDebug("ANY modifier is set");
break;
default:
break;
}
ptr++;
}
if(args[2]) { if (found == 0)
goto error;
}
ptr = args[2]; /** Finally parse ignored flags */
if (strlen(arg3) > 0) {
ptr = arg3;
while (*ptr != '\0') { while (*ptr != '\0') {
switch (*ptr) { switch (*ptr) {
@ -443,25 +437,19 @@ static DetectFlagsData *DetectFlagsParse (const char *rawstr)
ptr++; ptr++;
} }
if(ignore == 0) { if (ignore == 0) {
SCLogDebug("ignore == 0"); SCLogDebug("ignore == 0");
goto error; goto error;
} }
} }
for (i = 0; i < (ret - 1); i++){
SCLogDebug("args[%"PRId32"] = %s",i, args[i]);
if (args[i] != NULL) SCFree(args[i]);
}
SCLogDebug("found %"PRId32" ignore %"PRId32"", found, ignore); SCLogDebug("found %"PRId32" ignore %"PRId32"", found, ignore);
SCReturnPtr(de, "DetectFlagsData"); SCReturnPtr(de, "DetectFlagsData");
error: error:
for (i = 0; i < (ret - 1); i++){ if (de) {
if (args[i] != NULL) SCFree(args[i]); SCFree(de);
} }
if (de) SCFree(de);
SCReturnPtr(NULL, "DetectFlagsData"); SCReturnPtr(NULL, "DetectFlagsData");
} }
@ -628,14 +616,11 @@ static _Bool PrefilterTcpFlagsIsPrefilterable(const Signature *s)
*/ */
static int FlagsTestParse01 (void) static int FlagsTestParse01 (void)
{ {
DetectFlagsData *de = NULL; DetectFlagsData *de = DetectFlagsParse("S");
de = DetectFlagsParse("S"); FAIL_IF_NULL(de);
if (de && (de->flags == TH_SYN) ) { FAIL_IF_NOT(de->flags == TH_SYN);
DetectFlagsFree(de); DetectFlagsFree(de);
return 1; PASS;
}
return 0;
} }
/** /**

Loading…
Cancel
Save