pcre: support multiple captures

Support up to 8 substring captures into pkt or flow vars.
pull/2559/head
Victor Julien 9 years ago
parent 017b16d421
commit a0bd15a1c4

@ -267,8 +267,14 @@ static inline int SCSigGetFlowvarType(Signature *sig)
while (sm != NULL) {
pd = (DetectPcreData *)sm->ctx;
if (sm->type == DETECT_PCRE && (pd->flags & DETECT_PCRE_CAPTURE_FLOW)) {
write++;
if (sm->type == DETECT_PCRE) {
uint8_t x;
for (x = 0; x < pd->idx; x++) {
if (pd->captypes[x] == VAR_TYPE_FLOW_VAR) {
write++;
break;
}
}
}
sm = sm->next;
@ -319,8 +325,14 @@ static inline int SCSigGetPktvarType(Signature *sig)
while (sm != NULL) {
pd = (DetectPcreData *)sm->ctx;
if (sm->type == DETECT_PCRE && (pd->flags & DETECT_PCRE_CAPTURE_PKT)) {
write++;
if (sm->type == DETECT_PCRE) {
uint8_t x;
for (x = 0; x < pd->idx; x++) {
if (pd->captypes[x] == VAR_TYPE_PKT_VAR) {
write++;
break;
}
}
}
sm = sm->next;

@ -213,26 +213,29 @@ int DetectPcrePayloadMatch(DetectEngineThreadCtx *det_ctx, const Signature *s,
/* regex matched and we're not negated,
* considering it a match */
SCLogDebug("ret %d capidx %u", ret, pe->capidx);
SCLogDebug("ret %d pe->idx %u", ret, pe->idx);
/* see if we need to do substring capturing. */
if (ret > 1 && pe->capidx != 0) {
SCLogDebug("capturing");
const char *str_ptr;
ret = pcre_get_substring((char *)ptr, ov, MAX_SUBSTRINGS, 1, &str_ptr);
if (ret) {
if (pe->flags & DETECT_PCRE_CAPTURE_PKT) {
if (p != NULL) {
PktVarAdd(p, pe->capname, (uint8_t *)str_ptr, ret);
}
} else if (pe->flags & DETECT_PCRE_CAPTURE_FLOW) {
if (f != NULL) {
/* store max 64k. Errors are ignored */
capture_len = (ret < 0xffff) ? (uint16_t)ret : 0xffff;
(void)DetectFlowvarStoreMatch(det_ctx, pe->capidx,
(uint8_t *)str_ptr, capture_len,
DETECT_FLOWVAR_TYPE_POSTMATCH);
}
if (ret > 1 && pe->idx != 0) {
uint8_t x;
for (x = 0; x < pe->idx; x++) {
SCLogDebug("capturing");
const char *str_ptr;
ret = pcre_get_substring((char *)ptr, ov, MAX_SUBSTRINGS, x+1, &str_ptr);
if (unlikely(ret == 0))
continue;
if (pe->captypes[x] == VAR_TYPE_PKT_VAR && p != NULL) {
const char *varname = VarNameStoreLookupById(pe->capids[x],
VAR_TYPE_PKT_VAR);
PktVarAdd(p, varname, (uint8_t *)str_ptr, ret);
} else if (pe->captypes[x] == VAR_TYPE_FLOW_VAR && f != NULL) {
/* store max 64k. Errors are ignored */
capture_len = (ret < 0xffff) ? (uint16_t)ret : 0xffff;
(void)DetectFlowvarStoreMatch(det_ctx, pe->capids[x],
(uint8_t *)str_ptr, capture_len,
DETECT_FLOWVAR_TYPE_POSTMATCH);
}
}
}
@ -607,7 +610,11 @@ static int DetectPcreParseCapture(char *regexstr, DetectEngineCtx *de_ctx, Detec
{
int ret = 0, res = 0;
int ov[MAX_SUBSTRINGS];
memset(&ov, 0, sizeof(ov));
char type_str[16] = "";
char *orig_right_edge = regexstr + strlen(regexstr);
SCLogDebug("regexstr %s, pd %p", regexstr, pd);
/* take the size of the whole input as buffer size for the string we will
* extract below. Add 1 to please Coverity's alloc_strlen test. */
@ -618,55 +625,57 @@ static int DetectPcreParseCapture(char *regexstr, DetectEngineCtx *de_ctx, Detec
if (de_ctx == NULL)
goto error;
SCLogDebug("\'%s\'", regexstr);
while (1) {
SCLogDebug("\'%s\'", regexstr);
ret = pcre_exec(parse_capture_regex, parse_capture_regex_study, regexstr, strlen(regexstr), 0, 0, ov, MAX_SUBSTRINGS);
if (ret < 3) {
return 0;
}
ret = pcre_exec(parse_capture_regex, parse_capture_regex_study, regexstr, strlen(regexstr), 0, 0, ov, MAX_SUBSTRINGS);
if (ret < 3) {
return 0;
}
res = pcre_copy_substring((char *)regexstr, ov, MAX_SUBSTRINGS, 1, type_str, sizeof(type_str));
if (res < 0) {
SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
goto error;
}
res = pcre_copy_substring((char *)regexstr, ov, MAX_SUBSTRINGS, 2, capture_str, cap_buffer_len);
if (res < 0) {
SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
goto error;
}
if (strlen(capture_str) == 0 || strlen(type_str) == 0) {
goto error;
}
res = pcre_copy_substring((char *)regexstr, ov, MAX_SUBSTRINGS, 1, type_str, sizeof(type_str));
if (res < 0) {
SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
goto error;
}
res = pcre_copy_substring((char *)regexstr, ov, MAX_SUBSTRINGS, 2, capture_str, cap_buffer_len);
if (res < 0) {
SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
goto error;
}
if (strlen(capture_str) == 0 || strlen(type_str) == 0) {
goto error;
}
SCLogDebug("type \'%s\'", type_str);
SCLogDebug("capture \'%s\'", capture_str);
SCLogDebug("type \'%s\'", type_str);
SCLogDebug("capture \'%s\'", capture_str);
pd->capname = SCStrdup(capture_str);
if (unlikely(pd->capname == NULL))
goto error;
if (pd->idx >= DETECT_PCRE_CAPTURE_MAX) {
SCLogError(SC_ERR_VAR_LIMIT, "rule can have maximally %d pkt/flow "
"var captures", DETECT_PCRE_CAPTURE_MAX);
return -1;
}
if (strcmp(type_str, "pkt") == 0) {
pd->flags |= DETECT_PCRE_CAPTURE_PKT;
} else if (strcmp(type_str, "flow") == 0) {
pd->flags |= DETECT_PCRE_CAPTURE_FLOW;
SCLogDebug("flow capture");
}
if (pd->capname != NULL) {
if (pd->flags & DETECT_PCRE_CAPTURE_PKT)
pd->capidx = VarNameStoreSetupAdd((char *)pd->capname, VAR_TYPE_PKT_VAR);
else if (pd->flags & DETECT_PCRE_CAPTURE_FLOW)
pd->capidx = VarNameStoreSetupAdd((char *)pd->capname, VAR_TYPE_FLOW_VAR);
}
if (strcmp(type_str, "pkt") == 0) {
pd->capids[pd->idx] = VarNameStoreSetupAdd((char *)capture_str, VAR_TYPE_PKT_VAR);
pd->captypes[pd->idx] = VAR_TYPE_PKT_VAR;
SCLogDebug("id %u type %u", pd->capids[pd->idx], pd->captypes[pd->idx]);
pd->idx++;
} else if (strcmp(type_str, "flow") == 0) {
pd->capids[pd->idx] = VarNameStoreSetupAdd((char *)capture_str, VAR_TYPE_FLOW_VAR);
pd->captypes[pd->idx] = VAR_TYPE_FLOW_VAR;
pd->idx++;
}
SCLogDebug("pd->capname %s", pd->capname);
//SCLogDebug("pd->capname %s", pd->capname);
regexstr += ov[1];
if (regexstr >= orig_right_edge)
break;
}
return 0;
error:
if (pd->capname != NULL) {
SCFree(pd->capname);
pd->capname = NULL;
}
return -1;
}
@ -708,9 +717,12 @@ static int DetectPcreSetup (DetectEngineCtx *de_ctx, Signature *s, char *regexst
sm->ctx = (void *)pd;
SigMatchAppendSMToList(s, sm, sm_list);
if (pd->capidx != 0) {
if (DetectFlowvarPostMatchSetup(s, pd->capidx) < 0)
goto error_nofree;
uint8_t x;
for (x = 0; x < pd->idx; x++) {
if (pd->captypes[x] == VAR_TYPE_FLOW_VAR) {
if (DetectFlowvarPostMatchSetup(s, pd->capids[x]) < 0)
goto error_nofree;
}
}
if (!(pd->flags & DETECT_PCRE_RELATIVE))
@ -751,8 +763,6 @@ static void DetectPcreFree(void *ptr)
DetectPcreData *pd = (DetectPcreData *)ptr;
if (pd->capname != NULL)
SCFree(pd->capname);
if (pd->re != NULL)
pcre_free(pd->re);
if (pd->sd != NULL)
@ -3022,7 +3032,7 @@ static int DetectPcreFlowvarCapture01(void)
FAIL_IF(!(PacketAlertCheck(p1, 1)));
FlowVar *fv = FlowVarGet(&f, pd->capidx);
FlowVar *fv = FlowVarGet(&f, pd->capids[0]);
FAIL_IF(fv == NULL);
FAIL_IF(fv->data.fv_str.value_len != ualen1);
@ -3114,7 +3124,7 @@ static int DetectPcreFlowvarCapture02(void)
s->sm_lists[g_http_header_buffer_id]->next->type != DETECT_PCRE);
DetectPcreData *pd2 = (DetectPcreData *)s->sm_lists[g_http_header_buffer_id]->next->ctx;
FAIL_IF(pd1->capidx != pd2->capidx);
FAIL_IF(pd1->capids[0] != pd2->capids[0]);
SCSigRegisterSignatureOrderingFuncs(de_ctx);
SCSigOrderSignatures(de_ctx);
@ -3136,7 +3146,7 @@ static int DetectPcreFlowvarCapture02(void)
FAIL_IF(!(PacketAlertCheck(p1, 1)));
FlowVar *fv = FlowVarGet(&f, pd1->capidx);
FlowVar *fv = FlowVarGet(&f, pd1->capids[0]);
FAIL_IF(fv == NULL);
if (fv->data.fv_str.value_len != ualen1) {
@ -3230,7 +3240,7 @@ static int DetectPcreFlowvarCapture03(void)
s->sm_lists[g_http_header_buffer_id]->next->type != DETECT_PCRE);
DetectPcreData *pd2 = (DetectPcreData *)s->sm_lists[g_http_header_buffer_id]->next->ctx;
FAIL_IF(pd1->capidx != pd2->capidx);
FAIL_IF(pd1->capids[0] != pd2->capids[0]);
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
@ -3249,7 +3259,7 @@ static int DetectPcreFlowvarCapture03(void)
FAIL_IF(PacketAlertCheck(p1, 1));
FlowVar *fv = FlowVarGet(&f, pd1->capidx);
FlowVar *fv = FlowVarGet(&f, pd1->capids[0]);
FAIL_IF(fv != NULL);
if (alp_tctx != NULL)

@ -27,20 +27,22 @@
#define DETECT_PCRE_RELATIVE 0x00001
#define DETECT_PCRE_RAWBYTES 0x00002
#define DETECT_PCRE_CASELESS 0x00004
#define DETECT_PCRE_CAPTURE_PKT 0x00008
#define DETECT_PCRE_CAPTURE_FLOW 0x00010
#define DETECT_PCRE_MATCH_LIMIT 0x00020
#define DETECT_PCRE_RELATIVE_NEXT 0x00040
#define DETECT_PCRE_NEGATE 0x00080
#define DETECT_PCRE_CAPTURE_MAX 8
typedef struct DetectPcreData_ {
/* pcre options */
pcre *re;
pcre_extra *sd;
int opts;
uint16_t flags;
uint32_t capidx;
char *capname;
uint8_t idx;
uint8_t captypes[DETECT_PCRE_CAPTURE_MAX];
uint32_t capids[DETECT_PCRE_CAPTURE_MAX];
} DetectPcreData;
/* prototypes */

@ -335,6 +335,7 @@ const char * SCErrorToString(SCError err)
CASE_CODE(SC_WARN_REMOVE_FILE);
CASE_CODE (SC_ERR_NO_MAGIC_SUPPORT);
CASE_CODE (SC_ERR_REDIS);
CASE_CODE (SC_ERR_VAR_LIMIT);
}
return "UNKNOWN_ERROR";

@ -325,6 +325,7 @@ typedef enum {
SC_WARN_REMOVE_FILE,
SC_ERR_NO_MAGIC_SUPPORT,
SC_ERR_REDIS,
SC_ERR_VAR_LIMIT,
} SCError;
const char *SCErrorToString(SCError);

Loading…
Cancel
Save