Implement per packet variables and switch the http stuff to it.

remotes/origin/master-1.0.x
Victor Julien 17 years ago
parent edf8650a7e
commit c4f2fe4bd7

@ -16,6 +16,7 @@ flow-queue.c flow-queue.h \
flow-hash.c flow-hash.h \
flow-util.c flow-util.h \
flow-var.c flow-var.h \
pkt-var.c pkt-var.h \
host.c host.h \
detect.c detect.h \
detect-engine.c detect-engine.h \
@ -30,6 +31,7 @@ detect-parse.c detect-parse.h \
detect-content.c detect-content.h \
detect-uricontent.c detect-uricontent.h \
detect-flowvar.c detect-flowvar.h \
detect-pktvar.c detect-pktvar.h \
detect-pcre.c detect-pcre.h \
detect-depth.c detect-depth.h \
detect-nocase.c detect-nocase.h \

@ -170,6 +170,15 @@ typedef struct _HttpUri {
u_int8_t cnt;
} HttpUri;
typedef struct _PktVar {
char *name;
u_int8_t *value;
u_int16_t value_len;
struct _PktVar *next; /* right now just implement this as a list,
* in the long run we have thing of something
* faster. */
} PktVar;
typedef struct _Packet
{
/* Addresses, Ports and protocol
@ -214,6 +223,9 @@ typedef struct _Packet
struct _Flow *flow;
u_int8_t flowflags;
/* pkt vars */
PktVar *pktvar;
/* header pointers */
EthernetHdr *ethh;
@ -272,6 +284,8 @@ typedef struct _PacketQueue {
u_int16_t dbg_maxlen;
#endif /* DBG_PERF */
} PacketQueue;
/* clear key vars so we don't need to call the expensive
* memset or bzero
*/
@ -297,6 +311,8 @@ typedef struct _PacketQueue {
(p)->flowflags = 0; \
(p)->alerts.cnt = 0; \
(p)->http_uri.cnt = 0; \
PktVarFree((p)->pktvar); \
(p)->pktvar = NULL; \
}

@ -5,13 +5,15 @@
#include "debug.h"
#include "decode.h"
#include "detect.h"
#include "pkt-var.h"
#include "flow-var.h"
#include "detect-pcre.h"
#include "detect-engine-mpm.h"
#define PARSE_CAPTURE_REGEX "\\(\\?P\\<([A-z0-9_]+)\\>"
#define PARSE_CAPTURE_REGEX "\\(\\?P\\<([A-z]+)\\_([A-z0-9_]+)\\>"
#define PARSE_REGEX "(?<!\\\\)/(.*)(?<!\\\\)/([A-z]*)"
static pcre *parse_regex;
static pcre_extra *parse_regex_study;
@ -47,6 +49,7 @@ void DetectPcreRegister (void) {
goto error;
}
opts |= PCRE_UNGREEDY; /* pkt_http_ua should be pkt, http_ua, for this reason the UNGREEDY */
parse_capture_regex = pcre_compile(PARSE_CAPTURE_REGEX, opts, &eb, &eo, NULL);
if(parse_capture_regex == NULL)
{
@ -119,7 +122,11 @@ int DetectPcreMatch (ThreadVars *t, PatternMatcherThread *pmt, Packet *p, Signat
p->http_uri.raw_size[pmt->pkt_cnt] = ret;
p->http_uri.cnt = pmt->pkt_cnt + 1;
} else {
FlowVarAdd(p->flow, pe->capname, (u_int8_t *)str_ptr, ret);
if (pe->flags & DETECT_PCRE_CAPTURE_PKT) {
PktVarAdd(p, pe->capname, (u_int8_t *)str_ptr, ret);
} else if (pe->flags & DETECT_PCRE_CAPTURE_FLOW) {
FlowVarAdd(p->flow, pe->capname, (u_int8_t *)str_ptr, ret);
}
}
}
}
@ -150,19 +157,25 @@ int DetectPcreSetup (Signature *s, SigMatch *m, char *regexstr)
#define MAX_SUBSTRINGS 30
int ret = 0, res = 0;
int ov[MAX_SUBSTRINGS];
const char *capture_str_ptr = NULL;
const char *capture_str_ptr = NULL, *type_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);
res = pcre_get_substring((char *)regexstr, ov, MAX_SUBSTRINGS, 1, &type_str_ptr);
if (res < 0) {
printf("DetectPcreSetup: pcre_get_substring failed\n");
return -1;
}
res = pcre_get_substring((char *)regexstr, ov, MAX_SUBSTRINGS, 2, &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");
//printf("DetectPcreSetup: type \'%s\'\n", type_str_ptr ? type_str_ptr : "NULL");
//printf("DetectPcreSetup: capture \'%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) {
@ -202,6 +215,13 @@ int DetectPcreSetup (Signature *s, SigMatch *m, char *regexstr)
if (capture_str_ptr != NULL) {
pd->capname = strdup((char *)capture_str_ptr);
}
if (type_str_ptr != NULL) {
if (strcmp(type_str_ptr,"pkt") == 0) {
pd->flags |= DETECT_PCRE_CAPTURE_PKT;
} else if (strcmp(type_str_ptr,"flow") == 0) {
pd->flags |= DETECT_PCRE_CAPTURE_FLOW;
}
}
//printf("DetectPcreSetup: pd->capname %s\n", pd->capname ? pd->capname : "NULL");
if (op != NULL) {
@ -276,6 +296,7 @@ int DetectPcreSetup (Signature *s, SigMatch *m, char *regexstr)
SigMatchAppend(s,m,sm);
if (type_str_ptr != NULL) pcre_free((char *)type_str_ptr);
if (capture_str_ptr != NULL) pcre_free((char *)capture_str_ptr);
if (re != NULL) free(re);
if (op_ptr != NULL) free(op_ptr);

@ -1,15 +1,18 @@
#ifndef __DETECT_PCRE_H__
#define __DETECT_PCRE_H__
#define DETECT_PCRE_DISTANCE 0x01
#define DETECT_PCRE_WITHIN 0x02
#define DETECT_PCRE_RELATIVE 0x04
#define DETECT_PCRE_DISTANCE 0x0001
#define DETECT_PCRE_WITHIN 0x0002
#define DETECT_PCRE_RELATIVE 0x0004
#define DETECT_PCRE_DISTANCE_NEXT 0x08
#define DETECT_PCRE_WITHIN_NEXT 0x10
#define DETECT_PCRE_DISTANCE_NEXT 0x0008
#define DETECT_PCRE_WITHIN_NEXT 0x0010
#define DETECT_PCRE_RAWBYTES 0x20
#define DETECT_PCRE_URI 0x40
#define DETECT_PCRE_RAWBYTES 0x0020
#define DETECT_PCRE_URI 0x0040
#define DETECT_PCRE_CAPTURE_PKT 0x0080
#define DETECT_PCRE_CAPTURE_FLOW 0x0100
typedef struct _DetectPcreData {
/* pcre options */
@ -23,7 +26,7 @@ typedef struct _DetectPcreData {
int32_t within;
int32_t distance;
u_int8_t flags;
u_int16_t flags;
char *capname;
} DetectPcreData;

@ -0,0 +1,211 @@
/* Simple pktvar content match part of the detection engine.
*
* Copyright (C) 2008 by Victor Julien <victor@inliniac.net> */
#include <ctype.h>
#include <pcre.h>
#include "decode.h"
#include "detect.h"
#include "threads.h"
#include "pkt-var.h"
#include "detect-pktvar.h"
#include "util-binsearch.h"
#define PARSE_REGEX "(.*),(.*)"
static pcre *parse_regex;
static pcre_extra *parse_regex_study;
int DetectPktvarMatch (ThreadVars *, PatternMatcherThread *, Packet *, Signature *, SigMatch *);
int DetectPktvarSetup (Signature *, SigMatch *, char *);
void DetectPktvarRegister (void) {
sigmatch_table[DETECT_PKTVAR].name = "pktvar";
sigmatch_table[DETECT_PKTVAR].Match = DetectPktvarMatch;
sigmatch_table[DETECT_PKTVAR].Setup = DetectPktvarSetup;
sigmatch_table[DETECT_PKTVAR].Free = NULL;
sigmatch_table[DETECT_PKTVAR].RegisterTests = NULL;
const char *eb;
int eo;
int opts = 0;
parse_regex = pcre_compile(PARSE_REGEX, opts, &eb, &eo, NULL);
if(parse_regex == NULL)
{
printf("pcre compile of \"%s\" failed at offset %d: %s\n", PARSE_REGEX, eo, eb);
goto error;
}
parse_regex_study = pcre_study(parse_regex, 0, &eb);
if(eb != NULL)
{
printf("pcre study failed: %s\n", eb);
goto error;
}
return;
error:
return;
}
/*
* returns 0: no match
* 1: match
* -1: error
*/
int DetectPktvarMatch (ThreadVars *t, PatternMatcherThread *pmt, Packet *p, Signature *s, SigMatch *m)
{
int ret = 0;
DetectPktvarData *pd = (DetectPktvarData *)m->ctx;
PktVar *pv = PktVarGet(p, pd->name);
if (pv != NULL) {
u_int8_t *ptr = BinSearch(pv->value, pv->value_len, pd->content, pd->content_len);
if (ptr != NULL)
ret = 1;
}
return ret;
}
int DetectPktvarSetup (Signature *s, SigMatch *m, char *rawstr)
{
DetectPktvarData *cd = NULL;
SigMatch *sm = NULL;
char *str = rawstr;
char dubbed = 0;
u_int16_t len;
char *varname = NULL, *varcontent = NULL;
#define MAX_SUBSTRINGS 30
int ret = 0, res = 0;
int ov[MAX_SUBSTRINGS];
ret = pcre_exec(parse_regex, parse_regex_study, rawstr, strlen(rawstr), 0, 0, ov, MAX_SUBSTRINGS);
if (ret > 1) {
const char *str_ptr;
res = pcre_get_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 1, &str_ptr);
if (res < 0) {
printf("DetectPcreSetup: pcre_get_substring failed\n");
return -1;
}
varname = (char *)str_ptr;
if (ret > 2) {
res = pcre_get_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 2, &str_ptr);
if (res < 0) {
printf("DetectPcreSetup: pcre_get_substring failed\n");
return -1;
}
varcontent = (char *)str_ptr;
}
}
printf("DetectPktvarSetup: varname %s, varcontent %s\n", varname, varcontent);
if (varcontent[0] == '\"' && varcontent[strlen(varcontent)-1] == '\"') {
str = strdup(varcontent+1);
str[strlen(varcontent)-2] = '\0';
dubbed = 1;
}
len = strlen(str);
if (len == 0)
return -1;
cd = malloc(sizeof(DetectPktvarData));
if (cd == NULL) {
printf("DetectPktvarSetup malloc failed\n");
goto error;
}
char converted = 0;
{
u_int16_t i, x;
u_int8_t bin = 0, binstr[3] = "", binpos = 0;
for (i = 0, x = 0; i < len; i++) {
// printf("str[%02u]: %c\n", i, str[i]);
if (str[i] == '|') {
if (bin) {
bin = 0;
} else {
bin = 1;
}
} else {
if (bin) {
if (isdigit(str[i]) ||
str[i] == 'A' || str[i] == 'a' ||
str[i] == 'B' || str[i] == 'b' ||
str[i] == 'C' || str[i] == 'c' ||
str[i] == 'D' || str[i] == 'd' ||
str[i] == 'E' || str[i] == 'e' ||
str[i] == 'F' || str[i] == 'f') {
// printf("part of binary: %c\n", str[i]);
binstr[binpos] = (char)str[i];
binpos++;
if (binpos == 2) {
u_int8_t c = strtol((char *)binstr, (char **) NULL, 16) & 0xFF;
#ifdef DEBUG
printf("Binstr %X\n", c);
#endif
binpos = 0;
str[x] = c;
x++;
converted = 1;
}
} else if (str[i] == ' ') {
// printf("space as part of binary string\n");
}
} else {
str[x] = str[i];
x++;
}
}
}
//#ifdef DEBUG
for (i = 0; i < x; i++) {
if (isprint(str[i])) printf("%c", str[i]);
else printf("\\x%02u", str[i]);
}
printf("\n");
//#endif
if (converted)
len = x;
}
cd->content = malloc(len);
if (cd->content == NULL)
return -1;
cd->name = strdup(varname);
memcpy(cd->content, str, len);
cd->content_len = len;
cd->flags = 0;
/* 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_FLOWVAR;
sm->ctx = (void *)cd;
SigMatchAppend(s,m,sm);
if (dubbed) free(str);
return 0;
error:
if (dubbed) free(str);
if (cd) free(cd);
if (sm) free(sm);
return -1;
}

@ -0,0 +1,17 @@
#ifndef __DETECT_PKTVAR_H__
#define __DETECT_PKTVAR_H__
#define DETECT_CONTENT_NOCASE 0x01
typedef struct _DetectPktvarData {
char *name;
u_int8_t *content;
u_int8_t content_len;
u_int8_t flags;
} DetectPktvarData;
/* prototypes */
void DetectPktvarRegister (void);
#endif /* __DETECT_PKTVAR_H__ */

@ -37,6 +37,7 @@
#include "detect-flow.h"
#include "detect-dsize.h"
#include "detect-flowvar.h"
#include "detect-pktvar.h"
#include "detect-noalert.h"
#include "action-globals.h"
@ -76,21 +77,21 @@ void SigLoadSignatures (void)
/* The next 3 rules handle HTTP header capture. */
/* http_uri -- for uricontent */
sig = SigInit("alert tcp any any -> any $HTTP_PORTS (msg:\"HTTP URI cap\"; flow:to_server; content:\"GET \"; depth:4; pcre:\"/^GET (?P<http_uri>.*) HTTP\\/\\d\\.\\d\\r\\n/G\"; noalert; sid:1;)");
sig = SigInit("alert tcp any any -> any $HTTP_PORTS (msg:\"HTTP URI cap\"; flow:to_server; content:\"GET \"; depth:4; pcre:\"/^GET (?P<pkt_http_uri>.*) HTTP\\/\\d\\.\\d\\r\\n/G\"; noalert; sid:1;)");
if (sig) {
prevsig = sig;
g_de_ctx->sig_list = sig;
}
/* http_host -- for the log-httplog module */
sig = SigInit("alert tcp any any -> any $HTTP_PORTS (msg:\"HTTP host cap\"; flow:to_server; content:\"Host:\"; pcre:\"/^Host: (?P<http_host>.*)\\r\\n/m\"; noalert; sid:2;)");
sig = SigInit("alert tcp any any -> any $HTTP_PORTS (msg:\"HTTP host cap\"; flow:to_server; content:\"Host:\"; pcre:\"/^Host: (?P<pkt_http_host>.*)\\r\\n/m\"; noalert; sid:2;)");
if (sig == NULL)
return;
prevsig->next = sig;
prevsig = sig;
/* http_ua -- for the log-httplog module */
sig = SigInit("alert tcp any any -> any $HTTP_PORTS (msg:\"HTTP UA cap\"; flow:to_server; content:\"User-Agent:\"; pcre:\"/^User-Agent: (?P<http_ua>.*)\\r\\n/m\"; noalert; sid:3;)");
sig = SigInit("alert tcp any any -> any $HTTP_PORTS (msg:\"HTTP UA cap\"; flow:to_server; content:\"User-Agent:\"; pcre:\"/^User-Agent: (?P<pkt_http_ua>.*)\\r\\n/m\"; noalert; sid:3;)");
if (sig == NULL)
return;
prevsig->next = sig;
@ -740,7 +741,7 @@ static DetectAddressGroup *GetHeadPtr(DetectAddressGroupsHead *head, int family)
return grhead;
}
#define MAX_UNIQ_GROUPS 5
#define MAX_UNIQ_GROUPS 8
/* set unique_groups to 0 for no grouping.
*
@ -2279,6 +2280,7 @@ void SigTableSetup(void) {
DetectFlowRegister();
DetectDsizeRegister();
DetectFlowvarRegister();
DetectPktvarRegister();
DetectNoalertRegister();
u_int8_t i = 0;

@ -215,6 +215,7 @@ enum {
DETECT_FLOW,
DETECT_DSIZE,
DETECT_FLOWVAR,
DETECT_PKTVAR,
DETECT_NOALERT,
DETECT_ADDRESS,

@ -18,8 +18,7 @@
#include "vips.h"
#include "debug.h"
#include "detect.h"
#include "flow.h"
#include "flow-var.h"
#include "pkt-var.h"
#include "threadvars.h"
#include "tm-modules.h"
@ -78,33 +77,29 @@ int LogHttplogIPv4(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq)
LogHttplogThread *aft = (LogHttplogThread *)data;
int i;
char timebuf[64], hostname[256] = "unknown", ua[256] = "unknown";
FlowVar *fv;
PktVar *pv;
u_int16_t size;
/* XXX add a better check for this */
if (p->http_uri.cnt == 0)
return 0;
/* we need a lock */
mutex_lock(&p->flow->m);
fv = FlowVarGet(p->flow, "http_host");
if (fv != NULL) {
size = fv->value_len;
pv = PktVarGet(p, "http_host");
if (pv != NULL) {
size = pv->value_len;
if (size >= sizeof(hostname))
size = sizeof(hostname) - 1;
strncpy(hostname,(char *)fv->value,size);
strncpy(hostname,(char *)pv->value,size);
}
fv = FlowVarGet(p->flow, "http_ua");
if (fv != NULL) {
size = fv->value_len;
pv = PktVarGet(p, "http_ua");
if (pv != NULL) {
size = pv->value_len;
if (size >= sizeof(ua))
size = sizeof(ua) - 1;
strncpy(ua,(char *)fv->value,size);
strncpy(ua,(char *)pv->value,size);
}
mutex_unlock(&p->flow->m);
CreateTimeString(&p->ts, timebuf, sizeof(timebuf));
@ -125,33 +120,29 @@ int LogHttplogIPv6(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq)
LogHttplogThread *aft = (LogHttplogThread *)data;
int i;
char timebuf[64], hostname[256] = "unknown", ua[256] = "unknown";
FlowVar *fv;
PktVar *pv;
u_int16_t size;
/* XXX add a better check for this */
if (p->http_uri.cnt == 0)
return 0;
/* we need a lock */
mutex_lock(&p->flow->m);
fv = FlowVarGet(p->flow, "http_host");
if (fv != NULL) {
size = fv->value_len;
pv = PktVarGet(p, "http_host");
if (pv != NULL) {
size = pv->value_len;
if (size >= sizeof(hostname))
size = sizeof(hostname) - 1;
strncpy(hostname,(char *)fv->value,size);
strncpy(hostname,(char *)pv->value,size);
}
fv = FlowVarGet(p->flow, "http_ua");
if (fv != NULL) {
size = fv->value_len;
pv = PktVarGet(p, "http_ua");
if (pv != NULL) {
size = pv->value_len;
if (size >= sizeof(ua))
size = sizeof(ua) - 1;
strncpy(ua,(char *)fv->value,size);
strncpy(ua,(char *)pv->value,size);
}
mutex_unlock(&p->flow->m);
CreateTimeString(&p->ts, timebuf, sizeof(timebuf));

@ -0,0 +1,93 @@
/* implement per packet vars */
/* TODO
* - move away from a linked list implementation
* - use different datatypes, such as string, int, etc.
* - have more than one instance of the same var, and be able to match on a
* specific one, or one all at a time. So if a certain capture matches
* multiple times, we can operate on all of them.
*/
#include <ctype.h>
#include "decode.h"
#include "pkt-var.h"
/* puts a new value into a pktvar */
void PktVarUpdate(PktVar *pv, u_int8_t *value, u_int16_t size) {
if (pv->value) free(pv->value);
pv->value = value;
pv->value_len = size;
}
/* get the pktvar with name 'name' from the pkt
*
* name is a normal string*/
PktVar *PktVarGet(Packet *p, char *name) {
PktVar *pv = p->pktvar;
for (;pv != NULL; pv = pv->next) {
if (pv->name && strcmp(pv->name, name) == 0)
return pv;
}
return NULL;
}
/* add a pktvar to the pkt, or update it */
void PktVarAdd(Packet *p, char *name, u_int8_t *value, u_int16_t size) {
//printf("Adding packet var \"%s\" with value(%d) \"%s\"\n", name, size, value);
PktVar *pv = PktVarGet(p, name);
if (pv == NULL) {
pv = malloc(sizeof(PktVar));
if (pv == NULL)
return;
pv->name = name;
pv->value = value;
pv->value_len = size;
pv->next = NULL;
PktVar *tpv = p->pktvar;
if (p->pktvar == NULL) p->pktvar = pv;
else {
while(tpv) {
if (tpv->next == NULL) {
tpv->next = pv;
return;
}
tpv = tpv->next;
}
}
} else {
PktVarUpdate(pv, value, size);
}
}
void PktVarFree(PktVar *pv) {
if (pv == NULL)
return;
pv->name = NULL;
if (pv->value) free(pv->value);
if (pv->next) PktVarFree(pv->next);
}
void PktVarPrint(PktVar *pv) {
u_int16_t i;
if (pv == NULL)
return;
printf("Name \"%s\", Value \"", pv->name);
for (i = 0; i < pv->value_len; i++) {
if (isprint(pv->value[i])) printf("%c", pv->value[i]);
else printf("\\%02X", pv->value[i]);
}
printf("\", Len \"%u\"\n", pv->value_len);
PktVarPrint(pv->next);
}

@ -0,0 +1,11 @@
/* Copyright (c) 2008 Victor Julien <victor@inliniac.net> */
#ifndef __PKT_VAR_H__
#define __PKT_VAR_H__
void PktVarAdd(Packet *, char *, u_int8_t *, u_int16_t);
PktVar *PktVarGet(Packet *, char *);
void PktVarFree(PktVar *);
void PktVarPrint(PktVar *);
#endif /* __PKT_VAR_H__ */
Loading…
Cancel
Save