Project

General

Profile

Feature #478 » u2-test-patchv2.diff

Ignacio Sanchez, 09/28/2012 08:32 AM

View differences:

src/alert-unified2-alert.c
*
* \author Breno Silva <breno.silva@gmail.com>
* \author Eric Leblond <eric@regit.org>
* \author Ignacio Sanchez <sanchezmartin.ji@gmail.com>
*
* Logs alerts in a format compatible to Snort's unified2 format, so it should
* be readable by Barnyard2.
* Experimental support for XFF extradata records.
*/
#include "suricata-common.h"
......
#include "threadvars.h"
#include "tm-threads.h"
#include "util-unittest.h"
#include "alert-unified2-alert.h"
#include "decode-ipv4.h"
......
#include "util-byte.h"
#include "util-misc.h"
#include "app-layer-htp.h"
#include "app-layer.h"
#include "output.h"
#include "alert-unified2-alert.h"
#include "util-privs.h"
......
} Unified2AlertFileHeader;
/**
* Unified2 Extra Data Header
*
*/
typedef struct _Unified2ExtraDataHdr{
uint32_t event_type;
uint32_t event_length;
} Unified2ExtraDataHdr;
/**
* Unified2 Extra Data (currently used only for XFF)
*
*/
typedef struct _Unified2ExtraData{
uint32_t sensor_id;
uint32_t event_id;
uint32_t event_second;
uint32_t type; /* EventInfo */
uint32_t data_type; /*EventDataType */
uint32_t blob_length; /* Length of the data + sizeof(blob_length) + sizeof(data_type)*/
} Unified2ExtraData;
/**
* Unified2 Ipv4 struct
*
* Used for storing ipv4 type values.
......
uint8_t packet_data[4]; /**< packet data */
} Unified2Packet;
#define ALERT_UNIFIED2ALERT_XFF 1
#define ALERT_UNIFIED2ALERT_XFF_OVERWRITE 2
#define ALERT_UNIFIED2ALERT_XFF_DEFAULT "X-Forwarded-For"
#define ALERT_UNIFIED2ALERT_XFF_MINLEN 7
typedef struct Unified2AlertFileCtx_ {
LogFileCtx *file_ctx;
uint32_t flags; /** Store mode */
char *xff_header; /** XFF Header name in case XFF mode is enabled */
} Unified2AlertFileCtx;
/**
* Unified2 thread vars
*
* Used for storing file options.
*/
typedef struct Unified2AlertThread_ {
LogFileCtx *file_ctx; /**< LogFileCtx pointer */
Unified2AlertFileCtx *unified2alert_ctx; /**< LogFileCtx pointer */
uint8_t *data; /**< Per function and thread data */
/** Pointer to the Unified2AlertFileHeader contained in
* the pointer data. */
......
*/
int Unified2AlertCloseFile(ThreadVars *t, Unified2AlertThread *aun) {
if (aun->file_ctx->fp != NULL) {
fclose(aun->file_ctx->fp);
if (aun->unified2alert_ctx->file_ctx->fp != NULL) {
fclose(aun->unified2alert_ctx->file_ctx->fp);
}
aun->file_ctx->size_current = 0;
aun->unified2alert_ctx->file_ctx->size_current = 0;
return 0;
}
......
"Error: Unified2AlertCloseFile failed");
return -1;
}
if (Unified2AlertOpenFileCtx(aun->file_ctx,aun->file_ctx->prefix) < 0) {
if (Unified2AlertOpenFileCtx(aun->unified2alert_ctx->file_ctx,aun->unified2alert_ctx->
file_ctx->prefix) < 0) {
SCLogError(SC_ERR_UNIFIED2_ALERT_GENERIC,
"Error: Unified2AlertOpenFileCtx, open new log file failed");
return -1;
......
{
int ret;
ret = fwrite(aun->data, aun->length, 1, aun->file_ctx->fp);
ret = fwrite(aun->data, aun->length, 1, aun->unified2alert_ctx->file_ctx->fp);
if (ret != 1) {
SCLogError(SC_ERR_FWRITE, "Error: fwrite failed: %s", strerror(errno));
return -1;
}
aun->file_ctx->size_current += aun->length;
aun->unified2alert_ctx->file_ctx->size_current += aun->length;
return 1;
}
/**
* \brief Function to return XFF IP if any...
* \retval 1 if the IP has been foudn and returned in dstbuf
* \retval 0 if the IP has not being found or error
*/
int GetXFFIP ( Packet *p, Unified2AlertThread *aun, char *dstbuf ){
char xffip[128];
if (aun->unified2alert_ctx->flags & ALERT_UNIFIED2ALERT_XFF) {
HtpState *htp_state = NULL;
htp_tx_t *tx = NULL;
htp_header_t *h_xff = NULL;
char *p_xff = NULL;
size_t idx = 0;
size_t hsize = 0;
if (p->flow && AppLayerGetProtoFromPacket(p) == ALPROTO_HTTP) {
htp_state = (HtpState *) AppLayerGetProtoStateFromPacket(p);
if ( htp_state && htp_state->connp && htp_state->connp->conn) {
hsize = list_size(htp_state->connp->conn->transactions);
for (idx = 0; idx < hsize; idx++) {
tx = list_get(htp_state->connp->conn->transactions, idx);
if (tx != NULL && tx->request_headers != NULL) {
h_xff = table_getc(tx->request_headers, aun->unified2alert_ctx->xff_header);
if (h_xff != NULL && bstr_len(h_xff->value) > ALERT_UNIFIED2ALERT_XFF_MINLEN - 1
&& bstr_len(h_xff->value) < 120) {
strlcpy(xffip, bstr_ptr(h_xff->value), bstr_len(h_xff->value) + 1);
/* Check for chained ips separated by ", ", we will get the last one */
p_xff = strrchr(xffip, ' ');
if (p_xff == NULL) {
p_xff = xffip;
} else {
p_xff++;
}
/* Sanity check on extracted IP */
if (strlen(p_xff) > ALERT_UNIFIED2ALERT_XFF_MINLEN - 1 &&
strlen(p_xff) < 43 ) {
strlcpy(dstbuf, p_xff, 42);
return 1; // OK
}
}
}
}
}
}
}
return 0; // Not found
}
/**
* \brief Unified2 main entry function
*
* \retval TM_ECODE_OK all is good
......
Unified2AlertThread *aun = (Unified2AlertThread *)data;
Unified2AlertFileHeader *hdr = (Unified2AlertFileHeader*)(aun->data);
Unified2Packet *phdr = (Unified2Packet *)(hdr + 1);
/* Prepare the pointers to extradata structures should they are required */
/* If they are required we will shift the *hdr and the *phdr */
Unified2AlertFileHeader *eu2hdr = (Unified2AlertFileHeader*)(aun->data);
Unified2ExtraDataHdr *ehdr = (Unified2ExtraDataHdr *)(eu2hdr + 1);
Unified2ExtraData *dhdr = (Unified2ExtraData *) (ehdr + 1);
uint32_t *edxff = (uint32_t *) (dhdr + 1);
aun->length = 0;
aun->offset = 0;
char ipbuf[128];
// If XFF in non overwrite mode...
if ((aun->unified2alert_ctx->flags & ALERT_UNIFIED2ALERT_XFF) &&
(aun->unified2alert_ctx->flags & ALERT_UNIFIED2ALERT_XFF_OVERWRITE) == 0 ) {
if ( GetXFFIP (p, aun, ipbuf) == 1 ) {
in_addr_t xffip;
if ( inet_pton(AF_INET, ipbuf, &(xffip) ) == 1 ) {
memset(dhdr, 0, sizeof(Unified2ExtraData));
eu2hdr->type = htonl (110);
eu2hdr->length = htonl(sizeof (Unified2ExtraDataHdr)
+ sizeof (Unified2ExtraData) + 4);
ehdr->event_type = htonl(4); // Extra hdr
ehdr->event_length = htonl(sizeof (Unified2ExtraDataHdr)
+ sizeof (Unified2ExtraData) + 4);
dhdr->sensor_id = 0;
dhdr->event_id = aun->event_id;
dhdr->event_second = htonl(p->ts.tv_sec);
dhdr->data_type = htonl(1);
dhdr->type = htonl(1);
dhdr->blob_length = htonl(12);
aun->length += sizeof(Unified2AlertFileHeader) + sizeof (Unified2ExtraDataHdr)
+ sizeof (Unified2ExtraData) + 4;
aun->offset += sizeof(Unified2AlertFileHeader) + sizeof (Unified2ExtraDataHdr)
+ sizeof (Unified2ExtraData) + 4;
*edxff=xffip;
//memcpy(aun->data + (aun->offset - 4), &xffip_net, 4);
/* Shift the *hdr and *phdr pointers */
hdr = (Unified2AlertFileHeader*)(edxff + 1);
phdr = (Unified2Packet *)(hdr + 1);
}
}
}
int ethh_offset = 0;
EthernetHdr ethhdr = { {0,0,0,0,0,0}, {0,0,0,0,0,0}, htons(ETHERNET_TYPE_IPV6) };
uint32_t hdr_length = 0;
......
datalink = DLT_RAW;
}
aun->length = sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE;
aun->offset = sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE;
aun->length += sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE;
aun->offset += sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE;
/* Include Packet header */
if (PKT_IS_IPV4(p)) {
......
SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread data");
goto error;
}
// If XFF in overwrite mode...
if (aun->unified2alert_ctx->flags & ALERT_UNIFIED2ALERT_XFF_OVERWRITE) {
if ( GetXFFIP (p, aun, ipbuf) == 1 ) {
in_addr_t xffip;
if ( inet_pton(AF_INET, ipbuf, &(xffip) ) == 1 ) {
fakehdr.ip4h.s_ip_src.s_addr = xffip;
}
}
}
memcpy(aun->data + aun->offset, &fakehdr, hdr_length);
aun->iphdr = (void *)(aun->data + aun->offset);
aun->offset += hdr_length;
} else if (PKT_IS_IPV6(p)) {
} else if (PKT_IS_IPV6(p)) {
FakeIPv6Hdr fakehdr;
hdr_length = sizeof(FakeIPv6Hdr);
......
SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread data");
goto error;
}
if (aun->unified2alert_ctx->flags & ALERT_UNIFIED2ALERT_XFF_OVERWRITE) {
if ( GetXFFIP (p, aun, ipbuf) == 1 ) {
uint32_t xffip6[4];
if ( inet_pton(AF_INET6, ipbuf, xffip6 ) == 1 ) {
memcpy(fakehdr.ip6h.s_ip6_src, xffip6, 16);
}
}
}
memcpy(aun->data + aun->offset, &fakehdr, hdr_length);
aun->iphdr = (void *)(aun->data + aun->offset);
aun->offset += hdr_length;
......
gphdr.event_second = htonl(p->ts.tv_sec);
gphdr.event_microsecond = htonl(p->ts.tv_usec);
gphdr.src_ip = *(struct in6_addr*)GET_IPV6_SRC_ADDR(p);
gphdr.dst_ip = *(struct in6_addr*)GET_IPV6_DST_ADDR(p);
gphdr.dst_ip = *(struct in6_addr*)GET_IPV6_DST_ADDR(p);
gphdr.protocol = p->proto;
if(p->action & ACTION_DROP)
......
phdr->classification_id = htonl(pa->s->class);
phdr->priority_id = htonl(pa->s->prio);
SCMutexLock(&aun->file_ctx->fp_mutex);
if ((aun->file_ctx->size_current + length) > aun->file_ctx->size_limit) {
SCMutexLock(&aun->unified2alert_ctx->file_ctx->fp_mutex);
if ((aun->unified2alert_ctx->file_ctx->size_current + length)
> aun->unified2alert_ctx->file_ctx->size_limit) {
if (Unified2AlertRotateFile(t,aun) < 0) {
aun->file_ctx->alerts += i;
SCMutexUnlock(&aun->file_ctx->fp_mutex);
aun->unified2alert_ctx->file_ctx->alerts += i;
SCMutexUnlock(&aun->unified2alert_ctx->file_ctx->fp_mutex);
return -1;
}
}
if (Unified2Write(aun) != 1) {
aun->file_ctx->alerts += i;
SCMutexUnlock(&aun->file_ctx->fp_mutex);
aun->unified2alert_ctx->file_ctx->alerts += i;
SCMutexUnlock(&aun->unified2alert_ctx->file_ctx->fp_mutex);
return -1;
}
......
pa->flags & (PACKET_ALERT_FLAG_STATE_MATCH|PACKET_ALERT_FLAG_STREAM_MATCH) ? 1 : 0);
if (ret != 1) {
SCLogError(SC_ERR_FWRITE, "Error: fwrite failed: %s", strerror(errno));
aun->file_ctx->alerts += i;
SCMutexUnlock(&aun->file_ctx->fp_mutex);
aun->unified2alert_ctx->file_ctx->alerts += i;
SCMutexUnlock(&aun->unified2alert_ctx->file_ctx->fp_mutex);
return -1;
}
fflush(aun->file_ctx->fp);
aun->file_ctx->alerts++;
SCMutexUnlock(&aun->file_ctx->fp_mutex);
fflush(aun->unified2alert_ctx->file_ctx->fp);
aun->unified2alert_ctx->file_ctx->alerts++;
SCMutexUnlock(&aun->unified2alert_ctx->file_ctx->fp_mutex);
}
return 0;
......
gphdr.event_microsecond = htonl(p->ts.tv_usec);
gphdr.src_ip = p->ip4h->s_ip_src.s_addr;
gphdr.dst_ip = p->ip4h->s_ip_dst.s_addr;
// If XFF in overwrite mode...
if (aun->unified2alert_ctx->flags & ALERT_UNIFIED2ALERT_XFF_OVERWRITE) {
char ipbuf[128];
if ( GetXFFIP (p, aun, ipbuf) == 1 ) {
in_addr_t xffip;
if ( inet_pton(AF_INET, ipbuf, &(xffip) ) == 1 ) {
if (p->flowflags & FLOW_PKT_TOCLIENT) {
gphdr.dst_ip = xffip;
} else {
gphdr.src_ip = xffip;
}
}
}
}
gphdr.protocol = IPV4_GET_RAW_IPPROTO(p->ip4h);
if(p->action & ACTION_DROP)
......
phdr->priority_id = htonl(pa->s->prio);
/* check and enforce the filesize limit */
SCMutexLock(&aun->file_ctx->fp_mutex);
SCMutexLock(&aun->unified2alert_ctx->file_ctx->fp_mutex);
if ((aun->file_ctx->size_current + length) > aun->file_ctx->size_limit) {
if ((aun->unified2alert_ctx->file_ctx->size_current + length)
> aun->unified2alert_ctx->file_ctx->size_limit) {
if (Unified2AlertRotateFile(tv,aun) < 0) {
aun->file_ctx->alerts += i;
SCMutexUnlock(&aun->file_ctx->fp_mutex);
aun->unified2alert_ctx->file_ctx->alerts += i;
SCMutexUnlock(&aun->unified2alert_ctx->file_ctx->fp_mutex);
return -1;
}
}
if (Unified2Write(aun) != 1) {
aun->file_ctx->alerts += i;
SCMutexUnlock(&aun->file_ctx->fp_mutex);
aun->unified2alert_ctx->file_ctx->alerts += i;
SCMutexUnlock(&aun->unified2alert_ctx->file_ctx->fp_mutex);
return -1;
}
......
ret = Unified2PacketTypeAlert(aun, p, event_id,
pa->flags & (PACKET_ALERT_FLAG_STATE_MATCH|PACKET_ALERT_FLAG_STREAM_MATCH) ? 1 : 0);
if (ret != 1) {
aun->file_ctx->alerts += i;
SCMutexUnlock(&aun->file_ctx->fp_mutex);
aun->unified2alert_ctx->file_ctx->alerts += i;
SCMutexUnlock(&aun->unified2alert_ctx->file_ctx->fp_mutex);
return -1;
}
fflush(aun->file_ctx->fp);
aun->file_ctx->alerts++;
SCMutexUnlock(&aun->file_ctx->fp_mutex);
fflush(aun->unified2alert_ctx->file_ctx->fp);
aun->unified2alert_ctx->file_ctx->alerts++;
SCMutexUnlock(&aun->unified2alert_ctx->file_ctx->fp_mutex);
}
return 0;
......
return TM_ECODE_FAILED;
}
/** Use the Ouptut Context (file pointer and mutex) */
aun->file_ctx = ((OutputCtx *)initdata)->data;
aun->unified2alert_ctx = ((OutputCtx *)initdata)->data;
aun->data = SCMalloc(sizeof(Unified2AlertFileHeader) + sizeof(Unified2Packet) + IPV4_MAXPACKET_LEN);
aun->data = SCMalloc(sizeof(Unified2AlertFileHeader) + sizeof(Unified2Packet) +
IPV4_MAXPACKET_LEN + sizeof(Unified2ExtraDataHdr) + sizeof (Unified2ExtraData));
if (aun->data == NULL) {
SCFree(aun);
return TM_ECODE_FAILED;
}
aun->datalen = sizeof(Unified2AlertFileHeader) + sizeof(Unified2Packet) + IPV4_MAXPACKET_LEN;
aun->datalen = sizeof(Unified2AlertFileHeader) + sizeof(Unified2Packet) +
IPV4_MAXPACKET_LEN + sizeof(Unified2ExtraDataHdr) + sizeof (Unified2ExtraData);
*data = (void *)aun;
......
goto error;
}
if (!(aun->file_ctx->flags & LOGFILE_ALERTS_PRINTED)) {
if (!(aun->unified2alert_ctx->file_ctx->flags & LOGFILE_ALERTS_PRINTED)) {
SCLogInfo("Alert unified2 module wrote %"PRIu64" alerts",
aun->file_ctx->alerts);
aun->unified2alert_ctx->file_ctx->alerts);
/* Do not print it for each thread */
aun->file_ctx->flags |= LOGFILE_ALERTS_PRINTED;
aun->unified2alert_ctx->file_ctx->flags |= LOGFILE_ALERTS_PRINTED;
}
......
{
int ret = 0;
LogFileCtx* file_ctx = NULL;
OutputCtx* output_ctx = NULL;
file_ctx = LogFileNewCtx();
if (file_ctx == NULL) {
SCLogError(SC_ERR_UNIFIED2_ALERT_GENERIC, "Couldn't create new file_ctx");
......
if (ret < 0)
goto error;
OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx));
output_ctx = SCCalloc(1, sizeof(OutputCtx));
if (output_ctx == NULL)
goto error;
output_ctx->data = file_ctx;
Unified2AlertFileCtx *unified2alert_ctx = SCMalloc(sizeof(Unified2AlertFileCtx));
if (unified2alert_ctx == NULL) {
goto error;
}
memset(unified2alert_ctx, 0x00, sizeof(Unified2AlertFileCtx));
unified2alert_ctx->file_ctx = file_ctx;
output_ctx->data = unified2alert_ctx;
output_ctx->DeInit = Unified2AlertDeInitCtx;
const char *xff = ConfNodeLookupChildValue(conf, "xff");
const char *xff_header = ConfNodeLookupChildValue(conf, "xffheadername");
const char *xff_overwrite = ConfNodeLookupChildValue(conf, "xffoverwrite");
if (xff != NULL && ConfValIsTrue(xff)) {
unified2alert_ctx->flags |= ALERT_UNIFIED2ALERT_XFF;
if (xff_header != NULL) {
unified2alert_ctx->xff_header = (char *) xff_header;
} else {
unified2alert_ctx->xff_header = ALERT_UNIFIED2ALERT_XFF_DEFAULT;
}
if (xff_overwrite != NULL && ConfValIsTrue(xff_overwrite)) {
unified2alert_ctx->flags |= ALERT_UNIFIED2ALERT_XFF_OVERWRITE;
}
}
SCLogInfo("Unified2-alert initialized: filename %s, limit %"PRIu64" MB",
filename, file_ctx->size_limit / (1024*1024));
......
return output_ctx;
error:
if (output_ctx != NULL) {
SCFree(output_ctx);
}
if (file_ctx != NULL) {
LogFileFreeCtx(file_ctx);
}
......
static void Unified2AlertDeInitCtx(OutputCtx *output_ctx)
{
if (output_ctx != NULL) {
LogFileCtx *logfile_ctx = (LogFileCtx *)output_ctx->data;
if (logfile_ctx != NULL) {
LogFileFreeCtx(logfile_ctx);
Unified2AlertFileCtx *unified2alert_ctx = (Unified2AlertFileCtx *) output_ctx->data;
if (unified2alert_ctx != NULL) {
LogFileCtx *logfile_ctx = unified2alert_ctx->file_ctx;
if (logfile_ctx != NULL) {
LogFileFreeCtx(logfile_ctx);
}
SCFree(unified2alert_ctx);
}
SCFree(output_ctx);
}
(7-7/7)