/* PCRE part of the detection engine. */ #include #include "debug.h" #include "decode.h" #include "detect.h" #include "flow-var.h" #include "detect-pcre.h" #include "detect-mpm.h" #define PARSE_CAPTURE_REGEX "\\(\\?P\\<([A-z0-9_]+)\\>" #define PARSE_REGEX "(?tcp_payload_len == 0) return 0; //printf("DetectPcre: pre match: t->pkt_ptr %p t->pkt_off %u\n", t->pkt_ptr, t->pkt_off); DetectPcreData *pe = (DetectPcreData *)m->ctx; if (s->flags & SIG_FLAG_RECURSIVE) { ptr = pmt->pkt_ptr ? pmt->pkt_ptr : p->tcp_payload; len = p->tcp_payload_len - pmt->pkt_off; } else if (pe->flags & DETECT_PCRE_RELATIVE) { ptr = pmt->pkt_ptr; len = p->tcp_payload_len - pmt->pkt_off; if (ptr == NULL || len == 0) return 0; } else { ptr = p->tcp_payload; len = p->tcp_payload_len; } //printf("DetectPcre: ptr %p, len %u\n", ptr, len); ret = pcre_exec(pe->re, pe->sd, (char *)ptr, len, 0, 0, ov, MAX_SUBSTRINGS); if (ret >= 0) { if (ret > 1 && pe->capname != NULL) { const char *str_ptr; ret = pcre_get_substring((char *)ptr, ov, MAX_SUBSTRINGS, 1, &str_ptr); if (ret) { if (strcmp(pe->capname,"http_uri") == 0) { if (pmt->de_scanned_httpuri == 1) PacketPatternCleanup(t, pmt); pmt->de_have_httpuri = 1; pmt->de_scanned_httpuri = 0; p->http_uri.raw[pmt->pkt_cnt] = (u_int8_t *)str_ptr; p->http_uri.raw_size[pmt->pkt_cnt] = ret; p->http_uri.cnt = pmt->pkt_cnt; } else { FlowVarAdd(p->flow, pe->capname, (u_int8_t *)str_ptr, ret); } } } /* update ptrs for pcre RELATIVE */ pmt->pkt_ptr = ptr+ov[1]; pmt->pkt_off = (ptr+ov[1]) - p->tcp_payload; //printf("DetectPcre: post match: t->pkt_ptr %p t->pkt_off %u\n", t->pkt_ptr, t->pkt_off); ret = 1; } else { ret = 0; } //printf("DetectPcreMatch: ret %d\n", ret); return ret; } int DetectPcreSetup (Signature *s, SigMatch *m, char *regexstr) { const char *eb; int eo; int opts = 0; DetectPcreData *pd = NULL; SigMatch *sm = NULL; char *re = NULL, *op = NULL; char dubbed = 0; #define MAX_SUBSTRINGS 30 int ret = 0, res = 0; int ov[MAX_SUBSTRINGS]; const char *capture_str_ptr = NULL; //printf("DetectPcreSetup: \'%s\'\n", regexstr); ret = pcre_exec(parse_capture_regex, parse_capture_regex_study, regexstr, strlen(regexstr), 0, 0, ov, MAX_SUBSTRINGS); if (ret > 1) { res = pcre_get_substring((char *)regexstr, ov, MAX_SUBSTRINGS, 1, &capture_str_ptr); if (res < 0) { printf("DetectPcreSetup: pcre_get_substring failed\n"); return -1; } } //printf("DetectPcreSetup: \'%s\'\n", capture_str_ptr ? capture_str_ptr : "NULL"); ret = pcre_exec(parse_regex, parse_regex_study, regexstr, strlen(regexstr), 0, 0, ov, MAX_SUBSTRINGS); if (ret < 0) { goto error; } if (ret > 1) { const char *str_ptr; res = pcre_get_substring((char *)regexstr, ov, MAX_SUBSTRINGS, 1, &str_ptr); if (res < 0) { printf("DetectPcreSetup: pcre_get_substring failed\n"); return -1; } re = (char *)str_ptr; if (ret > 2) { res = pcre_get_substring((char *)regexstr, ov, MAX_SUBSTRINGS, 2, &str_ptr); if (res < 0) { printf("DetectPcreSetup: pcre_get_substring failed\n"); return -1; } op = (char *)str_ptr; } } //printf("ret %d re \'%s\', op \'%s\'\n", ret, re, op); pd = malloc(sizeof(DetectPcreData)); if (pd == NULL) { printf("DetectPcreSetup malloc failed\n"); goto error; } memset(pd, 0, sizeof(DetectPcreData)); pd->depth = 0; pd->flags = 0; if (capture_str_ptr != NULL) { pd->capname = strdup((char *)capture_str_ptr); } //printf("DetectPcreSetup: pd->capname %s\n", pd->capname ? pd->capname : "NULL"); if (op != NULL) { while (*op) { DEBUGPRINT("DetectPcreSetup: regex option %c", *op); switch (*op) { case 'A': opts |= PCRE_ANCHORED; break; case 'E': opts |= PCRE_DOLLAR_ENDONLY; break; case 'G': opts |= PCRE_UNGREEDY; break; case 'i': opts |= PCRE_CASELESS; break; case 'm': opts |= PCRE_MULTILINE; break; case 's': opts |= PCRE_DOTALL; break; case 'x': opts |= PCRE_EXTENDED; break; case 'B': /* snort's option */ pd->flags |= DETECT_PCRE_RAWBYTES; break; case 'R': /* snort's option */ pd->flags |= DETECT_PCRE_RELATIVE; break; case 'U': /* snort's option */ pd->flags |= DETECT_PCRE_URI; break; default: printf("DetectPcreSetup: unknown regex modifier '%c'\n", *op); break; } op++; } } //printf("DetectPcreSetup: \"%s\"\n", re); pd->re = pcre_compile(re, opts, &eb, &eo, NULL); if(pd->re == NULL) { printf("pcre compile of \"%s\" failed at offset %d: %s\n", regexstr, eo, eb); goto error; } pd->sd = pcre_study(pd->re, 0, &eb); if(eb != NULL) { printf("pcre study failed : %s\n", eb); goto error; } /* Okay so far so good, lets get this into a SigMatch * and put it in the Signature. */ sm = SigMatchAlloc(); if (sm == NULL) goto error; sm->type = DETECT_PCRE; sm->ctx = (void *)pd; SigMatchAppend(s,m,sm); if (dubbed) free(re); return 0; error: if (dubbed) free(re); if (pd) free(pd); if (sm) free(sm); return -1; }